diff --git a/public/index.php b/public/index.php index 0bfbce2053fd..f384dd5416cf 100644 --- a/public/index.php +++ b/public/index.php @@ -14,7 +14,10 @@ PHP_VERSION ); - exit($message); + header('HTTP/1.1 503 Service Unavailable.', true, 503); + echo $message; + + exit(1); } /* @@ -47,30 +50,9 @@ $paths = new Config\Paths(); -// LOAD DOTENV FILE -// Load environment settings from .env files into $_SERVER and $_ENV -require_once $paths->systemDirectory . '/Config/DotEnv.php'; -(new CodeIgniter\Config\DotEnv($paths->appDirectory . '/../'))->load(); - -// DEFINE ENVIRONMENT -if (! defined('ENVIRONMENT')) { - $env = $_ENV['CI_ENVIRONMENT'] ?? $_SERVER['CI_ENVIRONMENT'] ?? getenv('CI_ENVIRONMENT'); - define('ENVIRONMENT', ($env !== false) ? $env : 'production'); - unset($env); -} - -// LOAD ENVIRONMENT BOOTSTRAP -if (is_file($paths->appDirectory . '/Config/Boot/' . ENVIRONMENT . '.php')) { - require_once $paths->appDirectory . '/Config/Boot/' . ENVIRONMENT . '.php'; -} else { - header('HTTP/1.1 503 Service Unavailable.', true, 503); - echo 'The application environment is not set correctly.'; - - exit(EXIT_ERROR); // EXIT_ERROR -} - // LOAD THE FRAMEWORK BOOTSTRAP FILE -require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php'; +require $paths->systemDirectory . '/Boot.php'; +CodeIgniter\Boot::BootWeb($paths); // Load Config Cache // $factoriesCache = new \CodeIgniter\Cache\FactoriesCache(); diff --git a/spark b/spark index 6b4034131925..a1b42e35b0b7 100755 --- a/spark +++ b/spark @@ -16,9 +16,12 @@ * -------------------------------------------------------------------- * The main entry point into the CLI system and allows you to run * commands and perform maintenance on your application. - * - * Because CodeIgniter can handle CLI requests as just another web request - * this class mainly acts as a passthru to the framework itself. + */ + +/* + *--------------------------------------------------------------- + * CHECK SERVER API + *--------------------------------------------------------------- */ // Refuse to run when called from php-cgi @@ -75,30 +78,9 @@ require FCPATH . '../app/Config/Paths.php'; $paths = new Config\Paths(); -// LOAD DOTENV FILE -// Load environment settings from .env files into $_SERVER and $_ENV -require_once $paths->systemDirectory . '/Config/DotEnv.php'; -(new CodeIgniter\Config\DotEnv($paths->appDirectory . '/../'))->load(); - -// DEFINE ENVIRONMENT -if (! defined('ENVIRONMENT')) { - $env = $_ENV['CI_ENVIRONMENT'] ?? $_SERVER['CI_ENVIRONMENT'] ?? getenv('CI_ENVIRONMENT'); - define('ENVIRONMENT', ($env !== false) ? $env : 'production'); - unset($env); -} - -// LOAD ENVIRONMENT BOOTSTRAP -if (is_file($paths->appDirectory . '/Config/Boot/' . ENVIRONMENT . '.php')) { - require_once $paths->appDirectory . '/Config/Boot/' . ENVIRONMENT . '.php'; -} else { - header('HTTP/1.1 503 Service Unavailable.', true, 503); - echo 'The application environment is not set correctly.'; - - exit(EXIT_ERROR); // EXIT_ERROR -} - // LOAD THE FRAMEWORK BOOTSTRAP FILE -require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php'; +require $paths->systemDirectory . '/Boot.php'; +CodeIgniter\Boot::BootSpark($paths); /* * --------------------------------------------------------------- diff --git a/system/Boot.php b/system/Boot.php new file mode 100644 index 000000000000..ba94cce6b910 --- /dev/null +++ b/system/Boot.php @@ -0,0 +1,237 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter; + +use CodeIgniter\Config\DotEnv; +use Config\Autoload; +use Config\Modules; +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` + */ + public static function bootWeb(Paths $paths): void + { + static::boot($paths); + } + + /** + * Used by `spark` + */ + public static function bootSpark(Paths $paths): void + { + static::boot($paths); + } + + protected static function boot(Paths $paths): void + { + 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(); + } + + /** + * 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(); + } + + /** + * 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')) { + define('WRITEPATH', realpath(rtrim($paths->writableDirectory, '\\/ ')) . 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(); + Services::autoloader()->loadHelpers(); + } + + protected static function setExceptionHandler(): void + { + Services::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 + { + Services::autoloader()->initializeKint(CI_DEBUG); + } +} diff --git a/system/Exceptions/FrameworkException.php b/system/Exceptions/FrameworkException.php index fb371bc49c8d..a223f8ec927a 100644 --- a/system/Exceptions/FrameworkException.php +++ b/system/Exceptions/FrameworkException.php @@ -59,6 +59,8 @@ public static function forCopyError(string $path) /** * @return static + * + * @deprecated 4.5.0 No longer used. */ public static function forMissingExtension(string $extension) { diff --git a/system/Test/bootstrap.php b/system/Test/bootstrap.php index 776250abfac3..4a068a4c97b1 100644 --- a/system/Test/bootstrap.php +++ b/system/Test/bootstrap.php @@ -11,9 +11,7 @@ * the LICENSE file that was distributed with this source code. */ -use CodeIgniter\Config\DotEnv; -use Config\Autoload; -use Config\Modules; +use CodeIgniter\Boot; use Config\Paths; use Config\Services; @@ -80,85 +78,9 @@ * and fires up an environment-specific bootstrapping. */ -// LOAD DOTENV FILE -// Load environment settings from .env files into $_SERVER and $_ENV -require_once $paths->systemDirectory . '/Config/DotEnv.php'; -(new DotEnv($paths->appDirectory . '/../'))->load(); - -/* - * --------------------------------------------------------------- - * LOAD ENVIRONMENT BOOTSTRAP - * --------------------------------------------------------------- - * - * Load any custom boot files based upon the current environment. - * If no boot file exists, we shouldn't continue because something - * is wrong. At the very least, they should have error reporting setup. - */ - -if (is_file(APPPATH . 'Config/Boot/' . ENVIRONMENT . '.php')) { - require_once APPPATH . 'Config/Boot/' . ENVIRONMENT . '.php'; -} - -/* - * --------------------------------------------------------------- - * GRAB OUR CONSTANTS - * --------------------------------------------------------------- - */ - -require_once APPPATH . 'Config/Constants.php'; - -/* - * --------------------------------------------------------------- - * LOAD COMMON FUNCTIONS - * --------------------------------------------------------------- - */ - -// Load Common.php from App then System -if (is_file(APPPATH . 'Common.php')) { - require_once APPPATH . 'Common.php'; -} - -require_once SYSTEMPATH . 'Common.php'; - -/* - * --------------------------------------------------------------- - * LOAD OUR AUTOLOADER - * --------------------------------------------------------------- - * - * The autoloader allows all of 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. - */ - -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(); -Services::autoloader()->loadHelpers(); - -/* - * --------------------------------------------------------------- - * SET EXCEPTION AND ERROR HANDLERS - * --------------------------------------------------------------- - */ - -Services::exceptions()->initialize(); - -/* - * --------------------------------------------------------------- - * INITIALIZE KINT - * --------------------------------------------------------------- - */ - -Services::autoloader()->initializeKint(CI_DEBUG); +// LOAD THE FRAMEWORK BOOTSTRAP FILE +require $paths->systemDirectory . '/Boot.php'; +Boot::bootTest($paths); /* * --------------------------------------------------------------- diff --git a/system/bootstrap.php b/system/bootstrap.php index 84d52cef5cbc..c0b021494737 100644 --- a/system/bootstrap.php +++ b/system/bootstrap.php @@ -11,12 +11,25 @@ * the LICENSE file that was distributed with this source code. */ +/** + * --------------------------------------------------------------- + * This file cannot be used. The code has moved to Boot.php. + * --------------------------------------------------------------- + */ + use CodeIgniter\Exceptions\FrameworkException; use Config\Autoload; use Config\Modules; use Config\Paths; use Config\Services; +header('HTTP/1.1 503 Service Unavailable.', true, 503); + +$message = 'This "system/bootstrap.php" is no longer used. If you are seeing this error message, +the upgrade is not complete. Please refer to the upgrade guide and complete the upgrade. +See https://codeigniter4.github.io/userguide/installation/upgrade_450.html' . PHP_EOL; +echo $message; + /* * --------------------------------------------------------------- * SETUP OUR PATH CONSTANTS @@ -146,3 +159,5 @@ */ Services::autoloader()->initializeKint(CI_DEBUG); + +exit(1); diff --git a/user_guide_src/source/changelogs/v4.5.0.rst b/user_guide_src/source/changelogs/v4.5.0.rst index d4219c7b0333..7d1a6c1023d4 100644 --- a/user_guide_src/source/changelogs/v4.5.0.rst +++ b/user_guide_src/source/changelogs/v4.5.0.rst @@ -185,6 +185,8 @@ Others - **Web Page Caching:** ``ResponseCache`` has been improved to include the request HTTP method in the cache key. This means that the same URI will be cached separately if the HTTP method is different. +- **Bootstrap:** The ``CodeIgniter\Boot`` class has been introduced, replacing + **system/bootstrap.php**. ******** BREAKING @@ -249,6 +251,8 @@ Others - **BaseModel:** The ``getIdValue()`` method has been changed to ``abstract``. - **Routing:** The :ref:`404-override` feature does change the Response status code to 404 by default. See :ref:`Upgrading Guide `. +- **system/bootstrap.php:** This file cannot be used. The code has been moved to + the new ``CodeIgniter\Boot`` class. Interface Changes =================