Properly declare & handle functions/methods that never return (exit/die inside) and add Cli::fatal_error() helper method

This commit is contained in:
Benjamin Renard 2023-07-26 16:51:16 +02:00
parent 248ea089fa
commit 8c108d0ebb
Signed by: bn8
GPG key ID: 3E2E1CE1907115BC
17 changed files with 126 additions and 160 deletions

View file

@ -271,7 +271,7 @@ function cli_cron($command_args) {
); );
} }
} }
exit($error?1:0); return !$error;
} }
Cli :: add_command( Cli :: add_command(
'cron', 'cron',

View file

@ -159,10 +159,8 @@ function handle_create($request) {
Tpl :: add_message(_("The element '% s' has been created."), $item['name']); Tpl :: add_message(_("The element '% s' has been created."), $item['name']);
Url :: redirect('item/'.$item['id']); Url :: redirect('item/'.$item['id']);
} }
else {
Tpl :: add_error(_("An error occurred while saving this item.")); Tpl :: add_error(_("An error occurred while saving this item."));
} }
}
Log :: debug('Validated data : '.vardump($info)); Log :: debug('Validated data : '.vardump($info));
Log :: debug('Fields errors : '.vardump($field_errors)); Log :: debug('Fields errors : '.vardump($field_errors));
if (isset($_POST['submit']) && !empty($field_errors)) if (isset($_POST['submit']) && !empty($field_errors))
@ -182,7 +180,8 @@ function handle_modify($request) {
global $status_list; global $status_list;
$item = get_item_from_url($request -> id); $item = get_item_from_url($request -> id);
if(is_array($item)) { if(!is_array($item))
Url :: error_404();
if (!can_modify($item)) { if (!can_modify($item)) {
Tpl :: add_error(_('You cannot edit this item.')); Tpl :: add_error(_('You cannot edit this item.'));
Url :: redirect('item/'.$item['id']); Url :: redirect('item/'.$item['id']);
@ -200,14 +199,12 @@ function handle_modify($request) {
Tpl :: add_message(_("You have not made any changes to element '% s'."), $item['name']); Tpl :: add_message(_("You have not made any changes to element '% s'."), $item['name']);
Url :: redirect('item/'.$item['id']); Url :: redirect('item/'.$item['id']);
} }
else if (update_item($item['id'], $changes) === true) { if (update_item($item['id'], $changes) === true) {
Tpl :: add_message(_("The element '% s' has been updated successfully."), $item['name']); Tpl :: add_message(_("The element '% s' has been updated successfully."), $item['name']);
Url :: redirect('item/'.$item['id']); Url :: redirect('item/'.$item['id']);
} }
else {
Tpl :: add_error(_("An error occurred while updating this item.")); Tpl :: add_error(_("An error occurred while updating this item."));
} }
}
Log :: debug('Validated data : '.vardump($info)); Log :: debug('Validated data : '.vardump($info));
Log :: debug('Fields errors : '.vardump($field_errors)); Log :: debug('Fields errors : '.vardump($field_errors));
Tpl :: assign('submited', isset($_POST['submit'])); Tpl :: assign('submited', isset($_POST['submit']));
@ -219,22 +216,15 @@ function handle_modify($request) {
Tpl :: assign('item_id', $item['id']); Tpl :: assign('item_id', $item['id']);
Tpl :: assign('field_errors', $field_errors); Tpl :: assign('field_errors', $field_errors);
Tpl :: assign('status_list', $status_list); Tpl :: assign('status_list', $status_list);
}
else {
Url :: error_404();
}
Tpl :: display( Tpl :: display("form.tpl", _("Element %s: Modification"), $item['name']);
"form.tpl", _("Element %s: Modification"),
(is_array($item)?$item['name']:"#".$request -> id)
);
} }
Url :: add_url_handler('|^item/(?P<id>[0-9]+)/modify$|', 'handle_modify'); Url :: add_url_handler('|^item/(?P<id>[0-9]+)/modify$|', 'handle_modify');
/** /**
* Archive one item page handler * Archive one item page handler
* @param EesyPHP\UrlRequest $request * @param EesyPHP\UrlRequest $request
* @return void * @return never
*/ */
function handle_archive($request) { function handle_archive($request) {
$item = get_item_from_url($request -> id); $item = get_item_from_url($request -> id);
@ -242,7 +232,7 @@ function handle_archive($request) {
Tpl :: add_error(_("Item #% s not found."), $request -> id); Tpl :: add_error(_("Item #% s not found."), $request -> id);
Url :: redirect('item'); Url :: redirect('item');
} }
elseif ($item['status'] == 'archived') { if ($item['status'] == 'archived') {
Tpl :: add_message(_("This item is already archived.")); Tpl :: add_message(_("This item is already archived."));
} }
else if (!can_archive($item)) { else if (!can_archive($item)) {

View file

@ -37,10 +37,8 @@ class App {
Config::register_extra_variable('root_directory_path', $root_directory_path); Config::register_extra_variable('root_directory_path', $root_directory_path);
$config_file = Config::replace_variables($config_file); $config_file = Config::replace_variables($config_file);
if ($config_file && !Config::load($config_file)) { if ($config_file && !Config::load($config_file))
Log::fatal('Fail to load configuration file (%s)', $config_file); Log::fatal('Fail to load configuration file (%s)', $config_file);
exit(1);
}
// Set config default values // Set config default values
App :: set_defaults( App :: set_defaults(

View file

@ -23,7 +23,7 @@ class Cas extends Method {
*/ */
public static function init() { public static function init() {
// In phpstan context, do not initialize // In phpstan context, do not initialize
if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) // @phpstan-ignore-line
return true; return true;
// Set config default values // Set config default values
App :: set_default( App :: set_default(
@ -124,10 +124,8 @@ class Cas extends Method {
*/ */
public static function logout() { public static function logout() {
if (App :: get('auth.cas.logout', null, 'bool') && !self :: $fake_authenticated_user) { if (App :: get('auth.cas.logout', null, 'bool') && !self :: $fake_authenticated_user) {
if (App :: get('auth.cas.logout_url')) { if (App :: get('auth.cas.logout_url'))
Url :: redirect(App :: get('auth.cas.logout_url')); Url :: redirect(App :: get('auth.cas.logout_url'));
exit();
}
phpCAS::logout(); phpCAS::logout();
} }
else { else {
@ -139,7 +137,7 @@ class Cas extends Method {
/** /**
* The CAS callback view * The CAS callback view
* @param \EesyPHP\UrlRequest $request * @param \EesyPHP\UrlRequest $request
* @return void * @return never
*/ */
public static function handle_cas_callback($request) { public static function handle_cas_callback($request) {
if (isset($_SESSION['cas_callback_url'])) { if (isset($_SESSION['cas_callback_url'])) {

View file

@ -113,7 +113,7 @@ class Http extends Method {
/** /**
* Force HTTP user authentification * Force HTTP user authentification
* @return void * @return never
*/ */
public static function force_login() { public static function force_login() {
header('HTTP/1.1 401 Authorization Required'); header('HTTP/1.1 401 Authorization Required');

View file

@ -21,7 +21,6 @@ class Method {
*/ */
public static function login($force=false) { public static function login($force=false) {
Log :: fatal('login() is not implement for this authentication method.'); Log :: fatal('login() is not implement for this authentication method.');
return null;
} }
/** /**

View file

@ -113,7 +113,7 @@ Additionnal parameters:
* Show usage message * Show usage message
* @param string|false $error Error message to show (optional) * @param string|false $error Error message to show (optional)
* @param array $extra_args Extra arguments to use to compute error message using sprintf * @param array $extra_args Extra arguments to use to compute error message using sprintf
* @return void * @return never
*/ */
public static function usage($error=false, ...$extra_args) { public static function usage($error=false, ...$extra_args) {
global $argv; global $argv;
@ -172,11 +172,12 @@ Additionnal parameters:
* Handle command line arguments * Handle command line arguments
* @param array|null $args Command line argurment to handle (optional, default: $argv) * @param array|null $args Command line argurment to handle (optional, default: $argv)
* @param bool|null $core_mode Force enable/disable EesyPHP core mode (optional, default: false) * @param bool|null $core_mode Force enable/disable EesyPHP core mode (optional, default: false)
* @return void * @return never
*/ */
public static function handle_args($args=null, $core_mode=false) { public static function handle_args($args=null, $core_mode=false) {
global $argv; global $argv;
self :: core_mode($core_mode); self :: core_mode($core_mode);
Log :: register_fatal_error_handler(array('\\EesyPHP\\Cli', 'fatal_error'));
$args = is_array($args)?$args:array_slice($argv, 1); $args = is_array($args)?$args:array_slice($argv, 1);
$log_level_set = false; $log_level_set = false;
self :: $command = null; self :: $command = null;
@ -193,7 +194,6 @@ Additionnal parameters:
case '-h': case '-h':
case '--help': case '--help':
self :: usage(); self :: usage();
break;
case '-d': case '-d':
case '--debug': case '--debug':
Log :: set_level('DEBUG'); Log :: set_level('DEBUG');
@ -257,7 +257,7 @@ Additionnal parameters:
* Command to create new project based on EesyPHP framework * Command to create new project based on EesyPHP framework
* *
* @param array $command_args The command arguments * @param array $command_args The command arguments
* @return void * @return true
*/ */
public static function cli_new_project($command_args) { public static function cli_new_project($command_args) {
echo "This CLI tool permit to initialize a new project using the EesyPHP framework.\n"; echo "This CLI tool permit to initialize a new project using the EesyPHP framework.\n";
@ -271,9 +271,9 @@ Additionnal parameters:
if (empty($input)) if (empty($input))
break; break;
if (!is_dir($input)) if (!is_dir($input))
echo "Invalid root directory specified: not found or is not a directory\n"; self::fatal_error("Invalid root directory specified: not found or is not a directory");
else if (!is_writeable($input)) else if (!is_writeable($input))
echo "Invalid root directory specified: not writeable\n"; self::fatal_error("Invalid root directory specified: not writeable");
else else
$root_path = $input; $root_path = $input;
} }
@ -289,23 +289,24 @@ Additionnal parameters:
$path = "$root_path/".$iterator->getSubPathname(); $path = "$root_path/".$iterator->getSubPathname();
if ($item->isDir()) { if ($item->isDir()) {
if (!mkdir($path)) if (!mkdir($path))
die("Fail to create $path directory\n"); self::fatal_error("Fail to create $path directory");
} }
else { else {
if (!copy($item, $path)) if (!copy($item, $path))
die("Fail to copy file to $path\n"); self::fatal_error("Fail to copy file to $path");
} }
if (!chmod($path, $item->getPerms())) if (!chmod($path, $item->getPerms()))
die("Fail to chmod file $path\n"); self::fatal_error("Fail to chmod file $path");
} }
echo "done. Start coding!\n"; echo "done. Start coding!\n";
return true;
} }
/** /**
* Command to start PHP built-in HTTP server to serve the EesyPHP project * Command to start PHP built-in HTTP server to serve the EesyPHP project
* *
* @param array $command_args The command arguments * @param array $command_args The command arguments
* @return void * @return never
*/ */
public static function cli_serve($command_args) { public static function cli_serve($command_args) {
$listen_address = null; $listen_address = null;
@ -315,40 +316,32 @@ Additionnal parameters:
switch($command_args[$i]) { switch($command_args[$i]) {
case '-P': case '-P':
case '--enable-profiler': case '--enable-profiler':
if (phpversion('xdebug') === false) { if (phpversion('xdebug') === false)
self :: usage(I18n::_("The PHP XDEBUG extension is missing.")); self :: usage(I18n::_("The PHP XDEBUG extension is missing."));
return;
}
$enable_profiler = true; $enable_profiler = true;
break; break;
case '-O': case '-O':
case '--profiler-output': case '--profiler-output':
$i++; $i++;
$profiler_output_dir = $command_args[$i]; $profiler_output_dir = $command_args[$i];
if (!is_dir($profiler_output_dir)) { if (!is_dir($profiler_output_dir))
self :: usage( self :: usage(
I18n::_('Invalid profiler output directory "%s": not found'), I18n::_('Invalid profiler output directory "%s": not found'),
$profiler_output_dir $profiler_output_dir
); );
return; if (!is_writable($profiler_output_dir))
}
if (!is_writable($profiler_output_dir)) {
self :: usage( self :: usage(
I18n::_('Invalid profiler output directory "%s": not writeable'), I18n::_('Invalid profiler output directory "%s": not writeable'),
$profiler_output_dir $profiler_output_dir
); );
return;
}
break; break;
default: default:
if (is_null($listen_address)) { if (is_null($listen_address)) {
$i++; $i++;
$listen_address = $command_args[$i]; $listen_address = $command_args[$i];
} }
else { else
self :: usage(I18n::_('Invalid parameter "%s"', $command_args[$i])); self :: usage(I18n::_('Invalid parameter "%s"', $command_args[$i]));
return;
}
break; break;
} }
} }
@ -357,37 +350,29 @@ Additionnal parameters:
if (is_null($listen_address)) if (is_null($listen_address))
$listen_address = '127.0.0.1:8000'; $listen_address = '127.0.0.1:8000';
$parts = explode(':', $listen_address); $parts = explode(':', $listen_address);
if (count($parts) != 2) { if (count($parts) != 2)
self :: usage( self :: usage(
I18n::_('Invalid listen address specify. Must be in formart host:port (or :port).') I18n::_('Invalid listen address specify. Must be in formart host:port (or :port).')
); );
return;
}
if (empty($parts[0])) { if (empty($parts[0])) {
$parts[0] = '0.0.0.0'; $parts[0] = '0.0.0.0';
} }
else if (!Check::ip_address($parts[0])) { else if (!Check::ip_address($parts[0]))
self :: usage( self :: usage(
I18n::_('Invalid listen host specified. Must be an IPv4 or IPv6 address.') I18n::_('Invalid listen host specified. Must be an IPv4 or IPv6 address.')
); );
return;
}
if (!Check::tcp_or_udp_port($parts[1])) { if (!Check::tcp_or_udp_port($parts[1]))
self :: usage( self :: usage(
I18n::_('Invalid listen port specified. Must be a positive integer between 1 and 65535.') I18n::_('Invalid listen port specified. Must be a positive integer between 1 and 65535.')
); );
return;
}
$listen_address = implode(':', $parts); $listen_address = implode(':', $parts);
$public_html = App::get('root_directory_path')."/public_html"; $public_html = App::get('root_directory_path')."/public_html";
chdir($public_html) or die( chdir($public_html) or self :: fatal_error(
sprintf(
'Fail to enter in the public_html directory of the application (%s).', 'Fail to enter in the public_html directory of the application (%s).',
$public_html $public_html
)
); );
$args = array( $args = array(
"-S", $listen_address, "-S", $listen_address,
@ -430,4 +415,23 @@ Additionnal parameters:
return $password; return $password;
} }
/**
* Handle a fatal error in a CLI command
* @param string $error The error message
* @param array $extra_args Extra arguments to use to compute the error message using sprintf
* @return never
*/
public static function fatal_error($error, ...$extra_args) {
// If extra arguments passed, format error message using sprintf
if ($extra_args) {
$error = call_user_func_array(
'sprintf',
array_merge(array($error), $extra_args)
);
}
fwrite(STDERR, "FATAL ERROR : $error\n");
exit(1);
}
} }

View file

@ -111,10 +111,8 @@ Class Config {
public static function isset($key, &$config=null) { public static function isset($key, &$config=null) {
if (array_key_exists($key, self :: $extra_variables)) if (array_key_exists($key, self :: $extra_variables))
return true; return true;
if (!is_array($config) && !self :: loaded()) { if (!is_array($config) && !self :: loaded())
Log :: fatal('Configuration not loaded (on checking if %s is set)', $key); Log :: fatal('Configuration not loaded (on checking if %s is set)', $key);
exit(1);
}
$exploded_key = explode('.', $key); $exploded_key = explode('.', $key);
if (!is_array($exploded_key)) return false; if (!is_array($exploded_key)) return false;
$value = is_array($config)?$config:self :: $config; $value = is_array($config)?$config:self :: $config;
@ -151,7 +149,6 @@ Class Config {
"Configuration not loaded (on getting %s):\n%s", "Configuration not loaded (on getting %s):\n%s",
$key, Log :: get_debug_backtrace_context() $key, Log :: get_debug_backtrace_context()
); );
exit(1);
} }
else { else {
$exploded_key = explode('.', $key); $exploded_key = explode('.', $key);
@ -186,10 +183,8 @@ Class Config {
$config = is_null($config)?self :: $config:$config; $config = is_null($config)?self :: $config:$config;
$iteration = 0; $iteration = 0;
while (preg_match('/\$\{([^\}]+)\}/', $value, $m)) { while (preg_match('/\$\{([^\}]+)\}/', $value, $m)) {
if ($iteration > 20) { if ($iteration > 20)
Log::fatal('Config::replace_variables(%s): max iteration reached'); Log::fatal('Config::replace_variables(%s): max iteration reached');
return $value;
}
if (is_callable($config)) if (is_callable($config))
$replace_by = call_user_func($config, $m[1], '', 'string', false); $replace_by = call_user_func($config, $m[1], '', 'string', false);
else else

View file

@ -57,10 +57,8 @@ class Db {
*/ */
public function __construct($dsn, $user=null, $password=null, $options=null, public function __construct($dsn, $user=null, $password=null, $options=null,
$date_format=null, $datetime_format=null, $locale_time=null) { $date_format=null, $datetime_format=null, $locale_time=null) {
if (!$dsn) { if (!$dsn)
Log :: fatal('Database DSN not configured'); Log :: fatal('Database DSN not configured');
return;
}
if ($date_format) $this -> date_format = $date_format; if ($date_format) $this -> date_format = $date_format;
if ($datetime_format) $this -> datetime_format = $datetime_format; if ($datetime_format) $this -> datetime_format = $datetime_format;
if ($locale_time) $this -> locale_time = $locale_time; if ($locale_time) $this -> locale_time = $locale_time;

View file

@ -343,9 +343,8 @@ class I18n {
false, // do not escape command args (already done) false, // do not escape command args (already done)
__DIR__ // Run from EesyPHP src directory __DIR__ // Run from EesyPHP src directory
); );
if (!is_array($eesyphp_php_files) || $eesyphp_php_files[0] != 0) { if (!is_array($eesyphp_php_files) || $eesyphp_php_files[0] != 0)
Log :: fatal(self::_("Fail to list EesyPHP PHP files.")); Log :: fatal(self::_("Fail to list EesyPHP PHP files."));
}
// Extract messages from EesyPHP PHP files using xgettext // Extract messages from EesyPHP PHP files using xgettext
$pot_file = "$root_path/php-messages.pot"; $pot_file = "$root_path/php-messages.pot";
@ -380,9 +379,8 @@ class I18n {
false, // do not escape command args (already done) false, // do not escape command args (already done)
App :: root_directory_path() // Run from Application root directory App :: root_directory_path() // Run from Application root directory
); );
if (!is_array($php_files) || $php_files[0] != 0) { if (!is_array($php_files) || $php_files[0] != 0)
Log :: fatal(self::_("Fail to list application PHP files.")); Log :: fatal(self::_("Fail to list application PHP files."));
}
// Extract messages from PHP files using xgettext // Extract messages from PHP files using xgettext
$pot_file = "$root_path/php-messages.pot"; $pot_file = "$root_path/php-messages.pot";
@ -416,10 +414,10 @@ class I18n {
false, // do not escape command args (already done) false, // do not escape command args (already done)
dirname($static_directory) // Run from parent directory dirname($static_directory) // Run from parent directory
); );
if (!is_array($result) || $result[0] != 0) { if (!is_array($result) || $result[0] != 0)
Log :: fatal(self::_("Fail to list JS files in the directory of static files '%s'."), $static_directory); Log :: fatal(
return; self::_("Fail to list JS files in the directory of static files '%s'."),
} $static_directory);
// Extract messages from JS files using xgettext // Extract messages from JS files using xgettext
$pot_file = "$root_path/js-$idx-messages.pot"; $pot_file = "$root_path/js-$idx-messages.pot";
@ -512,11 +510,9 @@ class I18n {
foreach ($command_args as $arg) { foreach ($command_args as $arg) {
if (!file_exists($arg)) if (!file_exists($arg))
Log :: fatal(self::_("Compendium file %s not found."), $arg); Log :: fatal(self::_("Compendium file %s not found."), $arg);
else {
$compendium_args[] = '-C'; $compendium_args[] = '-C';
$compendium_args[] = $arg; $compendium_args[] = $arg;
} }
}
$domain = Cli::core_mode()?self::CORE_TEXT_DOMAIN:self::TEXT_DOMAIN; $domain = Cli::core_mode()?self::CORE_TEXT_DOMAIN:self::TEXT_DOMAIN;
$root_path = Cli::core_mode()?self::$core_root_path:self::$root_path; $root_path = Cli::core_mode()?self::$core_root_path:self::$root_path;
@ -587,7 +583,6 @@ class I18n {
} }
Log :: fatal(self::_("Fail to open root lang directory (%s)."), App :: root_directory_path()); Log :: fatal(self::_("Fail to open root lang directory (%s)."), App :: root_directory_path());
return false;
} }
/** /**
@ -714,7 +709,6 @@ class I18n {
return !$error; return !$error;
} }
Log :: fatal(self::_("Fail to open root lang directory (%s)."), App :: root_directory_path()); Log :: fatal(self::_("Fail to open root lang directory (%s)."), App :: root_directory_path());
return false;
} }
} }

View file

@ -82,7 +82,7 @@ class Log {
// Set log level: // Set log level:
// Note: in Phpstan context, force FATAL level // Note: in Phpstan context, force FATAL level
if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) // @phpstan-ignore-line
self :: set_level('FATAL'); self :: set_level('FATAL');
else else
self :: set_level(App::get('log.level', null, 'string')); self :: set_level(App::get('log.level', null, 'string'));
@ -150,7 +150,7 @@ class Log {
* @param string $level The message level (key of self :: $levels) * @param string $level The message level (key of self :: $levels)
* @param string $message The message to log * @param string $message The message to log
* @param array $extra_args Extra arguments to use to compute message using sprintf * @param array $extra_args Extra arguments to use to compute message using sprintf
* @return true * @return ($level is "FATAL" ? never : true)
*/ */
public static function log($level, $message, ...$extra_args) { public static function log($level, $message, ...$extra_args) {
global $argv; global $argv;
@ -295,10 +295,11 @@ class Log {
* Log an fatal message * Log an fatal message
* @param string $message The message to log * @param string $message The message to log
* @param array $extra_args Extra arguments to use to compute message using sprintf * @param array $extra_args Extra arguments to use to compute message using sprintf
* @return true * @return never
*/ */
public static function fatal($message, ...$extra_args) { public static function fatal($message, ...$extra_args) {
return call_user_func_array( // @phpstan-ignore-next-line
call_user_func_array(
array('EesyPHP\\Log', 'log'), array('EesyPHP\\Log', 'log'),
array_merge(array('FATAL', $message), $extra_args) array_merge(array('FATAL', $message), $extra_args)
); );

View file

@ -26,7 +26,7 @@ class SentryIntegration {
*/ */
public static function init() { public static function init() {
// In phpstan context, do not initialize // In phpstan context, do not initialize
if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) // @phpstan-ignore-line
return; return;
// Set config default values // Set config default values
App :: set_default( App :: set_default(

View file

@ -48,6 +48,7 @@ class SentrySpan {
*/ */
public function __construct($op, $name) { public function __construct($op, $name) {
// In phpstan context, do not initialize // In phpstan context, do not initialize
// @phpstan-ignore-next-line
if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__'))
return; return;
$this -> parent = \Sentry\SentrySdk::getCurrentHub()->getSpan(); $this -> parent = \Sentry\SentrySdk::getCurrentHub()->getSpan();

View file

@ -28,6 +28,7 @@ class SentryTransaction {
*/ */
public function __construct($op=null, $name=null) { public function __construct($op=null, $name=null) {
// In phpstan context, do not initialize // In phpstan context, do not initialize
// @phpstan-ignore-next-line
if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__'))
return; return;
// Setup context for the full transaction // Setup context for the full transaction
@ -54,6 +55,7 @@ class SentryTransaction {
*/ */
public function __destruct() { public function __destruct() {
// In phpstan context, do nothing // In phpstan context, do nothing
// @phpstan-ignore-next-line
if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__'))
return; return;
SentrySpan :: finishAll(); SentrySpan :: finishAll();

View file

@ -89,6 +89,7 @@ class Tpl {
*/ */
public static function init() { public static function init() {
// In phpstan context, do not initialize // In phpstan context, do not initialize
// @phpstan-ignore-next-line
if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__')) if (defined('__PHPSTAN_RUNNING__') && constant('__PHPSTAN_RUNNING__'))
return; return;
@ -126,12 +127,10 @@ class Tpl {
// Handle and check templates_c directories // Handle and check templates_c directories
$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 ($templates_c_dir) {
if (!is_dir($templates_c_dir) || !is_writable($templates_c_dir)) { if (!is_dir($templates_c_dir) || !is_writable($templates_c_dir))
Log :: fatal( Log :: fatal(
"Template cache directory not found or not writable (%s)", "Template cache directory not found or not writable (%s)",
$templates_c_dir); $templates_c_dir);
return;
}
} }
else { else {
$public_root_url = Url :: public_root_url(); $public_root_url = Url :: public_root_url();
@ -140,13 +139,11 @@ class Tpl {
} }
else { else {
$root_directory_path = App::root_directory_path(); $root_directory_path = App::root_directory_path();
if ($root_directory_path == '.') { if ($root_directory_path == '.')
Log :: fatal( Log :: fatal(
'Fail to compute a unique templates cache directory for this application. An public '. 'Fail to compute a unique templates cache directory for this application. An public '.
'root URL or an application root directory must be set if you do not provide it at '. 'root URL or an application root directory must be set if you do not provide it at '.
'initialization (or via config parameter).'); 'initialization (or via config parameter).');
return;
}
$unique_name = $root_directory_path; $unique_name = $root_directory_path;
if (substr($unique_name, 0, 1) == '/') if (substr($unique_name, 0, 1) == '/')
$unique_name = substr($unique_name, 1); $unique_name = substr($unique_name, 1);
@ -156,12 +153,10 @@ class Tpl {
$templates_c_dir = sys_get_temp_dir().'/'.str_replace( $templates_c_dir = sys_get_temp_dir().'/'.str_replace(
'/', '_', "eesyphp_templates_cache_$unique_name" '/', '_', "eesyphp_templates_cache_$unique_name"
); );
if (!is_dir($templates_c_dir) && !mkdir($templates_c_dir)) { if (!is_dir($templates_c_dir) && !mkdir($templates_c_dir))
Log :: fatal( Log :: fatal(
'Fail to create application templates cache directory (%s)', 'Fail to create application templates cache directory (%s)',
$templates_c_dir); $templates_c_dir);
return;
}
App :: set_default('templates.cache_directory', $templates_c_dir); App :: set_default('templates.cache_directory', $templates_c_dir);
} }
self :: $smarty = new Smarty(); self :: $smarty = new Smarty();
@ -433,10 +428,8 @@ class Tpl {
* @return void * @return void
*/ */
public static function display($template, $pagetitle=null, ...$extra_args) { public static function display($template, $pagetitle=null, ...$extra_args) {
if (!$template) { if (!$template)
Log :: fatal(I18n::_("No template specified.")); Log :: fatal(I18n::_("No template specified."));
return;
}
// If refresh parameter is present, remove it and redirect // If refresh parameter is present, remove it and redirect
if (isset($_GET['refresh'])) { if (isset($_GET['refresh'])) {
@ -445,7 +438,6 @@ class Tpl {
if (!empty($_GET)) if (!empty($_GET))
$url .= '?'.http_build_query($_GET); $url .= '?'.http_build_query($_GET);
Url :: redirect($url); Url :: redirect($url);
return;
} }
$sentry_span = new SentrySpan('smarty.display_template', "Display Smarty template"); $sentry_span = new SentrySpan('smarty.display_template', "Display Smarty template");
@ -520,7 +512,7 @@ class Tpl {
* @param array|null $data AJAX returned data (optional) * @param array|null $data AJAX returned data (optional)
* @param bool $pretty AJAX returned data * @param bool $pretty AJAX returned data
* (optional, default: true if $_REQUEST['pretty'] is set, False otherwise) * (optional, default: true if $_REQUEST['pretty'] is set, False otherwise)
* @return void * @return never
*/ */
public static function display_ajax_return($data=null, $pretty=false) { public static function display_ajax_return($data=null, $pretty=false) {
if (!is_array($data)) if (!is_array($data))
@ -548,7 +540,7 @@ class Tpl {
* Handle a fatal error * Handle a fatal error
* @param string $error The error message * @param string $error The error message
* @param array $extra_args Extra arguments to use to compute the error message using sprintf * @param array $extra_args Extra arguments to use to compute the error message using sprintf
* @return void * @return never
*/ */
public static function fatal_error($error, ...$extra_args) { public static function fatal_error($error, ...$extra_args) {
// If extra arguments passed, format error message using sprintf // If extra arguments passed, format error message using sprintf
@ -559,17 +551,18 @@ class Tpl {
); );
} }
if (php_sapi_name() == "cli") if (php_sapi_name() == "cli") {
die("FATAL ERROR : $error\n"); if (App :: get('cli.enabled', null, 'bool'))
Cli :: fatal_error($error);
die("FATAL ERROR: $error\n");
}
// Set HTTP reponse code to 500 // Set HTTP reponse code to 500
http_response_code(500); http_response_code(500);
// Handle API mode // Handle API mode
if (Url :: api_mode()) { if (Url :: api_mode())
self :: display_ajax_return(array('success' => false, 'error' => $error)); self :: display_ajax_return(array('success' => false, 'error' => $error));
return;
}
self :: assign('fatal_error', $error); self :: assign('fatal_error', $error);
self :: display('fatal_error.tpl'); self :: display('fatal_error.tpl');
@ -610,12 +603,10 @@ class Tpl {
* @return void * @return void
*/ */
public static function register_templates_directory($path, $priority=null) { public static function register_templates_directory($path, $priority=null) {
if (!is_dir($path)) { if (!is_dir($path))
Log :: fatal( Log :: fatal(
'register_templates_directory(%s): this templates directory does not exists', 'register_templates_directory(%s): this templates directory does not exists',
$path); $path);
return;
}
if (substr($path, -1) == '/') if (substr($path, -1) == '/')
$path = substr($path, 0, -1); $path = substr($path, 0, -1);
if (is_null($priority)) { if (is_null($priority)) {
@ -800,7 +791,7 @@ class Tpl {
* Note: this URL handler is registered in EesyPHP\Url by self::init(). * Note: this URL handler is registered in EesyPHP\Url by self::init().
* @see self::init() * @see self::init()
* @param UrlRequest $request * @param UrlRequest $request
* @return void * @return never
*/ */
public static function handle_static_file($request) { public static function handle_static_file($request) {
$path = self :: resolve_static_path($request->root_url, $request->path); $path = self :: resolve_static_path($request->root_url, $request->path);

View file

@ -169,7 +169,7 @@ class Url {
* @param $request UrlRequest|null The request (optional, default: null) * @param $request UrlRequest|null The request (optional, default: null)
* @param $error_code int|null The HTTP error code (optional, default: 400) * @param $error_code int|null The HTTP error code (optional, default: 400)
* *
* @return void * @return never
**/ **/
public static function error_page($request=null, $error_code=null) { public static function error_page($request=null, $error_code=null) {
$http_errors = array( $http_errors = array(
@ -213,7 +213,7 @@ class Url {
* *
* @param UrlRequest|null $request The request (optional, default: null) * @param UrlRequest|null $request The request (optional, default: null)
* *
* @return void * @return never
**/ **/
public static function error_404($request=null) { public static function error_404($request=null) {
self :: error_page($request, 404); self :: error_page($request, 404);
@ -240,10 +240,11 @@ class Url {
/** /**
* Trigger a 404 HTTP error * Trigger a 404 HTTP error
* @param UrlRequest|null $request Current UrlRequest object (optional, default: null) * @param UrlRequest|null $request Current UrlRequest object (optional, default: null)
* @return void * @return never
*/ */
public static function trigger_error_404($request=null) { public static function trigger_error_404($request=null) {
call_user_func_array(self :: $error_404_handler, array($request)); call_user_func_array(self :: $error_404_handler, array($request));
exit();
} }
@ -257,17 +258,13 @@ class Url {
*/ */
protected static function get_request($default_url=null) { protected static function get_request($default_url=null) {
$current_url = self :: get_current_url(); $current_url = self :: get_current_url();
if ($current_url === false) { if ($current_url === false)
Log :: fatal( Log :: fatal(
I18n::_('Unable to determine the requested page. '. I18n::_('Unable to determine the requested page. '.
'If the problem persists, please contact support.') 'If the problem persists, please contact support.')
); );
exit(); if (!is_array(self :: $patterns))
}
if (!is_array(self :: $patterns)) {
Log :: fatal('URL : No URL patterns configured !'); Log :: fatal('URL : No URL patterns configured !');
exit();
}
Log :: debug("URL : current url = '$current_url'"); Log :: debug("URL : current url = '$current_url'");
if (array_key_exists($_SERVER['REQUEST_METHOD'], self :: $patterns)) { if (array_key_exists($_SERVER['REQUEST_METHOD'], self :: $patterns)) {
@ -295,7 +292,6 @@ class Url {
if ($default_url !== false) { if ($default_url !== false) {
Log :: debug("Current url match with no pattern. Redirect to default url ('$default_url')"); Log :: debug("Current url match with no pattern. Redirect to default url ('$default_url')");
self :: redirect($default_url); self :: redirect($default_url);
exit();
} }
// Error 404 // Error 404
$api_mode = self :: $_api_mode || (strpos($current_url, 'api/') === 0); $api_mode = self :: $_api_mode || (strpos($current_url, 'api/') === 0);
@ -388,7 +384,7 @@ class Url {
* *
* @param string|false $go The destination URL * @param string|false $go The destination URL
* *
* @return void * @return never
**/ **/
public static function redirect($go=false) { public static function redirect($go=false) {
if ($go===false) if ($go===false)
@ -415,7 +411,6 @@ class Url {
Log :: fatal( Log :: fatal(
I18n::_('Unable to determine the requested page (loop detected). '. I18n::_('Unable to determine the requested page (loop detected). '.
'If the problem persists, please contact support.')); 'If the problem persists, please contact support.'));
else
$_SESSION['last_redirect'] = $url; $_SESSION['last_redirect'] = $url;
Log :: debug("redirect($go) => Redirect to : <$url>"); Log :: debug("redirect($go) => Redirect to : <$url>");

View file

@ -136,7 +136,7 @@ function cast($value, $type, $split=false) {
* @param string|null $mime_type The file MIME type (optional, default: auto-detected) * @param string|null $mime_type The file MIME type (optional, default: auto-detected)
* @param int|null $max_age Max age in second of this file in browser cache (optional, * @param int|null $max_age Max age in second of this file in browser cache (optional,
* default: null=1h, set to False to disable Cache-Control header) * default: null=1h, set to False to disable Cache-Control header)
* @return void * @return never
*/ */
function dump_file($file_path, $mime_type=null, $max_age=null) { function dump_file($file_path, $mime_type=null, $max_age=null) {
if (is_file($file_path)) { if (is_file($file_path)) {