summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorGeorge Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2023-03-26 04:50:46 +0300
committerGeorge Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2023-03-26 04:50:46 +0300
commit21fedb3af692b12c1f0aa266bbf788b01f2cbe4c (patch)
treee600e16a2894407eba840e7694a4f290669e31d8 /core
parentd90b51ce89bcc693e3014b313fe8e3b975031adf (diff)
downloadclassroom-21fedb3af692b12c1f0aa266bbf788b01f2cbe4c.tar.gz
classroom-21fedb3af692b12c1f0aa266bbf788b01f2cbe4c.tar.bz2
classroom-21fedb3af692b12c1f0aa266bbf788b01f2cbe4c.zip
auth tests
Diffstat (limited to 'core')
-rw-r--r--core/classes/Render.php343
-rw-r--r--core/classes/session/DefaultSession.php9
-rw-r--r--core/classes/session/FilesSession.php20
-rw-r--r--core/config/anom_settings.php312
-rw-r--r--core/config/credentials.php126
-rw-r--r--core/config/init.php17
-rw-r--r--core/helpers/error_handling.php8
-rw-r--r--core/helpers/render.php338
8 files changed, 602 insertions, 571 deletions
diff --git a/core/classes/Render.php b/core/classes/Render.php
new file mode 100644
index 0000000..401178d
--- /dev/null
+++ b/core/classes/Render.php
@@ -0,0 +1,343 @@
+<?php
+/** Rendering System
+ *
+ * this is the View part of the anom MVC framework
+ ***/
+
+ Class Render {
+
+ /** 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('OUTPUT_STARTED')) define('OUTPUT_STARTED',1);
+ */
+ public static function template($template, $data) {
+
+ $file = VIEWS_DIRECTORY . $template . '.php';
+
+ if (file_exists($file)) {
+ if (!defined('OUTPUT_STARTED')) define('OUTPUT_STARTED', 1);
+
+ ob_start();
+
+ extract( self::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
+ */
+
+ public static function sections($sections) {
+
+ foreach($sections as $sect) {
+
+ if ($sect['key'] == '') {
+ self::view( $sect['view'], $sect['data'] );
+
+ } else {
+ self::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]
+ */
+ public static function view($view, $data=[], $sanitize = false) {
+
+ $file = VIEWS_DIRECTORY . $view . '.php';
+
+ if (file_exists($file)) {
+ if (!defined('OUTPUT_STARTED')) define('OUTPUT_STARTED', 1);
+
+ extract( $sanitize ? self::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
+ */
+ public static function asap($view, $data, $sanitize = false) {
+ self::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
+ */
+ public static function 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
+ */
+ public static function 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']);
+ */
+ public static function 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)
+ */
+ public static 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(self::remove_invisible_characters($val));
+
+ } else if (is_array($val)) {
+ $output[$key] = self::sanitize_output($val);
+
+ } else {
+ $output[$key] = $val;
+ }
+ }
+ return $output;
+ }
+
+
+ /** remove_invisible_characters()
+ * ---
+ * @used by sanitize_output()
+ */
+ public static 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)
+ */
+ public static 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
+ */
+ public static 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);
+ }
+ }
+
+ }
+
+
+
+} \ No newline at end of file
diff --git a/core/classes/session/DefaultSession.php b/core/classes/session/DefaultSession.php
index d3099a5..079ab9d 100644
--- a/core/classes/session/DefaultSession.php
+++ b/core/classes/session/DefaultSession.php
@@ -2,14 +2,19 @@
/** DefauleSession
* --
+ *
* is a dummy session hanlder that wraps the
* php's default session engine implementation;
+ *
*/
class DefaultSession implements SessionHandlerInterface {
public function __construct()
{
// Start the session
+ // (the default way)
+ // and let the session* functions
+ // do what they know
session_name(SESSION_NAME);
session_start();
}
@@ -21,7 +26,9 @@ class DefaultSession implements SessionHandlerInterface {
public function close() {}
#[ReturnTypeWillChange]
- public function read(string $id) {}
+ public function read(string $id) {
+
+ }
#[ReturnTypeWillChange]
public function write(string $id, string $data) {}
diff --git a/core/classes/session/FilesSession.php b/core/classes/session/FilesSession.php
index 8762776..a06f29c 100644
--- a/core/classes/session/FilesSession.php
+++ b/core/classes/session/FilesSession.php
@@ -35,6 +35,7 @@ class FileSessionHandler implements SessionHandlerInterface
public function __construct()
{
// values comming from configuration
+ $this->sessionName = SESSION_NAME;
$this->sess_filename = $path;
$this->minutes = $minutes;
@@ -49,7 +50,7 @@ class FileSessionHandler implements SessionHandlerInterface
);
// Start the session
- session_name(SESSION_NAME);
+ session_name($this->sessionName);
session_start();
}
@@ -80,14 +81,9 @@ class FileSessionHandler implements SessionHandlerInterface
public function read($sessionId): string|false
{
if (!file_exists($filename) || !is_readable($filename)) return false;
- return file_get_contents($filename);
+ $data = file_get_contents($filename);
- # if ($this->files->isFile($path = $this->path.'/'.$sessionId) &&
- # $this->files->lastModified($path) >= Carbon::now()->subMinutes($this->minutes)->getTimestamp()) {
- # return $this->files->sharedGet($path);
- # }
-
- # depricated? return '';
+ return @unserialize($data);
}
/** write
@@ -96,11 +92,11 @@ class FileSessionHandler implements SessionHandlerInterface
public function write($sessionId, $data): bool
{
$h = fopen($filename, 'w');
- if (fwrite($h,$data) === false) {
+ if (fwrite($h, serialize($data)) === false) {
throw new Exception('Could not write session data');
return false;
- }
- fclose($h);
+ }
+ fclose($h);
return true;
}
@@ -128,7 +124,7 @@ class FileSessionHandler implements SessionHandlerInterface
->in($this->path)
->files()
->ignoreDotFiles(true)
- ->date('<= now - '.$lifetime.' seconds');
+ ->date('<= now - '. $lifetime .' seconds');
$deletedSessions = 0;
diff --git a/core/config/anom_settings.php b/core/config/anom_settings.php
index 406c6aa..76c7c62 100644
--- a/core/config/anom_settings.php
+++ b/core/config/anom_settings.php
@@ -1,35 +1,37 @@
<?php
+
/** CONFIGURATION PATAMETRES
- * ---
+ * -----------------------------------------------------------------------------
* This is the first file you need to setup
* in order to start a new application
+ *
+ * NOTE:
+ * You may rewrite the defines manualy setting any values manualy
+ * Here we propose that you use an .env file (with is a very safe option)
+ * the env file is saved into `/core/auth` folder
*/
+if (file_exists("../core/auth/.env")) {
+ $ini_array = parse_ini_file("../core/auth/.env");
+}
+
// DEFINE WHETTHER THE APP RUNS ON PRODUCTION
// Don't forget to change this setting
// when deploying to a different stage
// -----------------------------------------------------------------------------
-// define by OS parameter
-//// if (getenv('ENVIRONMENT')) {
-//// if (getenv('ENVIRONMENT') == 'PRODUCTION') {
-////
-//// define('PRODUCTION', true);
-////
-//// } else {
-//// define('PRODUCTION', false);
-//// }
-//// }
-//// // define by .env file
-//// if (!defined('PRODUCTION')) {
-//// if (file_exists('../core/auth/.env')) {
-//// $ini_array = parse_ini_file("../core/auth/.env");
-////
-//// define('PRODUCTION', $ini_array['ENVIRONMENT']);
-//// }
-//// } else {
-//// define('PRODUCTION', false); // or define manualy
-//// }
-define('PRODUCTION', false);
+
+# // define by OS parameter
+# if (getenv('ENVIRONMENT')) {
+# if (getenv('ENVIRONMENT') == 'PRODUCTION') {
+# define('PRODUCTION', true);
+# } else {
+# define('PRODUCTION', false);
+# }
+# }
+
+# define by .env file
+define('PRODUCTION', ($ini_array['ENVIRONMENT'] == 'production') );
+
// Custom Names ////////////////////////////////////////////////////////////////
@@ -43,15 +45,17 @@ define('SESSION_NAME', 'clroom'); // Session Name
-// APPLICATION PATHS ///////////////////////////////////////////////////////////
-// -----------------------------------------------------------------------------
-
-// Obligarory
-// These are needed in order to run the bare minimum MVC system
-// They also make code easier to read
-//
-// NOTE: probably you don't need to chage these defines
-// -----------------------------------------------------------------------------
+/** APPLICATION PATHS ///////////////////////////////////////////////////////////
+ * -----------------------------------------------------------------------------
+ *
+ * Obligarory
+ * These are needed in order to run the bare minimum MVC system
+ * They also make code easier to read
+ *
+ * NOTE:
+ * probably you don't need to chage these defines
+ * -----------------------------------------------------------------------------
+ */
define('APP_ROOT', dirname(get_included_files()[0]) );
@@ -68,22 +72,28 @@ define('VIEWS_DIRECTORY', APP_ROOT.'/app/views/');
define('TESTS_DIRECTORY', APP_ROOT."/../tests/");
-// AUTOLOADER //////////////////////////////////////////////////////////////////
-// -----------------------------------------------------------------------------
-
-// An autoloader for classes is required;
-// OPTION 1: COMPOSER
-// Composer is recommended and makes much more than simple autoloding
+/** AUTOLOADER /////////////////////////////////////////////////////////////////
+ * -----------------------------------------------------------------------------
+ * An autoloader for classes is required;
+ *
+ *
+ * OPTION 1: COMPOSER
+ * Composer is recommended and makes much more than simple autoloding
+ */
define('AUTOLOADER' , '../vendor/autoload.php');
-// OPTION 2: Custom Autoloader
-// If Composer is not supported, another autoloading proccess required
-// Comment/Disable the 1st option and uncomment/Enable the next line
+/** ...
+ *
+ * OPTION 2: Custom Autoloader
+ * If Composer is not supported, another autoloading proccess required
+ * Comment/Disable the 1st option and uncomment/Enable the next line
+ */
# define('AUTOLOADER' , '../core/helpers/autoload.php');
-// CLASSPATHS : array of paths where classes are saved
-// Needed only when the custom autoloader is used
-// (like autoload.classmap section of Composer)
+/** CLASSPATHS : array of paths where classes are saved
+ * Needed only when the custom autoloader is used
+ * (like autoload.classmap section of Composer)
+ */
# define('CLASSPATHS', array(
# '/../core/classes/',
# '/app/controllers/',
@@ -94,27 +104,45 @@ define('AUTOLOADER' , '../vendor/autoload.php');
-// ADVANCED OPTIMIZATION ///////////////////////////////////////////////////////
-// -----------------------------------------------------------------------------
-
-// APP_CACHE defines the cache-driver;
-// accepted values are the name of the Cache-interface impementations (the exact
-// names of the classes)
-//
-// 'FileCache' : caching in filesystem; fair if caching on HDD; great on SSD
-// 'RedisCache' : caching in Redis server; generally recommended if available
-// 'MemCachedCache' : caching in Memcached server; recommended if available
-//
-// NOTE: FileCache on a NVMe SDD is the fastest option;
-// Redis and Memcached are really-fast caching options and are available for
-// scaling horizontaly your application (eache one has it's own strngths;
-// study, then choose the one that fulfills your needs;
-// -----------------------------------------------------------------------------
+ /** SESSION HANDLING //////////////////////////////////////////////////////////
+ * ----------------------------------------------------------------------------
+ *
+ * there are several session drivers for session handling:
+ *
+ * 'DefaultSession' : uses the default (file-based) php session management
+ * 'FileSession' : defines a custom file-based session mechanism
+ * 'DatabaseSession' : mechanism that stores Session data into a DataBase
+ * ----------------------------------------------------------------------------
+ */
+
+define('SESSION_DRIVER', 'DefaultSession');
+
+
+
+/* ADVANCED OPTIMIZATION ///////////////////////////////////////////////////////
+ * -----------------------------------------------------------------------------
+ *
+ * APP_CACHE defines the cache-driver;
+ * accepted values are the name of the Cache-interface impementations (the exact
+ * names of the classes)
+ *
+ * 'FileCache' : caching in filesystem; fair if caching on HDD; great on SSD
+ * 'RedisCache' : caching in Redis server; generally recommended if available
+ * 'MemCachedCache' : caching in Memcached server; recommended if available
+ *
+ * NOTE: FileCache on a NVMe SDD is the fastest option;
+ * Redis and Memcached are really-fast caching options and are available for
+ * scaling horizontaly your application (eache one has it's own strngths;
+ * study, then choose the one that fulfills your needs;
+ * -----------------------------------------------------------------------------
+ */
define('CACHE_DRIVER', 'FileCache');
-// Caching expiration times fpr various expensive objects
-// -----------------------------------------------------------------------------
+
+/** Caching expiration times fpr various expensive objects
+ * -----------------------------------------------------------------------------
+ */
// Root objects like product-categories tree
define('CACHE_ROOT_TTL', 28800); // 8 hours
@@ -126,17 +154,11 @@ define('CACHE_CATEGORY_TTL', 18000); // 5 hours
define('CACHE_PRODUCT_TTL', 3600); // 1 hour
-// SESSION_DRIVER ; accepted values...
-// 'files' : (defult) php uses filesystem for saving session; fair if caching in SSD drive
-// 'redis' : keep sessions in a Redis server; rapid-fast but wastes large amount of RAM
-// 'database' : keep session data in Database; ideal for session across multiple servers
-// -----------------------------------------------------------------------------
-define('SESSION_DRIVER', 'files');
// CONNECTIONS ...
-define('FILECACHE_PATH', APP_ROOT.'/cache/'); // if CACHE_DRIVER is set to 'FileCache'
+define('FILECACHE_PATH', APP_ROOT.'/cache/'); // if CACHE_DRIVER is set to 'FileCache'
# define('REDIS_HOST', '127.0.0.1'); // if CACHE_DRIVER is set to 'RedisCache'
@@ -144,16 +166,16 @@ define('FILECACHE_PATH', APP_ROOT.'/cache/'); // if CACHE_DRIVER is set to 'Fi
-
-// SECURITY SETTINGS ///////////////////////////////////////////////////////////
-// -----------------------------------------------------------------------------
-
-// Cross Site Request Forgery
-// ---
-// Enables a CSRF cookie token to be set. When set to TRUE, token will be
-// checked on a submitted form. If you are accepting user data, it is strongly
-// recommended CSRF protection be enabled.
-// -----------------------------------------------------------------------------
+/** SECURITY SETTINGS ///////////////////////////////////////////////////////////
+ * -----------------------------------------------------------------------------
+ *
+ * Cross Site Request Forgery
+ * ---
+ * Enables a CSRF cookie token to be set. When set to TRUE, token will be
+ * checked on a submitted form. If you are accepting user data, it is strongly
+ * recommended CSRF protection be enabled.
+ * -----------------------------------------------------------------------------
+ */
define('CSRF_PROTCTION', false);
@@ -166,3 +188,137 @@ define('CSRF_EXPIRE', 7200); // The number in seconds the token shoul
define('CSRF_REGENERATE', TRUE); // Regenerate token on every submission
define('CSRF_EXCLUDE_URIS', array()); // Array of URIs which ignore CSRF checks
+
+
+
+
+/** CREDENTIALS
+ * -----------------------------------------------------------------------------
+ */
+
+/** SERVICE PARAMETRES
+ * -----------------------------------------------------------------------------
+ *
+ * Connection parametres and credentials for accssing services
+ * needed by the application; Such services may be..
+ *
+ * - RDBMS
+ * -- MySQL
+ * -- PotgresSQL
+ *
+ * - Caching services
+ * -- Redis
+ * -- MemCached
+ *
+ * Edit only the constants needed by the application;
+ * Comment those you do not need;
+ *
+ * /////////////////////////////////////////////////////////////////////////////
+ */
+
+/** DATABASE CONNECTION PARAMETRES
+ * -----------------------------------------------------------------------------
+ * Production and staging environments may use different databases.
+ *
+ * A safe practice is to keep credentials outside plain files like this one
+ * in environmental variable or other secret file etc.
+ *
+ * Uncomment/enable each group of definitions suits your case to define
+ * the credentials needed for accessing the database
+ */
+
+/** This is a SAFE method (define credentials as OS environmental variables)
+ * -----------------------------------------------------------------------------
+ */
+# define('DB_NAME', getenv('DB_NAME')); // database name
+#
+# define('DB_USER', getenv('DB_USER')); // database user-name
+#
+# define('DB_PASS', getenv('DB_PASS')); // user's pass
+#
+# define('PDO_HOST', getenv('PDO_HOST')); // database host (connection string)
+
+
+/** This is another SAFE method (keep credentials in an .env file)
+ * -----------------------------------------------------------------------------
+ */
+
+ $ini_array = parse_ini_file("../core/auth/.env");
+
+ define('DB_NAME', $ini_array['DB_NAME']);
+
+ define('DB_USER', $ini_array['DB_USER']);
+
+ define('DB_PASS', $ini_array['DB_PASS']);
+
+ define('PDO_HOST', $ini_array['PDO_HOST']);
+
+
+ /** This is just good enough
+ * -----------------------------------------------------------------------------
+ */
+
+ # if (!PRODUCTION) { // == Deployed on staging
+ #
+ # // STAGING SETTINGS:
+ #
+ # define('DB_NAME', 'dev_db_name');
+ #
+ # define('DB_USER', 'devUserName');
+ #
+ # define('DB_PASS', getenv('DBPASSWORD'));
+ #
+ # // PDO_HOST can be a hostname/port combination -or- a unix socket
+ # // ...examples:
+ # // define('PDO_HOST', 'host=/localhost') ## hostname case
+ # // define('PDO_HOST', 'host=/localhost;port=3456') ## hostname/port case
+ # // define('PDO_HOST', 'unix_socket=/sql/ex123:europe:some-db'); ## unix socket
+ # define('PDO_HOST', 'unix_socket=/cloudsql/name-123456:europe-west4:name-db-eu');
+ #
+ # } else { // == Deployed on production
+ #
+ # // PRODUCTION SETTINGS:
+ #
+ # define('DB_NAME', 'your_db_name');
+ # define('DB_USER', 'dbusername');
+ # define('DB_PASS', getenv('DBPASSWORD'));
+ # define('PDO_HOST', 'unix_socket=/cloudsql/name-123456:europe-west4:name-db-eu');
+ #
+ # }
+
+ define('DB_TIMEZONE', "SET time_zone = 'Europe/Athens'");
+
+ /** NOTE:
+ * Both Redis and Memcached configurations are given as a template to work on;
+ * In most cases the default values should do the job -- of course you need to
+ * read the README file (check the project's root);
+ * As these caching services are not fully tested you may need to ochestrate
+ * the services in detail or edit the connection strings into the core classes
+ * (hosted under the '/core/classes/cacher' folder)
+ */
+
+
+ /** REDIS SERVICE
+ * -----------------------------------------------------------------------------
+ * Most of the times Redis is running on 'localhost' (host = '127.0.0.1')
+ * When implemented via anom's docker-composer (redis via bridge) then you need
+ * do declare the hostname as 'redis'
+ */
+ #
+ # if (!defined('REDIS_HOST')) define('REDIS_HOST', 'redis');
+ #
+ # if (!defined('REDIS_PORT')) define('REDIS_PORT', 6379);
+ #
+ # if (!defined('REDIS_PASS')) define('REDIS_PASS', null);
+
+
+ /** MEMCACHED
+ * -----------------------------------------------------------------------------
+ * Memcached looks very much like Redis (plus, both are serving from RAM)
+ * Usualy Memcashed is running localy so host is 'localhost' ('127.0.0.1')
+ * If you use the framework's docker-composer implementation then
+ * the hostname is 'anomemcached'
+ */
+ #
+ #if (!defined('MEMCACHE_HOST')) define('MEMCACHE_HOST', 'anomemcached');
+ \ No newline at end of file
diff --git a/core/config/credentials.php b/core/config/credentials.php
deleted file mode 100644
index 43fa0a4..0000000
--- a/core/config/credentials.php
+++ /dev/null
@@ -1,126 +0,0 @@
-<?php
-/** SERVICE PARAMETRES
- * -----------------------------------------------------------------------------
- *
- * Connection parametres and credentials for accssing services
- * needed by the application; Such services may be..
- *
- * - RDBMS
- * -- MySQL
- * -- PotgresSQL
- *
- * - Caching services
- * -- Redis
- * -- MemCached
- *
- * Edit only the constants needed by the application;
- * Comment those you do not need;
- *
- * /////////////////////////////////////////////////////////////////////////////
- */
-
-/** DATABASE CONNECTION PARAMETRES
- * -----------------------------------------------------------------------------
- * Production and staging environments may use different databases.
- *
- * A safe practice is to keep credentials outside plain files like this one
- * in environmental variable or other secret file etc.
- *
- * Uncomment/enable each group of definitions suits your case to define
- * the credentials needed for accessing the database
- */
-
-/** This is a SAFE method (define credentials as OS environmental variables)
- * -----------------------------------------------------------------------------
- */
-# define('DB_NAME', getenv('DB_NAME')); // database name
-#
-# define('DB_USER', getenv('DB_USER')); // database user-name
-#
-# define('DB_PASS', getenv('DB_PASS')); // user's pass
-#
-# define('PDO_HOST', getenv('PDO_HOST')); // database host (connection string)
-
-
-/** This is another SAFE method (keep credentials in an .env file)
- * -----------------------------------------------------------------------------
- */
-
-$ini_array = parse_ini_file("../core/auth/.env");
-
-define('DB_NAME', $ini_array['DB_NAME']);
-
-define('DB_USER', $ini_array['DB_USER']);
-
-define('DB_PASS', $ini_array['DB_PASS']);
-
-define('PDO_HOST', $ini_array['PDO_HOST']);
-
-
-/** This is just good enough
- * -----------------------------------------------------------------------------
- */
-#
-# if (!PRODUCTION) { // == Deployed on staging
-#
-# // STAGING SETTINGS:
-#
-# define('DB_NAME', 'dev_db_name');
-#
-# define('DB_USER', 'devUserName');
-#
-# define('DB_PASS', getenv('DBPASSWORD'));
-#
-# // PDO_HOST can be a hostname/port combination -or- a unix socket
-# // ...examples:
-# // define('PDO_HOST', 'host=/localhost') ## hostname case
-# // define('PDO_HOST', 'host=/localhost;port=3456') ## hostname/port case
-# // define('PDO_HOST', 'unix_socket=/sql/ex123:europe:some-db'); ## unix socket
-# define('PDO_HOST', 'unix_socket=/cloudsql/name-123456:europe-west4:name-db-eu');
-#
-# } else { // == Deployed on production
-#
-# // PRODUCTION SETTINGS:
-#
-# define('DB_NAME', 'your_db_name');
-# define('DB_USER', 'dbusername');
-# define('DB_PASS', getenv('DBPASSWORD'));
-# define('PDO_HOST', 'unix_socket=/cloudsql/name-123456:europe-west4:name-db-eu');
-#
-# }
-
-define('DB_TIMEZONE', "SET time_zone = 'Europe/Athens'");
-
-/** NOTE:
- * Both Redis and Memcached configurations are given as a template to work on;
- * In most cases the default values should do the job -- of course you need to
- * read the README file (check the project's root);
- * As these caching services are not fully tested you may need to ochestrate
- * the services in detail or edit the connection strings into the core classes
- * (hosted under the '/core/classes/cacher' folder)
- */
-
-
-/** REDIS SERVICE
- * -----------------------------------------------------------------------------
- * Most of the times Redis is running on 'localhost' (host = '127.0.0.1')
- * When implemented via anom's docker-composer (redis via bridge) then you need
- * do declare the hostname as 'redis'
- */
-#
-# if (!defined('REDIS_HOST')) define('REDIS_HOST', 'redis');
-#
-# if (!defined('REDIS_PORT')) define('REDIS_PORT', 6379);
-#
-# if (!defined('REDIS_PASS')) define('REDIS_PASS', null);
-
-
-/** MEMCACHED
- * -----------------------------------------------------------------------------
- * Memcached looks very much like Redis (plus, both are serving from RAM)
- * Usualy Memcashed is running localy so host is 'localhost' ('127.0.0.1')
- * If you use the framework's docker-composer implementation then
- * the hostname is 'anomemcached'
- */
-#
-#if (!defined('MEMCACHE_HOST')) define('MEMCACHE_HOST', 'anomemcached');
diff --git a/core/config/init.php b/core/config/init.php
index b035faf..2db2503 100644
--- a/core/config/init.php
+++ b/core/config/init.php
@@ -16,19 +16,16 @@
* anything else can be injected on-demand
*/
-// Load authorization parametres
-// -----------------------------------------------------------------------------
-require_once CREDENTIALS;
-
// setup error-handliing
// -----------------------------------------------------------------------------
require_once '../core/helpers/error_handling.php';
-// Load rendering sub-system
-// -----------------------------------------------------------------------------
-require_once RENDERING_SYSTEM;
+// depricated:
+/// // Load rendering sub-system
+/// // -----------------------------------------------------------------------------
+/// require_once RENDERING_SYSTEM;
// Setup Application Engiine
@@ -43,16 +40,12 @@ Registry::vow('database', function() { return new Database(); });
// Attach Cache to the Resitry as a vow
// (CACHE_DRIVER) acts as driver-wrapper
+// --- -- -- - - -
Registry::vow('cache', function() { return new (CACHE_DRIVER)(); });
// CHECK: if strict mode has any benefits:
// Registry::vow('cache', function():Cache_interface { return new (CACHE_DRIVER)(); });
-// Start session
-Registry::set('session', new DefaultSession());
-
-
-
// Initialize THE REQUEST
// -----------------------------------------------------------------------------
Registry::set('REQUEST', new Request());
diff --git a/core/helpers/error_handling.php b/core/helpers/error_handling.php
index bc60968..95db98c 100644
--- a/core/helpers/error_handling.php
+++ b/core/helpers/error_handling.php
@@ -82,16 +82,16 @@ function on_shutdown_check_for_fatal()
// 2nd: Show Errors
if (PRODUCTION) {
- if (!defined('VIEW_LOADED')) {
+ if (!defined('OUTPUT_STARTED')) {
// throw a prety-error message
- render_view('error/general', ['message' => 'Please forgive me, I know not what I do']);
+ Render::view('error/general', ['message' => 'Please forgive me, I know not what I do']);
}
} else {
- if (!defined('VIEW_LOADED')) {
+ if (!defined('OUTPUT_STARTED')) {
// no template loaded; render erros in general-error template
- render_view('error/general', ['message' => implode("<br/>And:<br/>", $anom_ERRORS)]);
+ Render::view('error/general', ['message' => implode("<br/>And:<br/>", $anom_ERRORS)]);
} else {
echo '<div style="padding:1em;background:#933;width:100%;color:#fff">
diff --git a/core/helpers/render.php b/core/helpers/render.php
deleted file mode 100644
index 9dcd34a..0000000
--- a/core/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);
- }
- }
-
-}
-
-
-