Skip to content

Commit

Permalink
Refactor the GLPI boot logic
Browse files Browse the repository at this point in the history
 - move services initialization to PostBoot listeners;
 - mutualize services booting with the console application;
 - move specific CLI logic in the `/front/cron.php` script;
 - move database status checks into a dedicated request listener;
 - remove the `--no-plugins` feature from the console to simplify the boot process.
  • Loading branch information
Pierstoval authored and trasher committed Dec 20, 2024
1 parent e5db895 commit 0a50164
Show file tree
Hide file tree
Showing 64 changed files with 876 additions and 789 deletions.
12 changes: 0 additions & 12 deletions .phpstan-baseline.php
Original file line number Diff line number Diff line change
Expand Up @@ -2437,18 +2437,6 @@
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Console/Application.php',
];
$ignoreErrors[] = [
'message' => '#^Call to function property_exists\\(\\) with \\$this\\(Glpi\\\\Console\\\\Application\\) and \'db\' will always evaluate to true\\.$#',
'identifier' => 'function.alreadyNarrowedType',
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Console/Application.php',
];
$ignoreErrors[] = [
'message' => '#^Property Glpi\\\\Console\\\\Application\\:\\:\\$error_handler is unused\\.$#',
'identifier' => 'property.unused',
'count' => 1,
'path' => __DIR__ . '/src/Glpi/Console/Application.php',
];
$ignoreErrors[] = [
'message' => '#^Strict comparison using \\!\\=\\= between null and \'development\' will always evaluate to true\\.$#',
'identifier' => 'notIdentical.alwaysTrue',
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ The present file will list all changes made to the project; according to the
- `Contract::showShort()`
- `DbUtils::closeDBConnections()`
- `DbUtils::regenerateTreeCompleteName()`
- `DBConnection::displayMySQLError()`
- `DBmysql::error` property.
- `Document::getImage()`
- `Document::showUploadedFilesDropdown()`
Expand All @@ -388,6 +389,7 @@ The present file will list all changes made to the project; according to the
- `Glpi\Api\API::showDebug()`
- `Glpi\Api\API::returnSanitizedContent()`
- `Glpi\Application\ErrorHandler::handleSqlError()`
- `Glpi\Console\Command\ForceNoPluginsOptionCommandInterface` class
- `Glpi\Dashboard\Filter::dates()`
- `Glpi\Dashboard\Filter::dates_mod()`
- `Glpi\Dashboard\Filter::itilcategory()`
Expand Down
8 changes: 1 addition & 7 deletions bin/console
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,5 @@ if (array_key_exists('config-dir', $options)) {
require_once dirname(__DIR__) . '/vendor/autoload.php';

$kernel = new \Glpi\Kernel\Kernel($options['env'] ?? null);
$kernel->loadCliConsoleOnlyConfig();

if (file_exists(GLPI_CONFIG_DIR . '/config_db.php')) {
include_once GLPI_CONFIG_DIR . '/config_db.php';
}

$application = new \Glpi\Console\Application();
$application = new \Glpi\Console\Application($kernel);
$application->run();
32 changes: 5 additions & 27 deletions dependency_injection/legacyConfigProviders.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,7 @@
namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use Glpi\Config\LegacyConfigProviderInterface;
use Glpi\Config\LegacyConfigurators\CleanPHPSelfParam;
use Glpi\Config\LegacyConfigurators\ConfigRest;
use Glpi\Config\LegacyConfigurators\CustomObjectsAutoloader;
use Glpi\Config\LegacyConfigurators\CustomObjectsBootstrap;
use Glpi\Config\LegacyConfigurators\InitializeDbConnection;
use Glpi\Config\LegacyConfigurators\InitializePlugins;
use Glpi\Config\LegacyConfigurators\LoadLegacyConfiguration;
use Glpi\Config\LegacyConfigurators\ProfilerStart;
use Glpi\Config\LegacyConfigurators\SessionConfig;
use Glpi\Config\LegacyConfigurators\SessionStart;
use Glpi\Config\LegacyConfigurators\StandardIncludes;
use Glpi\Config\LegacyConfigurators;

return static function (ContainerConfigurator $container): void {
$services = $container->services();
Expand All @@ -65,22 +55,10 @@
* ⚠ Here, ORDER of definition matters!
*/

$services->set(ProfilerStart::class)->tag($tagName, ['priority' => 200]);
$services->set(InitializeDbConnection::class)->tag($tagName, ['priority' => 190]);
$services->set(LoadLegacyConfiguration::class)->tag($tagName, ['priority' => 180]);
$services->set(SessionStart::class)->tag($tagName, ['priority' => 170]);
$services->set(StandardIncludes::class)->tag($tagName, ['priority' => 160]);
$services->set(CleanPHPSelfParam::class)->tag($tagName, ['priority' => 150]);
$services->set(SessionConfig::class)->tag($tagName, ['priority' => 130]);

// Must be done before plugins initialization, to allow plugin to work with concrete class names.
$services->set(CustomObjectsAutoloader::class)->tag($tagName, ['priority' => 120]);

$services->set(InitializePlugins::class)->tag($tagName, ['priority' => 110]);

// Must be done after plugins initialization, to allow plugin to register new capacities.
$services->set(CustomObjectsBootstrap::class)->tag($tagName, ['priority' => 100]);
$services->set(LegacyConfigurators\StandardIncludes::class)->tag($tagName, ['priority' => 160]);
$services->set(LegacyConfigurators\CleanPHPSelfParam::class)->tag($tagName, ['priority' => 150]);
$services->set(LegacyConfigurators\SessionConfig::class)->tag($tagName, ['priority' => 130]);

// FIXME: This class MUST stay at the end until the entire config is revamped.
$services->set(ConfigRest::class)->tag($tagName, ['priority' => 10]);
$services->set(LegacyConfigurators\ConfigRest::class)->tag($tagName, ['priority' => 10]);
};
1 change: 1 addition & 0 deletions dependency_injection/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
$services->load('Glpi\Config\\', $projectDir . '/src/Glpi/Config');
$services->load('Glpi\Controller\\', $projectDir . '/src/Glpi/Controller');
$services->load('Glpi\Http\\', $projectDir . '/src/Glpi/Http');
$services->load('Glpi\Kernel\\Listener\\', $projectDir . '/src/Glpi/Kernel/Listener');
$services->load('Glpi\DependencyInjection\\', $projectDir . '/src/Glpi/DependencyInjection');
$services->load('Glpi\Progress\\', $projectDir . '/src/Glpi/Progress')->exclude($projectDir . '/src/Glpi/Progress/SessionProgress.php');

Expand Down
50 changes: 44 additions & 6 deletions front/cron.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@
* ---------------------------------------------------------------------
*/

/**
* @var \DBmysql|null $DB
* @var array $CFG_GLPI
*/
global $DB, $CFG_GLPI;

if (PHP_SAPI === 'cli') {
// Check the resources state before trying to instanciate the Kernel.
// It must be done here as this check must be done even when the Kernel
Expand All @@ -43,13 +49,45 @@
require_once dirname(__DIR__) . '/vendor/autoload.php';

$kernel = new \Glpi\Kernel\Kernel();
$kernel->loadCommonGlobalConfig();
}
$kernel->boot();

/**
* @var array $CFG_GLPI
*/
global $CFG_GLPI;
// Handle the `--debug` argument
$debug = array_search('--debug', $_SERVER['argv']);
if ($debug) {
$_SESSION['glpi_use_mode'] = Session::DEBUG_MODE;
unset($_SERVER['argv'][$debug]);
$_SERVER['argv'] = array_values($_SERVER['argv']);
$_SERVER['argc']--;
}

if ($CFG_GLPI['maintenance_mode'] ?? false) {
echo 'Service is down for maintenance. It will be back shortly.' . PHP_EOL;
exit();
}

if (!($DB instanceof DBmysql)) {
echo sprintf(
'ERROR: The database configuration file "%s" is missing or is corrupted. You have to either restart the install process, or restore this file.',
GLPI_CONFIG_DIR . '/config_db.php'
) . PHP_EOL;
exit();
}

if (!$DB->connected) {
echo 'ERROR: The connection to the SQL server could not be established. Please check your configuration.' . PHP_EOL;
exit();
}

if (!Config::isLegacyConfigurationLoaded()) {
echo 'ERROR: Unable to load the GLPI configuration from the database.' . PHP_EOL;
exit();
}

if (!defined('SKIP_UPDATES') && !Update::isDbUpToDate()) {
echo 'The GLPI codebase has been updated. The update of the GLPI database is necessary.' . PHP_EOL;
exit();
}
}

// Ensure current directory when run from crontab
chdir(__DIR__);
Expand Down
13 changes: 5 additions & 8 deletions install/install.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@
Session::loadLanguage(with_plugins: false);
}

