From 83f14457997559efc6ccb9a8cfd20d269c8351e2 Mon Sep 17 00:00:00 2001 From: Benjamin Renard Date: Wed, 1 Mar 2023 16:22:11 +0100 Subject: [PATCH] Make core libs set their default config values in App This permit to homogenize the method to store it and permit an access to all config default values. Futhermore, core libs init() methods now does not handle parameters: all are taken from config. --- src/App.php | 61 ++++++++++++++--- src/Auth.php | 12 +++- src/Auth/Cas.php | 22 +++++-- src/Auth/Db.php | 24 +++++-- src/Auth/Form.php | 7 ++ src/Auth/Http.php | 15 ++++- src/Auth/Ldap.php | 73 ++++++++++++--------- src/Email.php | 133 ++++++++++++++------------------------ src/I18n.php | 28 ++++---- src/Log.php | 78 +++++++++++----------- src/SentryIntegration.php | 42 +++++------- src/Session.php | 27 ++++---- src/Tpl.php | 60 ++++++++--------- src/Url.php | 13 ++-- 14 files changed, 326 insertions(+), 269 deletions(-) diff --git a/src/App.php b/src/App.php index c46cceb..7a89a6c 100644 --- a/src/App.php +++ b/src/App.php @@ -39,13 +39,30 @@ class App { exit(1); } + // Set config default values + App :: set_defaults( + array( + 'overwrite_config_files' => array(), + 'upload_tmp_directory' => null, + 'upload_max_filesize' => null, + 'sentry.enabled' => true, + 'log.enabled' => true, + 'session.enabled' => true, + 'templates.enabled' => true, + 'url.enabled' => true, + 'mail.enabled' => true, + 'i18n.enabled' => true, + 'cli.enabled' => true, + ) + ); + // Load overwrite configuration file - foreach (self :: get('overwrite_config_files', array(), 'array') as $file) { + foreach (self :: get('overwrite_config_files', null, 'array') as $file) { $file = Config::replace_variables($file); if (is_file($file)) Config::load($file, true); } - if (self :: get('sentry.enabled', true, 'bool')) + if (self :: get('sentry.enabled', null, 'bool')) SentryIntegration :: init(); $sentry_transaction = new SentryTransaction(); $sentry_span = new SentrySpan('app.init', 'Application initialization'); @@ -60,13 +77,13 @@ class App { Config :: ini_set('post_max_size', strval(self::get('upload_max_filesize', null, 'int') * 1.1)); } - if (self :: get('log.enabled', true, 'bool')) + if (self :: get('log.enabled', null, 'bool')) Log::init(); - if (self :: get('session.enabled', true, 'bool')) + if (self :: get('session.enabled', null, 'bool')) Session::init(); - if (self :: get('templates.enabled', true, 'bool')) + if (self :: get('templates.enabled', null, 'bool')) Tpl :: init(); - if (self :: get('url.enabled', true, 'bool')) { + if (self :: get('url.enabled', null, 'bool')) { Url::init(); Url :: add_url_handler(null, array('EesyPHP\\App', 'handle_homepage')); } @@ -74,11 +91,11 @@ class App { Auth :: init(); Url :: add_url_handler('#^logout$#', array('EesyPHP\\App', 'handle_logout'), null, false); } - if (self :: get('mail.enabled', true, 'bool')) + if (self :: get('mail.enabled', null, 'bool')) Email :: init(); - if (self :: get('i18n.enabled', true, 'bool')) + if (self :: get('i18n.enabled', null, 'bool')) I18n::init(); - if (self :: get('cli.enabled', true, 'bool')) + if (self :: get('cli.enabled', null, 'bool')) Cli::init(); $sentry_span->finish(); } @@ -175,6 +192,32 @@ class App { return Config::set($key, $value); } + /** + * Set a specific option default value + * + * @param string $key The configuration variable key + * @param mixed $value The configuration variable default value + * @return boolean + **/ + public static function set_default($key, $value) { + return Config::set("default.$key", $value, self :: $options); + } + + /** + * Set a specific options default value + * + * @param array $values Associative array of configuration variables name and + * default values + * @return boolean + **/ + public static function set_defaults($values) { + $error = false; + foreach($values as $key => $value) + if (!self :: set_default($key, $value)) + $error = true; + return !$error; + } + /** * Retreive application root directory path * @return string|null diff --git a/src/Auth.php b/src/Auth.php index 96553e8..7d18384 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -36,7 +36,17 @@ class Auth { * @return void */ public static function init() { - if (!self :: enabled()) return; + // Set config default values + App :: set_default( + 'auth', + array( + 'methods' => array(), + 'backends' => array(), + 'enabled' => self :: enabled(), + 'allow_multiple_match' => null, + 'allow_multiple_match_with_valid_password' => null, + ) + ); self :: $methods = array(); foreach(App::get('auth.methods', array(), 'array') as $method) { if (!$method || !is_string($method)) { diff --git a/src/Auth/Cas.php b/src/Auth/Cas.php index cc52c8c..5594b76 100644 --- a/src/Auth/Cas.php +++ b/src/Auth/Cas.php @@ -25,6 +25,20 @@ class Cas extends Method { // In phpstan context, do not initialize if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) return true; + // Set config default values + App :: set_default( + 'auth.cas', + array( + 'host' => null, + 'port' => 443, + 'context' => '/idp/cas', + 'version' => '2.0', + 'logout' => true, + 'fake_authenticated_user' => null, + 'debug_log_file' => null, + 'ca_cert_certificate_path' => null, + ) + ); self :: $fake_authenticated_user = App :: get( 'auth.cas.fake_authenticated_user', null, 'string'); if (self :: $fake_authenticated_user) return true; @@ -37,7 +51,7 @@ class Cas extends Method { return false; } - $cas_version = App :: get('auth.cas.version', '2.0', 'string'); + $cas_version = App :: get('auth.cas.version', null, 'string'); $supported_cas_versions = phpCAS::getSupportedProtocols(); if (!array_key_exists($cas_version, $supported_cas_versions)) { Log :: error( @@ -51,8 +65,8 @@ class Cas extends Method { phpCAS::client( $cas_version, App :: get('auth.cas.host'), - App :: get('auth.cas.port', 443, 'int'), - App :: get('auth.cas.context', '/idp/cas', 'string'), + App :: get('auth.cas.port', null, 'int'), + App :: get('auth.cas.context', null, 'string'), Url :: get_absolute_url("/") ); if (App :: get('auth.cas.ca_cert_certificate_path')) @@ -109,7 +123,7 @@ class Cas extends Method { * @return void */ public static function logout() { - if (App :: get('auth.cas.logout', true, 'bool') && !self :: $fake_authenticated_user) { + if (App :: get('auth.cas.logout', null, 'bool') && !self :: $fake_authenticated_user) { if (App :: get('auth.cas.logout_url')) { Url :: redirect(App :: get('auth.cas.logout_url')); exit(); diff --git a/src/Auth/Db.php b/src/Auth/Db.php index 149fd68..101413b 100644 --- a/src/Auth/Db.php +++ b/src/Auth/Db.php @@ -69,14 +69,28 @@ class Db extends Backend { * @return boolean */ public static function init() { + // Set config default values + App :: set_default( + 'auth.db', + array( + 'dsn' => null, + 'user' => null, + 'password' => null, + 'options' => array(), + 'users_table' => 'users', + 'username_field' => 'username', + 'password_field' => 'password', + 'exposed_fields' => array('name', 'mail'), + ) + ); self :: $dsn = App::get('auth.db.dsn', null, 'string'); self :: $user = App::get('auth.db.user', null, 'string'); self :: $password = App::get('auth.db.password', null, 'string'); - self :: $options = App::get('auth.db.options', array(), 'array'); - self :: $users_table = App::get('auth.db.users_table', 'users', 'string'); - self :: $username_field = App::get('auth.db.username_field', 'username', 'string'); - self :: $password_field = App::get('auth.db.password_field', 'password', 'string'); - self :: $exposed_fields = App::get('auth.db.exposed_fields', array('name', 'mail'), 'array'); + self :: $options = App::get('auth.db.options', null, 'array'); + self :: $users_table = App::get('auth.db.users_table', null, 'string'); + self :: $username_field = App::get('auth.db.username_field', null, 'string'); + self :: $password_field = App::get('auth.db.password_field', null, 'string'); + self :: $exposed_fields = App::get('auth.db.exposed_fields', null, 'array'); return boolval(self :: $dsn); } diff --git a/src/Auth/Form.php b/src/Auth/Form.php index 97742a7..fb9b09d 100644 --- a/src/Auth/Form.php +++ b/src/Auth/Form.php @@ -16,6 +16,13 @@ class Form extends Method { * @return boolean */ public static function init() { + // Set config default values + App :: set_default( + 'auth.login_form', + array( + 'display_other_methods' => array(), + ) + ); Url :: add_url_handler('#^login$#', array('EesyPHP\\Auth\\Form', 'handle_login'), null, false); Hook :: register('logged_in', array('\\EesyPHP\\Auth\\Form', 'logged_in_hook')); return true; diff --git a/src/Auth/Http.php b/src/Auth/Http.php index b0d3808..425a8eb 100644 --- a/src/Auth/Http.php +++ b/src/Auth/Http.php @@ -29,9 +29,18 @@ class Http extends Method { * @return boolean */ public static function init() { - self :: $method = App::get('auth.http.method', 'PHP_AUTH', 'string'); + // Set default config values + App :: set_default( + 'auth.http', + array( + 'method' => 'PHP_AUTH', + 'realm' => _('Authentication required'), + 'trust_without_password_challenge' => false, + ) + ); + self :: $method = App::get('auth.http.method', null, 'string'); self :: $realm = App::get( - 'auth.http.realm', _('Authentication required'), 'string'); + 'auth.http.realm', null, 'string'); return true; } @@ -91,7 +100,7 @@ class Http extends Method { return null; } - if (App :: get('auth.http.trust_without_password_challenge', false, 'bool')) + if (App :: get('auth.http.trust_without_password_challenge', null, 'bool')) $user = Auth :: get_user($auth_data['username']); else $user = Auth :: authenticate($auth_data['username'], $auth_data['password']); diff --git a/src/Auth/Ldap.php b/src/Auth/Ldap.php index 562ae5a..bb9d1fe 100644 --- a/src/Auth/Ldap.php +++ b/src/Auth/Ldap.php @@ -28,38 +28,49 @@ class Ldap extends Backend { */ private static $connection = null; - /** - * Default LDAP user attributes configuration - * @var array - */ - private static $default_user_attributes = array( - 'login' => array( - 'ldap_name' => 'uid', - 'type' => 'string', - 'multivalued' => false, - 'default' => null, - ), - 'mail' => array( - 'type' => 'string', - 'multivalued' => false, - 'default' => null, - ), - 'name' => array( - 'ldap_name' => 'displayName', - 'alt_ldap_name' => 'cn', - 'type' => 'string', - 'multivalued' => false, - 'default' => null, - ), - ); - /** * Initialize * @return bool */ public static function init() { + // Set default config values + App :: set_default( + 'auth.ldap', + array( + 'host' => array(), + 'port' => null, + 'basedn' => null, + 'binddn' => null, + 'bindpw' => null, + 'starttls' => false, + 'user_filter_by_uid' => 'uid=[username]', + 'user_basedn' => null, + 'bind_with_username' => false, + 'user_attributes' => array( + 'login' => array( + 'ldap_name' => 'uid', + 'type' => 'string', + 'multivalued' => false, + 'default' => null, + ), + 'mail' => array( + 'type' => 'string', + 'multivalued' => false, + 'default' => null, + ), + 'name' => array( + 'ldap_name' => 'displayName', + 'alt_ldap_name' => 'cn', + 'type' => 'string', + 'multivalued' => false, + 'default' => null, + ), + ), + 'netldap2_path' => 'Net/LDAP2.php', + ) + ); if (!class_exists('Net_LDAP2')) { - $path = App::get('auth.ldap.netldap2_path', 'Net/LDAP2.php', 'string'); + $path = App::get('auth.ldap.netldap2_path', null, 'string'); if (!@include($path)) { Log::error('Fail to load Net_LDAP2 (%s)', $path); return false; @@ -73,11 +84,11 @@ class Ldap extends Backend { } self :: $ldap_config = array ( - 'host' => implode(' ', App :: get('auth.ldap.host', array(), 'array')), + 'host' => implode(' ', App :: get('auth.ldap.host', null, 'array')), 'basedn' => App :: get('auth.ldap.basedn', null, 'string'), 'binddn' => App :: get('auth.ldap.bind_dn', null, 'string'), 'bindpw' => App :: get('auth.ldap.bind_password', null, 'string'), - 'starttls' => App :: get('starttls', false, 'bool'), + 'starttls' => App :: get('starttls', null, 'bool'), ); if ($port = App :: get('auth.ldap.port', null, 'int')) self :: $ldap_config['port'] = $port; @@ -202,7 +213,7 @@ class Ldap extends Backend { * @return \EesyPHP\Auth\User|null|false The user object if found, null it not, false in case of error */ public static function get_user($username) { - $attrs = App::get('auth.ldap.user_attributes', self :: $default_user_attributes, 'array'); + $attrs = App::get('auth.ldap.user_attributes', null, 'array'); $attrs_names = array(); foreach($attrs as $attr => $attr_config) { $name = Config::get("ldap_name", $attr, 'string', false, $attr_config); @@ -215,7 +226,7 @@ class Ldap extends Backend { $users = self :: search( str_replace( '[username]', Net_LDAP2_Filter::escape($username), - App::get('auth.ldap.user_filter_by_uid', 'uid=[username]', 'string') + App::get('auth.ldap.user_filter_by_uid', null, 'string') ), $attrs_names, App::get('auth.ldap.user_basedn', null, 'string') @@ -261,7 +272,7 @@ class Ldap extends Backend { public static function check_password($user, $password) { $config = self :: $ldap_config; $config['binddn'] = ( - App::get('auth.ldap.bind_with_username', false, 'bool')? + App::get('auth.ldap.bind_with_username', null, 'bool')? $user->username: $user->dn ); diff --git a/src/Email.php b/src/Email.php index 3082b93..dd47bb9 100644 --- a/src/Email.php +++ b/src/Email.php @@ -10,90 +10,45 @@ use finfo; class Email { - /** - * Default sender - * @var string|null; - */ - protected static $sender = null; - - /** - * Sending method : - * - mail : use PHP mail function - * - sendmail : use sendmail system command - * - smtp : use an SMTP server (PHP PEAR Net_SMTP required) - * @var string - */ - protected static $send_method = 'mail'; - - /** - * Sending parameters - * @see http://pear.php.net/manual/en/package.mail.mail.factory.php - * @var array|null - */ - protected static $send_params = null; - - /** - * Catch all sent email recipient - * @var string|array|null - */ - protected static $catch_all = null; - - /** - * Default headers to add on all sent emails - * @var array - */ - protected static $headers = array(); - - /** - * PHP PEAR Mail lib path - * @var string - */ - protected static $php_mail_path = 'Mail.php'; - - /** - * PHP PEAR Mail lib path - * @var string - */ - protected static $php_mail_mime_path = 'Mail/mime.php'; - - /** * Initialization - * @param string|null $php_mail_path PHP PEAR Mail lib path (optional, default: from - * email.php_mail_path config key if set, 'Mail.php' otherwise) - * @param string|null $php_mail_mime_path PHP PEAR Mail lib path (optional, default: from - * email.php_mail_mime_path config key if set, 'Mail/mime.php' otherwise) * @return void */ - public static function init($sender=null, $send_method=null, $send_params=null, $catch_all=null, - $headers=null, $php_mail_path=null, $php_mail_mime_path=null) { - if (is_null($sender)) - $sender = App::get('email.sender', null, 'string'); - if ($sender) self :: $sender = $sender; + public static function init() { + // Set config default values + App :: set_default( + 'email', + array( + // Default sender + 'sender' => null, - if (is_null($send_method)) - $send_method = App::get('email.send_method', null, 'string'); - if ($send_method) self :: $send_method = $send_method; + /** + * Sending method : + * - mail : use PHP mail function + * - sendmail : use sendmail system command + * - smtp : use an SMTP server (PHP PEAR Net_SMTP required) + */ + 'send_method' => null, - if (is_null($send_params)) - $send_params = App::get('email.send_params', null, 'array'); - if ($send_params) self :: $send_params = $send_params; + /** + * Sending parameters + * @see http://pear.php.net/manual/en/package.mail.mail.factory.php + */ + 'send_params' => array(), - if (is_null($catch_all)) - $catch_all = App::get('email.catch_all'); - if ($catch_all) self :: $catch_all = $catch_all; + // Catch all sent email recipient + 'catch_all' => null, - if (is_null($headers)) - $headers = App::get('email.headers', null, 'array'); - if ($headers) self :: $headers = $headers; + // Default headers to add on all sent emails + 'headers' => array(), - if (is_null($php_mail_path)) - $php_mail_path = App::get('email.php_mail_path', null, 'string'); - if ($php_mail_path) self :: $php_mail_path = $php_mail_path; + // PHP PEAR Mail lib path + 'php_mail_path' => 'Mail.php', - if (is_null($php_mail_mime_path)) - $php_mail_mime_path = App::get('email.php_mail_mime_path', null, 'string'); - if ($php_mail_mime_path) self :: $php_mail_mime_path = $php_mail_mime_path; + // PHP PEAR Mail_mime lib path + 'php_mail_mime_path' => 'Mail/mime.php', + ) + ); } @@ -116,24 +71,29 @@ class Email { public static function send($from, $to, $subject, $msg, $html=false, $attachments=null, $headers=null, $encoding=null, $eol=null) { if (!class_exists('Mail')) - require_once(self :: $php_mail_path); + require_once(App :: get('php_mail_path', null, 'string')); if (!class_exists('Mail_mime')) - require_once(self :: $php_mail_mime_path); + require_once(App :: get('php_mail_mime_path', null, 'string')); - $mail_obj = Mail::factory(self :: $send_method, self :: $send_params); + $mail_obj = Mail::factory( + App :: get('email.send_method', null, 'string'), + App :: get('email.send_params', null, 'array') + ); if (!$headers) $headers = array(); - $headers = array_merge($headers, self :: $headers); + $headers = array_merge($headers, App :: get('email.headers', null, 'array')); Log :: trace( 'Mail catch all: %s', - self :: $catch_all? - vardump(self :: $catch_all):'not set' + App :: get('email.catch_all')? + vardump(App :: get('email.catch_all')):'not set' ); - if (self :: $catch_all) { + if (App :: get('email.catch_all')) { Log :: debug( 'Mail catch to %s', - is_array(self :: $catch_all)?implode(',', self :: $catch_all):self :: $catch_all + is_array(App :: get('email.catch_all'))? + implode(',', App :: get('email.catch_all')): + App :: get('email.catch_all') ); $msg .= sprintf( ( @@ -144,8 +104,9 @@ class Email { (is_array($to)?implode(',', $to):$to)); $headers["X-Orig-To"] = $to; $to = ( - is_array(self :: $catch_all)? - implode(',', self :: $catch_all):self :: $catch_all + is_array(App :: get('email.catch_all'))? + implode(',', App :: get('email.catch_all')): + App :: get('email.catch_all') ); } @@ -159,7 +120,7 @@ class Email { unset($headers['From']); } elseif (!$from) { - $from = self :: $sender; + $from = App::get('email.sender'); } $headers["To"] = $to; @@ -170,7 +131,7 @@ class Email { foreach(array_keys($headers) as $header) { if(in_array(strtoupper($header), array('BCC', 'CC'))) { - if (self :: $catch_all) { + if (App :: get('email.catch_all')) { Log :: debug("Mail catched: remove $header header"); $msg .= sprintf( ( diff --git a/src/I18n.php b/src/I18n.php index bb6dd30..1d6e547 100644 --- a/src/I18n.php +++ b/src/I18n.php @@ -35,25 +35,21 @@ class I18n { * Detect best translation language and configure the translation * system. * - * @param string|null $root_path The root directory path of translation files - * (optional, default: from i18n.root_directory config key if set, - * '${root_directory_path}/locales' otherwise) - * @param string|null $default_locale The default locale - * (optional, default: from i18n.default_locale config key if set, - * 'en_US.UTF8' otherwise) * @return void */ - public static function init($root_path=null, $default_locale=null) { - if (is_null($root_path)) - self :: $root_path = App::get( - 'i18n.root_directory', '${root_directory_path}/locales', 'string'); - if (!is_null($root_path)) - self :: $root_path = $root_path; + public static function init() { + // Set config default values + App :: set_default( + 'i18n', + array( + 'root_directory' => '${root_directory_path}/locales', + 'default_locale' => null, + ) + ); - if (is_null($default_locale)) - $default_locale = App::get('i18n.default_locale', null, 'string'); - if (!is_null($default_locale)) - self :: $default_locale = $default_locale; + self :: $root_path = App::get( + 'i18n.root_directory', null, 'string'); + $default_locale = App::get('i18n.default_locale', null, 'string'); if (!class_exists('Locale')) { Log :: error('Locale PHP class does not exist. May be php-intl is not installed?'); diff --git a/src/Log.php b/src/Log.php index a877459..804ae8d 100644 --- a/src/Log.php +++ b/src/Log.php @@ -38,12 +38,6 @@ class Log { 'FATAL' => 5, ); - /* - * Default log level - * @var string - */ - protected static $default_level = 'WARNING'; - /* * Current log level * @var string|null @@ -63,42 +57,46 @@ class Log { /** * Initialization - * @param string $filepath The log file path - * (optional, default: from log.file_path or log.cli_file_path is set) - * @param string|null $level The log level - * (optional, default: from log.level config key if set, otherwise, - * see self :: $default_level) - * @param int|null $php_errors_levels PHP errors level as expected by set_error_handler() - * (optional, default: from log.php_errors_levels if set, E_ALL & ~E_STRICT - * if level is TRACE or DEBUG, and E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED - * otherwise) * @return void */ - public static function init($filepath=null, $level=null, $php_errors_levels=null) { - if ($filepath) - self :: $filepath = $filepath; - elseif (php_sapi_name() == 'cli') - self :: $filepath = App::get( - 'log.cli_logfile_path', App::get('log.cli_file_path')); - else - self :: $filepath = App::get('log.file_path'); + public static function init() { + // Set config default values + App :: set_default( + 'log', + array( + 'level' => 'WARNING', + 'file_path' => null, + 'cli_file_path' => '${log.file_path}', + 'default_locale' => null, + 'error_log_fallback' => true, + 'php_errors_levels' => array(), // Depend of effective log level, see below + ) + ); + self :: $filepath = App::get( + php_sapi_name() == 'cli'?'log.cli_logfile_path':'log.file_path' + ); // PHP error_log() fallback - self :: $error_log_fallback = App::get('log.error_log_fallback', true, 'bool'); + self :: $error_log_fallback = App::get('log.error_log_fallback', null, 'bool'); // Set log level: // Note: in Phpstan context, force FATAL level if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) self :: set_level('FATAL'); else - self :: set_level($level?$level:App::get('log.level')); + self :: set_level(App::get('log.level', null, 'string')); + App :: set_default( + 'log.php_errors_levels', + in_array(self :: $level, array('DEBUG', 'TRACE'))? + array('E_ALL', '~E_STRICT'): + array('E_ALL', '~E_STRICT', '~E_NOTICE', '~E_DEPRECATED') + ); // Log PHP errors - if (!is_null($php_errors_levels)) { - self :: $php_errors_levels = $php_errors_levels; - } - elseif ($levels = App::get('log.php_errors_levels', array(), 'array')) { + $levels = App::get('log.php_errors_levels', array(), 'array'); + if ($levels) { + self :: $php_errors_levels = E_ALL; $code = 'self :: $php_errors_levels = '; while($level = array_shift($levels)) { if (!is_string($level)) continue; @@ -125,14 +123,8 @@ class Log { } $code .= ";"; eval($code); + set_error_handler(array('EesyPHP\\Log', 'on_php_error'), self :: $php_errors_levels); } - elseif (in_array(self :: $level, array('DEBUG', 'TRACE'))) { - self :: $php_errors_levels = E_ALL & ~E_STRICT; - } - else { - self :: $php_errors_levels = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED; - } - set_error_handler(array('EesyPHP\\Log', 'on_php_error'), self :: $php_errors_levels); // Log uncatched exceptions set_exception_handler(array('EesyPHP\\Log', 'exception')); @@ -162,7 +154,13 @@ class Log { public static function log($level, $message, ...$extra_args) { global $argv; - if (!array_key_exists($level, self :: $levels)) $level = self :: $default_level; + if (!array_key_exists($level, self :: $levels)) { + self :: warning( + "Invalid log level specified logging the message %s, use 'WARNING':\n%s", + $message, self :: get_debug_backtrace_context() + ); + $level = 'WARNING'; + } if (self :: $levels[$level] < self :: $levels[self :: $level]) return true; if(self :: $filepath && is_null(self :: $file_fd)) { self :: $file_fd = fopen(self :: $filepath, 'a'); @@ -337,13 +335,13 @@ class Log { public static function set_level($level=null) { // Set default log level (if not defined or invalid) if (is_null($level)) { - self :: $level = self :: $default_level; + self :: $level = App::get_default('log.level', null, 'string'); } elseif (!array_key_exists($level, self :: $levels)) { - self :: $level = self :: $default_level; + self :: $level = App::get_default('log.level', null, 'string'); self :: warning( "Invalid log level value found in configuration (%s). ". - "Set as default (%s).", vardump($level), self :: $default_level); + "Set as default (%s).", vardump($level), self :: $level); } else { self :: $level = $level; diff --git a/src/SentryIntegration.php b/src/SentryIntegration.php index 4afde2a..bf9024a 100644 --- a/src/SentryIntegration.php +++ b/src/SentryIntegration.php @@ -18,35 +18,31 @@ class SentryIntegration { * @see https://www.php.net/manual/fr/errorfunc.constants.php * @var array */ - protected static $php_error_types = array( - E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, - E_RECOVERABLE_ERROR,E_DEPRECATED, - ); + protected static $php_error_types; /** * Initialization - * @param string|null $dsn Sentry DSN - * (optional, default: from sentry.dsn config key if set, null otherwise) - * @param float|null $traces_sample_rate Sentry traces sample rate - * (optional, default: from sentry.traces_sample_rate config key if set, - * 0.2 otherwise) - * @param array|null $php_error_types Types of PHP error to log in Sentry - * (optional, default: from sentry.php_error_types config key if set, - * otherwise, see self::$php_error_types) * @return void */ - public static function init($dsn=null, $traces_sample_rate=null, - $php_error_types=null) { + public static function init() { // In phpstan context, do not initialize if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) return; - \Sentry\init([ - 'dsn' => $dsn?$dsn:App::get('sentry.dsn'), - 'traces_sample_rate' => ( - $traces_sample_rate? - $traces_sample_rate: - App::get('sentry.traces_sample_rate', 0.2, 'float') + // Set config default values + App :: set_default( + 'sentry', + array( + 'dsn' => null, + 'traces_sample_rate' => 0.2, + 'php_error_types' => array( + 'E_ERROR', 'E_PARSE', 'E_CORE_ERROR', 'E_COMPILE_ERROR', 'E_USER_ERROR', + 'E_RECOVERABLE_ERROR', 'E_DEPRECATED', ), + ) + ); + \Sentry\init([ + 'dsn' => App::get('sentry.dsn'), + 'traces_sample_rate' => App::get('sentry.traces_sample_rate', null, 'float'), ]); \Sentry\configureScope(function (\Sentry\State\Scope $scope): void { @@ -56,12 +52,8 @@ class SentryIntegration { ]); }); - if (!is_array($php_error_types)) - $php_error_types = App::get( - 'sentry.php_error_types', self :: $php_error_types, 'array' - ); self :: $php_error_types = array(); - foreach($php_error_types as $php_error_type) { + foreach(App::get('sentry.php_error_types', null, 'array') as $php_error_type) { if (is_string($php_error_type) && defined($php_error_type)) $php_error_type = constant($php_error_type); if (!is_int($php_error_type)) continue; diff --git a/src/Session.php b/src/Session.php index 22c0df7..fed7fcb 100644 --- a/src/Session.php +++ b/src/Session.php @@ -11,30 +11,30 @@ class Session { * Session max duration (in seconds, default: 12h) * @var int */ - protected static $max_duration = 12 * 60 * 60; + protected static $max_duration; /** * Initialization - * @param int|null $max_duration Session max duration in second - * (optional, default: from session.max_duration config key if set, 12h otherwise) - * @param int|null $timeout Session inactivity timeout in second - * (optional, default: from session.timeout config key if set, no timeout otherwise) * @return void */ - public static function init($max_duration=null, $timeout=null) { + public static function init() { // In CLI or Phpstan context, do not initialize if ( php_sapi_name() == "cli" || (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) ) return; + // Set config default values + App :: set_default( + 'session', + array( + 'max_duration' => 43200, // 12h + 'timeout' => null, + ) + ); // Define session max duration - if (is_null($max_duration)) - $max_duration = App::get('session.max_duration', null, 'int'); - if (is_int($max_duration)) - self :: $max_duration = $max_duration; - + self :: $max_duration = App::get('session.max_duration', null, 'int'); Config :: ini_set('session.gc_maxlifetime', strval(self :: $max_duration)); Config :: ini_set('session.cookie_lifetime', strval(self :: $max_duration)); @@ -47,9 +47,8 @@ class Session { } // Handle session timeout - if (is_null($timeout)) - $timeout = App::get('session.timeout', null, 'int'); - if (is_int($timeout) && $timeout) { + $timeout = App::get('session.timeout', null, 'int'); + if ($timeout) { if (!isset($_SESSION['session_last_access'])) { Log :: debug('Set initial session last access'); $_SESSION['session_last_access'] = time(); diff --git a/src/Tpl.php b/src/Tpl.php index 8acb4be..2dd817f 100644 --- a/src/Tpl.php +++ b/src/Tpl.php @@ -33,12 +33,6 @@ class Tpl { */ public static $templates_directories = array(); - /** - * Smarty cache templates directory path - * @var string - */ - public static $templates_c_dir; - /** * Enable/disable AJAX returned data debugging in logs * @var bool @@ -83,28 +77,38 @@ class Tpl { /** * Initialization - * @param string $templates_dir Smarty templates directory path - * (optional, default: from templates.directory config key) - * @param string $templates_c_dir Smarty cache templates directory path - * (optional, default: from templates.cache_directory config key) - * @param bool $debug_ajax Enable/disable AJAX returned data debugging in logs - * (optional, default: from templates.debug_ajax or debug_ajax config keys if set, - * false otherwise) - * @param bool $static_root_url Configure custom root URL path for static files - * (optional, default: from templates.static_root_url config key if set, - * '/static' otherwise. Set to False to disable) * @return void */ - public static function init($templates_dir=null, $templates_c_dir=null, $debug_ajax=null, - $static_root_url=null) { + public static function init() { // In phpstan context, do not initialize if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) return; + + // Set config default values + App :: set_default( + 'templates', + array( + // Main Smarty templates directory path + 'directory' => null, + // Smarty cache templates directory path + // Default: see below, compute only if not set + 'cache_directory' => null, + 'main_pagetitle' => null, + 'static_root_url' => 'static/', + 'static_directories' => array(), + 'included_css_files' => array(), + 'included_js_files' => array(), + 'webstats_js_code' => null, + 'upload_max_filesize' => null, + 'debug_ajax' => App::get('debug_ajax', false, 'bool'), + ) + ); + // Handle templates directories self :: $core_templates_directory = realpath(__DIR__."/../templates"); self :: register_templates_directory(self :: $core_templates_directory); - if (is_null($templates_dir)) - $templates_dir = App::get('templates.directory', null, 'string'); + + $templates_dir = App::get('templates.directory', null, 'string'); if ($templates_dir) { if (!is_dir($templates_dir)) Log :: fatal("Template directory not found (%s)", $templates_dir); @@ -112,8 +116,7 @@ class Tpl { } // Handle and check templates_c directories - if (is_null($templates_c_dir)) - $templates_c_dir = App::get('templates.cache_directory', null, 'string'); + $templates_c_dir = App::get('templates.cache_directory', null, 'string'); if ($templates_c_dir) { if (!is_dir($templates_c_dir) || !is_writable($templates_c_dir)) { Log :: fatal( @@ -151,18 +154,17 @@ class Tpl { $templates_c_dir); return; } + App :: set_default('templates.cache_directory', $templates_c_dir); } self :: $smarty = new Smarty(); self :: $smarty->setTemplateDir(self :: $core_templates_directory); self :: $smarty->setCompileDir($templates_c_dir); self :: $smarty->registerResource('Tpl', new TplSmartyResource()); - if (is_null($debug_ajax)) - $debug_ajax = App::get('templates.debug_ajax', App::get('debug_ajax')); + $debug_ajax = App::get('templates.debug_ajax', null, 'bool'); self :: $_debug_ajax = boolval($debug_ajax); Log :: register_fatal_error_handler(array('\\EesyPHP\\Tpl', 'fatal_error')); - if (is_null($static_root_url)) - $static_root_url = App::get('templates.static_root_url', 'static/', 'string'); + $static_root_url = App::get('templates.static_root_url', null, 'string'); if ($static_root_url) { if (substr($static_root_url, 0, 1) == '/') $static_root_url = substr($static_root_url, 1); @@ -173,7 +175,7 @@ class Tpl { self :: register_static_directory(self :: $core_static_directory, 100); self :: register_function('static_url', array('EesyPHP\\Tpl', 'smarty_static_url')); - foreach(App :: get('templates.static_directories', array(), 'array') as $path) + foreach(App :: get('templates.static_directories', null, 'array') as $path) self :: register_static_directory($path); self :: register_function('var_dump', array('EesyPHP\\Tpl', 'smarty_var_dump')); @@ -365,8 +367,8 @@ class Tpl { self :: assign('session_key', isset($_SESSION['session_key'])?$_SESSION['session_key']:null); // Handle CSS & JS files included - self :: add_css_file(App::get('templates.included_css_files', array(), 'array')); - self :: add_js_file(App::get('templates.included_js_files', array(), 'array')); + self :: add_css_file(App::get('templates.included_css_files', null, 'array')); + self :: add_js_file(App::get('templates.included_js_files', null, 'array')); // Messages self :: assign('errors', self :: get_errors()); diff --git a/src/Url.php b/src/Url.php index 1e3e89f..8e5f993 100644 --- a/src/Url.php +++ b/src/Url.php @@ -58,22 +58,23 @@ class Url { /** * Initialization - * @param string|null $public_root_url The application public root URL - * (optional, default: from public_root_url config key) - * @param bool $api_mode Enable/disable API mode * @return void */ - public static function init($public_root_url=null, $api_mode=false) { + public static function init() { + // Set default config values + App :: set_default('public_root_url', null); + App :: set_default('api_mode', false); + if (php_sapi_name() == 'cli-server' && getenv('EESYPHP_SERVE_URL')) $public_root_url = getenv('EESYPHP_SERVE_URL'); - else if (is_null($public_root_url)) + else $public_root_url = App::get('public_root_url', null, 'string'); if (is_string($public_root_url) && $public_root_url) { // Remove trailing slash $public_root_url = rtrim($public_root_url, '/'); self :: $public_root_url = $public_root_url?$public_root_url:null; } - self :: $_api_mode = boolval($api_mode); + self :: $_api_mode = boolval(App::get('api_mode', null, 'bool')); } /**