Skip to content

feat: add Boot class #8604

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 6 additions & 24 deletions public/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
PHP_VERSION
);

exit($message);
header('HTTP/1.1 503 Service Unavailable.', true, 503);
echo $message;

exit(1);
}

/*
Expand Down Expand Up @@ -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();
Expand Down
34 changes: 8 additions & 26 deletions spark
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);

/*
* ---------------------------------------------------------------
Expand Down
237 changes: 237 additions & 0 deletions system/Boot.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
<?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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I always find it difficult to intercept the boot process. I don't want to overcomplicated this, but would it make sense to have an extension of this in App\ to allow devs to modify the boot process? This class could have necessary methods as final. Alternatively there could be another file like app/Config/Boot/Default.php that is always loaded alongside the environment-specific version.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to modify the boot process, extend the Boot class, and run your Boot in index.php.


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);
}
}
2 changes: 2 additions & 0 deletions system/Exceptions/FrameworkException.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
Loading