Session::checkCookieSecureConfig();

//Print a correct Html header for application
function header_html($etape)
{
Expand Down Expand Up @@ -518,11 +516,12 @@ function checkConfigFile()

checkConfigFile();

// Add a flag that will be used to validate that installation can be processed.
// This flag is put here just after checking that DB config file does not exist yet.
// It is mandatory to validate that `Etape_4` to `Etape_6` are not used outside installation process
// to change GLPI base URL without even being authenticated.
// Add a flag that will be used to validate that installation can be processed.
// This flag is put here just after checking that DB config file does not exist yet.
// It is mandatory to validate that installation endpoints are not used outside installation process
// to alter the GLPI database or configuration.
$_SESSION['can_process_install'] = true;
$_SESSION['is_installing'] = true;

header_html(__("Select your language"));
choose_language();
Expand All @@ -532,8 +531,6 @@ function checkConfigFile()
$_POST["db_pass"] = rawurldecode($_POST["db_pass"]);
}

$_SESSION['is_installing'] = true;

switch ($_POST["install"]) {
case "lang_select": // lang ok, go accept licence
checkConfigFile();
Expand Down
21 changes: 5 additions & 16 deletions install/update.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,30 +37,21 @@
use Glpi\Cache\CacheManager;
use Glpi\Toolbox\VersionParser;

include_once(GLPI_CONFIG_DIR . "/config_db.php");

/**
* @var \DBmysql|null $DB
* @var \Psr\SimpleCache\CacheInterface $GLPI_CACHE
* @var \Update $update
* @var bool $HEADER_LOADED
*/
global $DB,
$GLPI_CACHE,
$update,
$HEADER_LOADED;
$GLPI_CACHE,
$update,
$HEADER_LOADED;

$GLPI_CACHE = (new CacheManager())->getInstallerCacheInstance();

Session::checkCookieSecureConfig();

if (!($DB instanceof DBmysql)) { // $DB can have already been init in install.php script
$DB = new DB();
}
$DB->disableTableCaching(); //prevents issues on fieldExists upgrading from old versions

Config::loadLegacyConfiguration();

$update = new Update($DB);

if (isset($_POST['update_end'])) {
Expand Down Expand Up @@ -146,10 +137,6 @@ function showSecurityKeyCheckForm()
//Debut du script
$HEADER_LOADED = true;

Session::start();

Session::loadLanguage('', false);

// Send UTF8 Headers
header("Content-Type: text/html; charset=UTF-8");

Expand Down Expand Up @@ -229,6 +216,8 @@ function showSecurityKeyCheckForm()
doUpdateDb();
echo "</div>";

Session::destroy(); // Remove session data set by web installation

$_SESSION['telemetry_from_install'] = true;

TemplateRenderer::getInstance()->display('install/update.html.twig', [
Expand Down
8 changes: 6 additions & 2 deletions phpunit/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,21 @@

define('FIXTURE_DIR', __DIR__ . "/../tests/fixtures");

global $CFG_GLPI, $GLPI_CACHE;
global $GLPI_CACHE;

require_once dirname(__DIR__) . '/vendor/autoload.php';

$kernel = new Kernel('testing');
$kernel->loadCommonGlobalConfig();
$kernel->boot();

if (!file_exists(GLPI_CONFIG_DIR . '/config_db.php')) {
echo("\nConfiguration file for tests not found\n\nrun: php bin/console database:install --env=testing ...\n\n");
exit(1);
}
if (!defined('SKIP_UPDATES') && !Update::isDbUpToDate()) {
echo 'The GLPI codebase has been updated. The update of the GLPI database is necessary.' . PHP_EOL;
exit(1);
}

//init cache
if (file_exists(GLPI_CONFIG_DIR . DIRECTORY_SEPARATOR . CacheManager::CONFIG_FILENAME)) {
Expand Down
23 changes: 0 additions & 23 deletions src/DBConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -646,29 +646,6 @@ public static function getHistoryMaxDate($DBconnection)
}


/**
* Display a common mysql connection error
**/
public static function displayMySQLError()
{
/** @var \DBmysql $DB */
global $DB;

$fr_msg = "Le serveur Mysql est inaccessible. Vérifiez votre configuration.";
$en_msg = "A link to the SQL server could not be established. Please check your configuration.";

if (!isCommandLine()) {
Html::nullHeader("Mysql Error", '');
echo "<div class='center'><p class ='b'>$en_msg</p><p class='b'>$fr_msg</p></div>";
Html::nullFooter();
} else {
echo "$en_msg\n$fr_msg\n";
}

exit(1);
}


/**
* @param $name
**/
Expand Down
3 changes: 0 additions & 3 deletions src/Glpi/Config/LegacyConfigurators/CleanPHPSelfParam.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,17 @@
use Glpi\Config\ConfigProviderHasRequestTrait;
use Glpi\Config\ConfigProviderWithRequestInterface;
use Glpi\Config\LegacyConfigProviderInterface;
use Glpi\Debug\Profiler;

final class CleanPHPSelfParam implements LegacyConfigProviderInterface, ConfigProviderWithRequestInterface
{
use ConfigProviderHasRequestTrait;

public function execute(): void
{
Profiler::getInstance()->start('CleanPHPSelfParam::execute', Profiler::CATEGORY_BOOT);
// Security of PHP_SELF
$self = \Html::cleanParametersURL($this->getRequest()->server->get('PHP_SELF'));

$_SERVER['PHP_SELF'] = $self;
$this->getRequest()->server->set('PHP_SELF', $self);
Profiler::getInstance()->stop('CleanPHPSelfParam::execute');
}
}
18 changes: 1 addition & 17 deletions src/Glpi/Config/LegacyConfigurators/ConfigRest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
namespace Glpi\Config\LegacyConfigurators;

use Glpi\Config\LegacyConfigProviderInterface;
use Glpi\Debug\Profiler;
use Session;

final readonly class ConfigRest implements LegacyConfigProviderInterface
Expand All @@ -45,21 +44,9 @@ public function execute(): void
/**
* @var array $CFG_GLPI
* @var \Psr\SimpleCache\CacheInterface $GLPI_CACHE
* @var bool $FOOTER_LOADED
* @var bool $HEADER_LOADED
* @var string $CURRENTCSRFTOKEN
*/
global $CFG_GLPI,
$GLPI_CACHE,
$FOOTER_LOADED, $HEADER_LOADED,
$CURRENTCSRFTOKEN
;
global $CFG_GLPI, $GLPI_CACHE;

// Mark if Header is loaded or not :
$HEADER_LOADED = false;
$FOOTER_LOADED = false;

Profiler::getInstance()->start('ConfigRest::execute', Profiler::CATEGORY_BOOT);
// Security : check CSRF token
if (!isAPI() && count($_POST) > 0) {
if (preg_match(':' . $CFG_GLPI['root_doc'] . '(/(plugins|marketplace)/[^/]*|)/ajax/:', $_SERVER['REQUEST_URI']) === 1) {
Expand All @@ -73,8 +60,6 @@ public function execute(): void
Session::checkCSRF($_POST);
}
}
// SET new global Token
$CURRENTCSRFTOKEN = '';

// Manage profile change
if (isset($_REQUEST["force_profile"]) && ($_SESSION['glpiactiveprofile']['id'] ?? -1) != $_REQUEST["force_profile"]) {
Expand Down Expand Up @@ -105,6 +90,5 @@ public function execute(): void
) {
Session::loadGroups();
}
Profiler::getInstance()->stop('ConfigRest::execute');
}
}
Loading

0 comments on commit 0a50164

Please sign in to comment.