summaryrefslogtreecommitdiff
path: root/helpers
diff options
context:
space:
mode:
authorGeorge Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2023-03-12 07:16:23 +0200
committerGeorge Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2023-03-12 07:16:23 +0200
commit7076343338ae3439f3c86f01144818abe8c31978 (patch)
tree794abb1e6b8f821091fd095341885496b6dad51d /helpers
parent47cbb529f5723b246125ae083a193e11481b89ef (diff)
downloadclassroom-7076343338ae3439f3c86f01144818abe8c31978.tar.gz
classroom-7076343338ae3439f3c86f01144818abe8c31978.tar.bz2
classroom-7076343338ae3439f3c86f01144818abe8c31978.zip
add container helpers; constuct public directory-tree
Diffstat (limited to 'helpers')
-rw-r--r--helpers/autoload.php43
-rw-r--r--helpers/design_patterns.php104
-rw-r--r--helpers/error_handling.php119
-rw-r--r--helpers/render.php338
4 files changed, 0 insertions, 604 deletions
diff --git a/helpers/autoload.php b/helpers/autoload.php
deleted file mode 100644
index c4359c6..0000000
--- a/helpers/autoload.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-/** register class-autoloader
- *
- * NOTE:
- * Composer is strongly recommended; it is a much better option
- * and takes care for many more than just autoloading classes;
- *
- * This's a fair autoloader in case composer is not available;
- * supports single and namespaced classes.
- */
-spl_autoload_register(
- function($className) {
-
- // in order to support common namespaced classes
- // replace '\' with '/' to get the path
- $classPath = str_replace('\\', DIRECTORY_SEPARATOR, $className);
-
- // check all possible classPaths for class
- foreach(CLASSPATHS as $key => $basePath) {
-
- $file = APP_ROOT . $basePath . $classPath .'.php';
-
- // if class-file exist, include it
- if (file_exists($file)) {
- require_once $file;
- break;
- }
-
- }
-
- // // Feel free to extend the fanctionality
- // // example:
- // // custom (exception) namespaced classes loader
- // $customNSclasses = array(
- // '\\George\\Class' => 'path/to/George/Class',
- // '\\Mary\\Class' => 'path/to/Marias/Class',
- // ...
- // );
- // if array_key_exists($className) {
- // require_once $customNSclasses[$className];
- // }
- }
-);
diff --git a/helpers/design_patterns.php b/helpers/design_patterns.php
deleted file mode 100644
index d66ffa9..0000000
--- a/helpers/design_patterns.php
+++ /dev/null
@@ -1,104 +0,0 @@
-<?php
-/** proxy
- * implements the proxy design pattern
- *
- * uses: Registry::cache
- *
- * algorithm:
- * - 1: proxy gets (Class::method, Arguments) and calculates a unique key
- * - 2: if a valid Cache for the triplete's key exists, it is served immediately
- * - 3: otherwise calls Class::Method(Arguments), caches then serves response
- *
- * @param $class_method (array): a 2 (string) items array in the form
- * : [ 'fully\qualifies\ClassName' , 'methodName' ]
- * : Using the ClassName::class notation is strongly recommended.
- * @param $args: array of arguments (passed to the Class::Method())
- * @param $ttl: time (in sec) where the data will remain valid (not expired)
- * @param $options: bitwise flags*
- * ---
- * @return $data (mixed)
- *
- * (*) option flags
- * all option flags represend non default behaviour of proxy
- * ---
- * PROXY_CACHE_ERRORS : cache value even if callback returns error
- * PROXY_IGNORE_CACHE : ignore if cache exist; get result from callback
- * PROXY_DO_NOT_CACHE : do not cache the result (even if from callback)
- */
-function proxy(array $callable, array $args, int $ttl, int $options=0)
-{
- // resolve option flags
- $cache_errors = ($options&PROXY_CACHE_ERRORS) ? true : false;
- $ignore_cache = ($options&PROXY_IGNORE_CACHE) ? true : false;
- $do_not_cache = ($options&PROXY_DO_NOT_CACHE) ? true : false;
-
- // we're gonna use cache;
- $cache = Registry::use('cache');
-
-
- // check validity of callable argument
- // -------------------------------------------------------------------------
- if ((!is_callable($callable)) || (!is_array($callable))) {
-
- throw new Exception(
- 'Proxy\'s first parameter has to be a callable array [fully\\qualified\\ClassName, method], passed:'.print_r($callable, true)
- );
-
- }
-
- // create a unique key
- // -------------------------------------------------------------------------
- list($class, $method) = $callable;
- $key = sha1(
- $class .':'. $method .':'. json_encode(
- $args, JSON_UNESCAPED_LINE_TERMINATORS|JSON_UNESCAPED_UNICODE
- )
- );
-
- // search cache if data for this key exist
- // -------------------------------------------------------------------------
- if (!$ignore_cache) {
- $data = $cache->get($key);
-
- } else { $data = false; } // ignore cache? pass false
-
-
- if ($data !== false) { // if exists, serve cached data
-
- // if cashed data exist
- // ---------------------------------------------------------------------
- # if (!PRODUCTION) Benchmark::add_spot('proxy-cached');
- if ($data == '_ERROR_') return false; // previous cached error
- else return $data; // previous cache ()
-
-
- } else { // else (not exist)...
-
- // no data on cache -> get data from Class::method( arguments )
- // ---------------------------------------------------------------------
- $data = call_user_func_array($callable, $args);
-
- // handle newly created data
- // ---------------------------------------------------------------------
-
- // if faulty data, return false
- if ($data == false) {
-
- if ($cache_errors && !$do_not_cache) { // cache the error
- $cache->set($key, '_ERROR_', $ttl);
- }
-
- # if (!PRODUCTION) Benchmark::add_spot('proxy-new-error');
- return false;
- }
-
- // store to cache
- if (!$do_not_cache) {
- $cache->set($key, $data, $ttl);
- }
-
- # if (!PRODUCTION) Benchmark::add_spot('proxy-new');
- return $data; // serve data
- }
-
-}
diff --git a/helpers/error_handling.php b/helpers/error_handling.php
deleted file mode 100644
index bc60968..0000000
--- a/helpers/error_handling.php
+++ /dev/null
@@ -1,119 +0,0 @@
-<?php
-/** ERROR HANDLING SECTION
- * handles exceptions and errors (even fatal)
- * -----------------------------------------------------------------------------
- * The code...
- * + Catches and handles all Errors and Throwable exceptions;
- * - creates the error messages (for the requester and developer)
- * ? TODO: routes the error messages to the logging channels
- */
-
-
-// Global array to save errors
-$anom_ERRORS = []; // ok, Globals are not recommended, but...
- // this one collects only errors (about the application);
- // it is oriented for the developer; not for the request.
-
-
-/** Error handler,
- * passes flow over the exception logger with new ErrorException.
- */
-function handle_error(int $type, string $message, string $file, int $line)
-{
- handle_exception( new ErrorException($message, 0, $type, $file, $line) );
-}
-
-
-/** Uncaught exception handler.
-*/
-function handle_exception(Throwable $e)
-{
- global $anom_ERRORS;
-
- // full message description to be logged
- $message = get_class($e) .": ". $e->getMessage()
- . " on file '". $e->getFile() . "' at line {$e->getLine()}";
-
- $anom_ERRORS[] = $message; // store the error
-}
-
-
-/**
- * Catch fatal error work-around
- * (set_error_handler not working on fatal errors).
- */
-function on_shutdown_check_for_fatal()
-{
- global $anom_ERRORS;
-
- $error = error_get_last();
-
- if ($error != null) { // ignore 'normal' system shutdowns [exit|die]()
-
- if ( $error["type"] == E_ERROR ) { // get as much error-info
- handle_error(
- $error["type"] ?? -1,
- $error["message"] ?? 'unknown error',
- $error["file"] ?? 'unknown file',
- $error["line"] ?? -1
- );
- }
- }
-
- if (($anom_ERRORS != [])) {
-
- // TODO:
- // Implemetnig the design/layout of the error-messages
- // output should not be an error's-handling task, thus
- // shall be assigned to the Rendes/View level;
- // Same about the log service channels
-
- // TODO:
- // FORWARD ERRORS into LOG-SYSTEM
- // ex. into some file...
- // file_put_contents("logs/thowable.log", $message_template .PHP_EOL, FILE_APPEND);
- // or ...some other channer (Email, Slack, Database etc).
- // Channes can be decided according to error severity;
- // a file-system error loggin for backup is recommended
- // partitioniong of errors onto file-system can be useful
-
- // TODO:
- // 1st: Log Errors
- // 2nd: Show Errors
-
- if (PRODUCTION) {
- if (!defined('VIEW_LOADED')) {
- // throw a prety-error message
- render_view('error/general', ['message' => 'Please forgive me, I know not what I do']);
- }
-
- } else {
-
- if (!defined('VIEW_LOADED')) {
- // no template loaded; render erros in general-error template
- render_view('error/general', ['message' => implode("<br/>And:<br/>", $anom_ERRORS)]);
-
- } else {
- echo '<div style="padding:1em;background:#933;width:100%;color:#fff">
- Errors:<br />'. implode("<br/>And:<br/>", $anom_ERRORS) .'</div>';
- }
- }
- }
-}
-
-
-// register callback on shutdown
-register_shutdown_function( "on_shutdown_check_for_fatal" );
-
-// register custom error handler callback
-set_error_handler( "handle_error" );
-
-// set custom exception handler function
-set_exception_handler( "handle_exception" );
-
-// send errors to stderr (instead of stdout)
-ini_set( "display_errors", "off" );
-
-// thow out all errors
-error_reporting( E_ALL );
-
diff --git a/helpers/render.php b/helpers/render.php
deleted file mode 100644
index 9dcd34a..0000000
--- a/helpers/render.php
+++ /dev/null
@@ -1,338 +0,0 @@
-<?php
-/** Rendering System
- * ---
- * this is the View part of the MVC framework.
- * Decided not to make it a Class
- ***/
-
-
-/** load template
- * ---
- * TODO:
- * explain/document the difference between a template and a view
- *
- * TODO:
- * Implementing the Render/View operation as a class, using the same-
- * name methods with Laraver or CodeIgniter could be good idea;
- * and get rid of if(!defined('VIEW_LOADED')) define('VIEW_LOADED',1);
- */
-function load_template($template, $data) {
-
- $file = VIEWS_DIRECTORY . $template . '.php';
-
- if (file_exists($file)) {
- if (!defined('VIEW_LOADED')) define('VIEW_LOADED', 1);
-
- ob_start();
-
- extract( sanitize_output($data) );
- require( $file );
-
- ob_flush();
-
- } else if (!PRODUCTION) {
-
- echo "<!-- view ". $file ." is missing -->";
- }
-
-}
-
-/** parse_sections
- * ---
- * parse a group of views (sections)
- * @param $sections: an array of sections
- *
- * each section group is an array with view, key and data properties
- * + view: defines the view template/file
- * + key: the variable name that view uses to parse data OR empty-string*
- * * if key is an empty then $data should be an array (which
- * includes all [variable-name:data] pairs utilized by the view)
- * + data: holds the actual data
- */
-
-function parse_sections($sections) {
-
- foreach($sections as $sect) {
-
- if ($sect['key'] == '') {
- render_view( $sect['view'], $sect['data'] );
-
- } else {
- render_view( $sect['view'], [ $sect['key'] => $sect['data']] );
- }
- }
-}
-
-
-/** render function
- * ---
- * uses php's short-tag syntax for templating system
- * extract data into template
- * @param $view: view-template filename
- * @param $data: data to embed into view-template
- * @param $sanitize: of true then sanitize data.
- * important NOTE: data is an array [key => value]
- */
-function render_view($view, $data, $sanitize = false) {
-
- $file = VIEWS_DIRECTORY . $view . '.php';
-
- if (file_exists($file)) {
- if (!defined('VIEW_LOADED')) define('VIEW_LOADED', 1);
-
- extract( $sanitize ? sanitize_output($data) : $data );
- require( $file );
-
- } else if (!PRODUCTION) {
-
- echo "<!-- view ". $file ." is missing -->";
- }
-
-}
-
-
-/** render asap
- * ---
- * render_view then output code
- * so that client will get html to render
- * while server calculates next html
- */
-function render_asap($view, $data, $sanitize = false) {
- render_view($view, $data, $sanitize);
- ob_flush();
-}
-
-
-/** render text
- * ---
- * This function simply echoes text
- * with Content-Type and Cache Headers
- * @param $data : the text to echo
- * @param $cType : Content-Type header
- * @param $ttl : cache-contol headers; if false response is not-cached; else (int) chache for $ttl seconds
- */
-function render_text( $data, $contentType = 'text/html; charset=UTF-8', $ttl = false ) {
- header('Content-Type: '. $contentType);
- if ($ttl) {
- $ts = gmdate("D, d M Y H:i:s", time() + $ttl) . " GMT";
- header("Expires: {$ts}");
- header("Pragma: cache");
- header("Cache-Control: max-age={$ttl}");
-
- } else {
- $ts = gmdate("D, d M Y H:i:s") . " GMT";
- header("Expires: {$ts}");
- header("Last-Modified: {$ts}");
- header("Pragma: no-cache");
- header("Cache-Control: no-cache, must-revalidate");
- }
- echo htmlspecialchars($data);
-}
-
-
-/** reply_json
- * ---
- * transform a php-array to json and echo to client
- * Can be used for API calls
- *
- * @param $data : the php array)
- * @param $ttl : cache-contol headers; if false response is not-cached; else chache for $ttl seconds
- */
-function reply_json( $data, $ttl = false ) {
- header('Content-Type: application/json');
- if ($ttl) {
- $ts = gmdate("D, d M Y H:i:s", time() + $ttl) . " GMT";
- header("Expires: {$ts}");
- header("Pragma: cache");
- header("Cache-Control: max-age={$ttl}");
-
- } else {
- $ts = gmdate("D, d M Y H:i:s") . " GMT";
- header("Expires: {$ts}");
- header("Last-Modified: {$ts}");
- header("Pragma: no-cache");
- header("Cache-Control: no-cache, must-revalidate");
- }
- echo json_encode($data, JSON_UNESCAPED_UNICODE);
-}
-
-
-
-
-// HELPER FUNCTIONS
-// -----------------------------------------------------------------------------
-
-
-/** link asset
- * ---
- * the function defines the assets (css or js)
- * to be loaded on the client (creates the HTML)
- * @param $type : type of asset [css|js]
- * @param $assetIDs : an array of ('assetID' => 'paramaters')
- *
- * example calls:
- * load_asset('css', ['main' => 'media="all"', 'filters' => 'media="all"']);
- * load_asset( 'js', ['jquery' => '', 'lazyloader' => 'async']);
- */
-function link_asset( $type, $assetIDs, $paramatres = '' ) {
-
- $code = ""; // code to return
-
- // make sure $assetIDs is array (for coding simplicity)
- if (!is_array($assetIDs)) {
- $assetIDs = [ $assetIDs ];
- }
-
- // check asset type and construct all asset inserts
- switch ($type) {
-
- case 'font':
- foreach($assetIDs as $asset) {
- $code .= "\n\t<link href='". FONTS_DIR . FONT_FILES[$asset] ."' as='font' type='font/woff2' {$paramatres}/>";
- }
- break;
-
- case 'js':
- foreach($assetIDs as $asset) {
- $code .= "\n\t<script src='". JS_DIR . JS_LIBRARIES[$asset] ."' id='{$asset}' {$paramatres}></script>";
- }
- break;
-
- case 'css':
- default:
- foreach($assetIDs as $asset) {
- $code .= "\n\t<link rel='stylesheet' href='". CSS_DIR . CSS_FILES[$asset] ."' id='{$asset}' {$paramatres} />";
- }
- }
-
- echo $code;
-}
-
-
-/** sanitize_output (recursive)
- * ---
- * Sanitizes data that are about to rendered
- * (usually when render_view() is called).
- * NOTE: mitigates XSS attachs
- * @param $data: (array)
- */
-function sanitize_output($data) {
- //// // check https://stackoverflow.com/questions/2002710/php-how-to-perform-htmlspecialchar-on-an-array-of-arrays
-
- //// $output = array_map("myFunc", $data);
- global $secure;
-
- $output = array();
- foreach($data as $key => $val) {
-
- if (is_string($val)) {
- $output[$key] = htmlspecialchars(remove_invisible_characters($val));
-
- } else if (is_array($val)) {
- $output[$key] = sanitize_output($val);
-
- } else {
- $output[$key] = $val;
- }
- }
- return $output;
-}
-
-
-/** remove_invisible_characters()
- * ---
- * @used by sanitize_output()
- */
-function remove_invisible_characters($str, $url_encoded = TRUE)
-{
- $non_displayables = array();
-
- // every control character except newline (dec 10),
- // carriage return (dec 13) and horizontal tab (dec 09)
- if ($url_encoded) {
- $non_displayables[] = '/%0[0-8bcef]/i'; // url encoded 00-08, 11, 12, 14, 15
- $non_displayables[] = '/%1[0-9a-f]/i'; // url encoded 16-31
- $non_displayables[] = '/%7f/i'; // url encoded 127
- }
-
- $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'; // 00-08, 11, 12, 14-31, 127
-
- do {
- $str = preg_replace($non_displayables, '', $str, -1, $count);
- } while ($count);
-
- return $str;
-}
-
-
-/** html
- * ---
- * outputs code as html
- *
- * @param $str (string)
- * @return html5 (string)
- */
-function html($str) {
- if (!isset($str) || $str== null) return;
- if (($str == '') || is_numeric($str)) return $str;
- return htmlspecialchars_decode($str, ENT_QUOTES|ENT_HTML5);
-}
-
-
-/** set_headers
- * ---
- * set custom response-Headers
- *
- * @param $contentType
- * @param $ttl: int or false)
- * @param $more: array of (content-type => content-value) pairs
- */
-function set_headers($contentType = 'text/html; charset=UTF-8', $ttl = false, $more = [] ) {
-
- // handle common content-type shorcuts
- switch ($contentType) {
- case 'text':
- case 'html':
- $contentType = 'text/html; charset=UTF-8';
- break;
- case 'json':
- $contentType = 'application/json; charset=utf-8';
- break;
- case 'js':
- $contentType = 'application/javascript; charset=utf-8';
- break;
- case 'css':
- $contentType = 'text/css';
- break;
- default:
- // $contentType stays as-is
- break;
- }
-
- // send headers
- header('Content-Type: '. $contentType);
- if ($ttl) {
- $ts = gmdate("D, d M Y H:i:s", time() + $ttl) . " GMT";
- header("Expires: {$ts}");
- header("Pragma: cache");
- header("Cache-Control: max-age={$ttl}");
-
- } else {
- $ts = gmdate("D, d M Y H:i:s") . " GMT";
- header("Expires: {$ts}");
- header("Last-Modified: {$ts}");
- header("Pragma: no-cache");
- header("Cache-Control: no-cache, must-revalidate");
- }
-
- // send more headers
- if ($more != []) {
- foreach($more as $header => $value) {
- header($header .': '. $value);
- }
- }
-
-}
-
-
-