CodeIgniter4/system/Boot.php
John Paul E. Balandan, CPA c3ac0f9483
chore: add more trailing commas in more places (#9395)
* Apply to parameters

* Apply to array destructuring

* Apply to match

* Apply for arguments
2025-01-13 11:03:02 +08:00

365 lines
10 KiB
PHP

<?php
declare(strict_types=1);
/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace CodeIgniter;
use CodeIgniter\Cache\FactoriesCache;
use CodeIgniter\CLI\Console;
use CodeIgniter\Config\DotEnv;
use Config\Autoload;
use Config\Modules;
use Config\Optimize;
use Config\Paths;
use Config\Services;
/**
* Bootstrap for the application
*
* @codeCoverageIgnore
*/
class Boot
{
/**
* Used by `public/index.php`
*
* Context
* web: Invoked by HTTP request
* php-cli: Invoked by CLI via `php public/index.php`
*
* @return int Exit code.
*/
public static function bootWeb(Paths $paths): int
{
static::definePathConstants($paths);
if (! defined('APP_NAMESPACE')) {
static::loadConstants();
}
static::checkMissingExtensions();
static::loadDotEnv($paths);
static::defineEnvironment();
static::loadEnvironmentBootstrap($paths);
static::loadCommonFunctions();
static::loadAutoloader();
static::setExceptionHandler();
static::initializeKint();
$configCacheEnabled = class_exists(Optimize::class)
&& (new Optimize())->configCacheEnabled;
if ($configCacheEnabled) {
$factoriesCache = static::loadConfigCache();
}
static::autoloadHelpers();
$app = static::initializeCodeIgniter();
static::runCodeIgniter($app);
if ($configCacheEnabled) {
static::saveConfigCache($factoriesCache);
}
// Exits the application, setting the exit code for CLI-based
// applications that might be watching.
return EXIT_SUCCESS;
}
/**
* Used by `spark`
*
* @return int Exit code.
*/
public static function bootSpark(Paths $paths): int
{
static::definePathConstants($paths);
if (! defined('APP_NAMESPACE')) {
static::loadConstants();
}
static::checkMissingExtensions();
static::loadDotEnv($paths);
static::defineEnvironment();
static::loadEnvironmentBootstrap($paths);
static::loadCommonFunctions();
static::loadAutoloader();
static::setExceptionHandler();
static::initializeKint();
static::autoloadHelpers();
static::initializeCodeIgniter();
$console = static::initializeConsole();
return static::runCommand($console);
}
/**
* Used by `system/Test/bootstrap.php`
*/
public static function bootTest(Paths $paths): void
{
static::loadConstants();
static::checkMissingExtensions();
static::loadDotEnv($paths);
static::loadEnvironmentBootstrap($paths, false);
static::loadCommonFunctions();
static::loadAutoloader();
static::setExceptionHandler();
static::initializeKint();
static::autoloadHelpers();
}
/**
* Used by `preload.php`
*/
public static function preload(Paths $paths): void
{
static::definePathConstants($paths);
static::loadConstants();
static::defineEnvironment();
static::loadEnvironmentBootstrap($paths, false);
static::loadAutoloader();
}
/**
* Load environment settings from .env files into $_SERVER and $_ENV
*/
protected static function loadDotEnv(Paths $paths): void
{
require_once $paths->systemDirectory . '/Config/DotEnv.php';
(new DotEnv($paths->appDirectory . '/../'))->load();
}
protected static function defineEnvironment(): void
{
if (! defined('ENVIRONMENT')) {
// @phpstan-ignore-next-line
$env = $_ENV['CI_ENVIRONMENT'] ?? $_SERVER['CI_ENVIRONMENT']
?? getenv('CI_ENVIRONMENT')
?: 'production';
define('ENVIRONMENT', $env);
}
}
protected static function loadEnvironmentBootstrap(Paths $paths, bool $exit = true): void
{
if (is_file($paths->appDirectory . '/Config/Boot/' . ENVIRONMENT . '.php')) {
require_once $paths->appDirectory . '/Config/Boot/' . ENVIRONMENT . '.php';
return;
}
if ($exit) {
header('HTTP/1.1 503 Service Unavailable.', true, 503);
echo 'The application environment is not set correctly.';
exit(EXIT_ERROR);
}
}
/**
* The path constants provide convenient access to the folders throughout
* the application. We have to set them up here, so they are available in
* the config files that are loaded.
*/
protected static function definePathConstants(Paths $paths): void
{
// The path to the application directory.
if (! defined('APPPATH')) {
define('APPPATH', realpath(rtrim($paths->appDirectory, '\\/ ')) . DIRECTORY_SEPARATOR);
}
// The path to the project root directory. Just above APPPATH.
if (! defined('ROOTPATH')) {
define('ROOTPATH', realpath(APPPATH . '../') . DIRECTORY_SEPARATOR);
}
// The path to the system directory.
if (! defined('SYSTEMPATH')) {
define('SYSTEMPATH', realpath(rtrim($paths->systemDirectory, '\\/ ')) . DIRECTORY_SEPARATOR);
}
// The path to the writable directory.
if (! defined('WRITEPATH')) {
$writePath = realpath(rtrim($paths->writableDirectory, '\\/ '));
if ($writePath === false) {
header('HTTP/1.1 503 Service Unavailable.', true, 503);
echo 'The WRITEPATH is not set correctly.';
// EXIT_ERROR is not yet defined
exit(1);
}
define('WRITEPATH', $writePath . DIRECTORY_SEPARATOR);
}
// The path to the tests directory
if (! defined('TESTPATH')) {
define('TESTPATH', realpath(rtrim($paths->testsDirectory, '\\/ ')) . DIRECTORY_SEPARATOR);
}
}
protected static function loadConstants(): void
{
require_once APPPATH . 'Config/Constants.php';
}
protected static function loadCommonFunctions(): void
{
// Require app/Common.php file if exists.
if (is_file(APPPATH . 'Common.php')) {
require_once APPPATH . 'Common.php';
}
// Require system/Common.php
require_once SYSTEMPATH . 'Common.php';
}
/**
* The autoloader allows all the pieces to work together in the framework.
* We have to load it here, though, so that the config files can use the
* path constants.
*/
protected static function loadAutoloader(): void
{
if (! class_exists(Autoload::class, false)) {
require_once SYSTEMPATH . 'Config/AutoloadConfig.php';
require_once APPPATH . 'Config/Autoload.php';
require_once SYSTEMPATH . 'Modules/Modules.php';
require_once APPPATH . 'Config/Modules.php';
}
require_once SYSTEMPATH . 'Autoloader/Autoloader.php';
require_once SYSTEMPATH . 'Config/BaseService.php';
require_once SYSTEMPATH . 'Config/Services.php';
require_once APPPATH . 'Config/Services.php';
// Initialize and register the loader with the SPL autoloader stack.
Services::autoloader()->initialize(new Autoload(), new Modules())->register();
}
protected static function autoloadHelpers(): void
{
service('autoloader')->loadHelpers();
}
protected static function setExceptionHandler(): void
{
service('exceptions')->initialize();
}
protected static function checkMissingExtensions(): void
{
if (is_file(COMPOSER_PATH)) {
return;
}
// Run this check for manual installations
$missingExtensions = [];
foreach ([
'intl',
'json',
'mbstring',
] as $extension) {
if (! extension_loaded($extension)) {
$missingExtensions[] = $extension;
}
}
if ($missingExtensions === []) {
return;
}
$message = sprintf(
'The framework needs the following extension(s) installed and loaded: %s.',
implode(', ', $missingExtensions),
);
header('HTTP/1.1 503 Service Unavailable.', true, 503);
echo $message;
exit(EXIT_ERROR);
}
protected static function initializeKint(): void
{
service('autoloader')->initializeKint(CI_DEBUG);
}
protected static function loadConfigCache(): FactoriesCache
{
$factoriesCache = new FactoriesCache();
$factoriesCache->load('config');
return $factoriesCache;
}
/**
* The CodeIgniter class contains the core functionality to make
* the application run, and does all the dirty work to get
* the pieces all working together.
*/
protected static function initializeCodeIgniter(): CodeIgniter
{
$app = service('codeigniter');
$app->initialize();
$context = is_cli() ? 'php-cli' : 'web';
$app->setContext($context);
return $app;
}
/**
* Now that everything is set up, it's time to actually fire
* up the engines and make this app do its thang.
*/
protected static function runCodeIgniter(CodeIgniter $app): void
{
$app->run();
}
protected static function saveConfigCache(FactoriesCache $factoriesCache): void
{
$factoriesCache->save('config');
}
protected static function initializeConsole(): Console
{
$console = new Console();
// Show basic information before we do anything else.
// @phpstan-ignore-next-line
if (is_int($suppress = array_search('--no-header', $_SERVER['argv'], true))) {
unset($_SERVER['argv'][$suppress]); // @phpstan-ignore-line
$suppress = true;
}
$console->showHeader($suppress);
return $console;
}
protected static function runCommand(Console $console): int
{
$exit = $console->run();
return is_int($exit) ? $exit : EXIT_SUCCESS;
}
}