nmsg::DEBUG]); msg::set_messenger_class(Console::class); msg::get()->setParametrableParams([ # En ligne de commande, on peut afficher les messages loggués "display_log" => true, ]); # avant que l'application soit configurée, rester en mode debug msg::get()->setLevels(msg::DEBUG_LEVELS, msg::DEBUG_LEVELS, msg::DEBUG); # si un fichier nommé .default-profile-devel existe dans le répertoire de # l'application ou du projet, alors le profil par défaut est devel global $argv; $homedir = os::homedir(); $projdir = path::abspath(path::dirname($argv[0])); while (true) { if (file_exists("$projdir/.default-profile-devel")) { config::set_default_profile(config::DEVEL); break; } # s'arrêter au répertoire du projet, ou à $HOMEDIR, ou à la racine if (file_exists("$projdir/composer.json")) break; if ($projdir == $homedir) break; $projdir = path::dirname($projdir); if ($projdir == "/") break; } } protected static function _app_configure(Application $app): void { config::configure(config::CONFIGURE_INITIAL_ONLY); # revenir à la configuration par défaut une fois que la configuration # initiale est faite msg::get()->setLevels(msg::PRINT_LEVELS, msg::LOG_LEVELS, msg::TYPE_LEVELS); nsay::reset_params(["min_level" => nmsg::NORMAL]); $app->parseArgs(); config::configure(); } protected static function _app_main(Application $app): void { $retcode = $app->main(); if (is_int($retcode)) exit($retcode); elseif (is_bool($retcode)) exit($retcode? 0: 1); elseif ($retcode !== null) exit(strval($retcode)); } static function run(?Application $app=null): void { $unlock = false; $stop = false; register_shutdown_function(function () use (&$unlock, &$stop) { $self = app::get(); if ($unlock) $self->getLockfile()->release(); if ($stop) $self->getRunfile()->stop(); }); try { static::_app_init(); if (static::USE_RUNFILE) { $self = app::get(); global $argc, $argv; if ($argc === 2 && $argv[1] === "--Application-Runlock-release") { $self->getLockfile()->release(); exit(0); } $useRunlock = static::USE_RUNLOCK; if ($useRunlock && $self->getLockfile()->warnIfLocked()) { exit(1); } $self->getRunfile()->start(); $stop = true; if ($useRunlock) { $self->getLockfile()->lock(); $unlock = true; } } if ($app === null) $app = new static(); static::_app_configure($app); static::_app_main($app); } catch (ExitException $e) { msg::error($e); exit($e->getCode()); } catch (Exception $e) { msg::error($e); exit(1); } } /** * sortir de l'application avec un code d'erreur, qui est 0 par défaut (i.e * pas d'erreur) * * équivalent à lancer l'exception {@link ExitException} */ protected static final function exit(int $exitcode=0, $message=null) { throw new ExitException($exitcode, $message); } /** * sortir de l'application avec un code d'erreur, qui vaut 1 par défaut (i.e * une erreur s'est produite) * * équivalent à lancer l'exception {@link ExitException} */ protected static final function die($message=null, int $exitcode=1) { throw new ExitException($exitcode, $message); } const PROFILE_SECTION = [ "title" => "PROFILS D'EXECUTION", ["group", ["-p", "--profile", "--app-profile", "args" => 1, "argsdesc" => "PROFILE", "action" => [null, "set_application_profile"], "help" => "spécifier le profil d'exécution", ], ["-P", "--prod", "action" => [config::class, "set_profile", config::PROD]], ["-T", "--test", "action" => [config::class, "set_profile", config::TEST]], ["--devel", "action" => [config::class, "set_profile", config::DEVEL]], ], ]; static function set_application_profile(string $profile): void { config::set_profile($profile); } const VERBOSITY_SECTION = [ "title" => "NIVEAU D'INFORMATION", "show" => false, ["group", ["--verbosity", "args" => 1, "argsdesc" => "silent|very-quiet|quiet|verbose|debug|trace", "action" => [null, "set_application_verbosity"], "help" => "spécifier le niveau d'informations affiché", ], ["-q", "--quiet", "action" => [null, "set_application_verbosity", "quiet"]], ["-v", "--verbose", "action" => [null, "set_application_verbosity", "verbose"]], ["-D", "--debug", "action" => [null, "set_application_verbosity", "debug"]], ["--sql-trace", "action" => [null, "set_application_sql_trace"]], ], ["-L", "--logfile", "args" => "file", "argsdesc" => "OUTPUT", "action" => [null, "set_application_log_output"], "help" => "Logger les messages de l'application dans le fichier spécifié", ], ["group", ["--color", "action" => [null, "set_application_color", true], "help" => "Afficher (resp. ne pas afficher) la sortie en couleur par défaut", ], ["--no-color", "action" => [null, "set_application_color", false]], ], ]; static function set_application_verbosity(string $verbosity): void { $msg = msg::get(); $nsay = nsay::get(); switch ($verbosity) { case "s": case "silent": $msg->setLevels([ msg::USER => msg::NEVER, msg::TECH => msg::NEVER, msg::EXCEPTION => msg::NEVER, ]); $nsay->resetParams([ "min_level" => nmsg::NONE, ]); break; case "Q": case "very-quiet": $msg->setLevels([ msg::USER => msg::CRITICAL, msg::TECH => msg::CRITICAL, msg::EXCEPTION => msg::NEVER, ]); $nsay->resetParams([ "min_level" => nmsg::MAJOR, ]); break; case "q": case "quiet": $msg->setLevels([ msg::USER => msg::MAJOR, msg::TECH => msg::MAJOR, msg::EXCEPTION => msg::NEVER, ]); $nsay->resetParams([ "min_level" => nmsg::MAJOR, ]); break; case "v": case "verbose": $msg->setLevels([ msg::USER => msg::MINOR, msg::TECH => msg::MINOR, msg::EXCEPTION => msg::NEVER, ]); $nsay->resetParams([ "min_level" => nmsg::MINOR, ]); break; case "D": case "debug": config::set_debug(); $msg->setLevels([ msg::USER => msg::MINOR, msg::TECH => msg::MINOR, msg::EXCEPTION => msg::NORMAL, ], null, msg::DEBUG); $nsay->resetParams([ "min_level" => nmsg::DEBUG, ]); break; case "T": case "trace": config::set_debug(); $msg->setLevels([ msg::USER => msg::MINOR, msg::TECH => msg::MINOR, msg::EXCEPTION => msg::MINOR, ], null, msg::DEBUG); $nsay->resetParams([ "min_level" => nmsg::DEBUG, ]); break; default: throw ValueException::invalid_value($verbosity, "verbosity"); } } static function set_application_sql_trace(): void { config::add(new ArrayConfig(["app" => ["trace_sql" => true]])); } static function set_application_log_output(string $logfile): void { msg::get()->setParametrableParams(["log_output" => $logfile]); nlog::create_or_reset_params([ "output" => $logfile, ], nStdMessenger::class, [ "add_date" => true, "min_level" => nlog::MINOR, ]); } static function set_application_color(bool $color): void { msg::get()->setParametrableParams(["color" => $color]); nsay::reset_params([ "color" => $color, ]); } const ARGS = [ "sections" => [ self::PROFILE_SECTION, self::VERBOSITY_SECTION, ], ]; /** @throws ArgsException */ function parseArgs(array $args=null): void { $parser = new ArgsParser(static::ARGS); $parser->parse($this, $args); } const PROFILE_COLORS = [ "prod" => "@r", "test" => "@g", "devel" => "@w", ]; const DEFAULT_PROFILE_COLOR = "y"; /** retourner le profil courant en couleur */ static function profile(?string $profile=null): string { if ($profile === null) $profile = config::get_profile(); foreach (static::PROFILE_COLORS as $text => $color) { if (strpos($profile, $text) !== false) { return $color? "$profile": $profile; } } $color = static::DEFAULT_PROFILE_COLOR; return $color? "$profile": $profile; } abstract function main(); }