first commit
This commit is contained in:
476
inc/console/application.class.php
Normal file
476
inc/console/application.class.php
Normal file
@ -0,0 +1,476 @@
|
||||
<?php
|
||||
/**
|
||||
* ---------------------------------------------------------------------
|
||||
* GLPI - Gestionnaire Libre de Parc Informatique
|
||||
* Copyright (C) 2015-2020 Teclib' and contributors.
|
||||
*
|
||||
* http://glpi-project.org
|
||||
*
|
||||
* based on GLPI - Gestionnaire Libre de Parc Informatique
|
||||
* Copyright (C) 2003-2014 by the INDEPNET Development Team.
|
||||
*
|
||||
* ---------------------------------------------------------------------
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This file is part of GLPI.
|
||||
*
|
||||
* GLPI is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GLPI is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GLPI. If not, see <http://www.gnu.org/licenses/>.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
namespace Glpi\Console;
|
||||
|
||||
if (!defined('GLPI_ROOT')) {
|
||||
die("Sorry. You can't access this file directly");
|
||||
}
|
||||
|
||||
use Config;
|
||||
use DB;
|
||||
use GLPI;
|
||||
use Glpi\Application\ErrorHandler;
|
||||
use Glpi\Console\Command\ForceNoPluginsOptionCommandInterface;
|
||||
use Glpi\Console\Command\GlpiCommandInterface;
|
||||
use Glpi\System\RequirementsManager;
|
||||
use Plugin;
|
||||
use Session;
|
||||
use Toolbox;
|
||||
|
||||
use Symfony\Component\Console\Application as BaseApplication;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\Helper;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Exception\CommandNotFoundException;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class Application extends BaseApplication {
|
||||
|
||||
/**
|
||||
* Error code returned when system requirements are missing.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
const ERROR_MISSING_REQUIREMENTS = 128; // start application codes at 128 be sure to be different from commands codes
|
||||
|
||||
/**
|
||||
* Pointer to $CFG_GLPI.
|
||||
* @var array
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @var ErrorHandler
|
||||
*/
|
||||
private $error_handler;
|
||||
|
||||
/**
|
||||
* @var DB
|
||||
*/
|
||||
private $db;
|
||||
|
||||
/**
|
||||
* @var OutputInterface
|
||||
*/
|
||||
private $output;
|
||||
|
||||
public function __construct() {
|
||||
|
||||
parent::__construct('GLPI CLI', GLPI_VERSION);
|
||||
|
||||
$this->initApplication();
|
||||
$this->initDb();
|
||||
$this->initSession();
|
||||
$this->initCache();
|
||||
$this->initConfig();
|
||||
|
||||
$this->computeAndLoadOutputLang();
|
||||
|
||||
// Load core commands only to check if called command prevent or not usage of plugins
|
||||
// Plugin commands will be loaded later
|
||||
$loader = new CommandLoader(false);
|
||||
$this->setCommandLoader($loader);
|
||||
|
||||
$use_plugins = $this->usePlugins();
|
||||
if ($use_plugins) {
|
||||
$this->loadActivePlugins();
|
||||
$loader->registerPluginsCommands();
|
||||
}
|
||||
}
|
||||
|
||||
protected function getDefaultInputDefinition() {
|
||||
|
||||
$definition = new InputDefinition(
|
||||
[
|
||||
new InputArgument(
|
||||
'command',
|
||||
InputArgument::REQUIRED,
|
||||
__('The command to execute')
|
||||
),
|
||||
|
||||
new InputOption(
|
||||
'--help',
|
||||
'-h',
|
||||
InputOption::VALUE_NONE,
|
||||
__('Display this help message')
|
||||
),
|
||||
new InputOption(
|
||||
'--quiet',
|
||||
'-q',
|
||||
InputOption::VALUE_NONE,
|
||||
__('Do not output any message')
|
||||
),
|
||||
new InputOption(
|
||||
'--verbose',
|
||||
'-v|vv|vvv',
|
||||
InputOption::VALUE_NONE,
|
||||
__('Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug')
|
||||
),
|
||||
new InputOption(
|
||||
'--version',
|
||||
'-V',
|
||||
InputOption::VALUE_NONE,
|
||||
__('Display this application version')
|
||||
),
|
||||
new InputOption(
|
||||
'--ansi',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
__('Force ANSI output')
|
||||
),
|
||||
new InputOption(
|
||||
'--no-ansi',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
__('Disable ANSI output')
|
||||
),
|
||||
new InputOption(
|
||||
'--no-interaction',
|
||||
'-n',
|
||||
InputOption::VALUE_NONE,
|
||||
__('Do not ask any interactive question')
|
||||
),
|
||||
new InputOption(
|
||||
'--config-dir',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
__('Configuration directory to use')
|
||||
),
|
||||
new InputOption(
|
||||
'--no-plugins',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
__('Disable GLPI plugins (unless commands forces plugins loading)')
|
||||
),
|
||||
new InputOption(
|
||||
'--lang',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
__('Output language (default value is existing GLPI "language" configuration or "en_GB")')
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
return $definition;
|
||||
}
|
||||
|
||||
protected function configureIO(InputInterface $input, OutputInterface $output) {
|
||||
|
||||
global $CFG_GLPI;
|
||||
|
||||
$this->output = $output;
|
||||
$this->error_handler->setOutputHandler($output);
|
||||
|
||||
parent::configureIO($input, $output);
|
||||
|
||||
// Trigger error on invalid lang. This is not done before as error handler would not be set.
|
||||
$lang = $input->getParameterOption('--lang', null, true);
|
||||
if (null !== $lang && !array_key_exists($lang, $CFG_GLPI['languages'])) {
|
||||
throw new RuntimeException(
|
||||
sprintf(__('Invalid "--lang" option value "%s".'), $lang)
|
||||
);
|
||||
}
|
||||
|
||||
if ($output->getVerbosity() === OutputInterface::VERBOSITY_DEBUG) {
|
||||
Toolbox::setDebugMode(Session::DEBUG_MODE, 0, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns output handler.
|
||||
*
|
||||
* @return OutputInterface
|
||||
*/
|
||||
public function getOutput() {
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) {
|
||||
|
||||
$begin_time = microtime(true);
|
||||
|
||||
if ($command instanceof GlpiCommandInterface && $command->mustCheckMandatoryRequirements()
|
||||
&& !$this->checkCoreMandatoryRequirements()) {
|
||||
return self::ERROR_MISSING_REQUIREMENTS;
|
||||
}
|
||||
|
||||
$result = parent::doRunCommand($command, $input, $output);
|
||||
|
||||
if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE) {
|
||||
$output->writeln(
|
||||
sprintf(
|
||||
__('Time elapsed: %s.'),
|
||||
Helper::formatTime(microtime(true) - $begin_time)
|
||||
)
|
||||
);
|
||||
$output->writeln(
|
||||
sprintf(
|
||||
__('Memory usage: %s.'),
|
||||
Helper::formatMemory(memory_get_peak_usage(true))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initalize GLPI.
|
||||
*
|
||||
* @global array $CFG_GLPI
|
||||
* @global GLPI $GLPI
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function initApplication() {
|
||||
|
||||
// Disable debug at bootstrap (will be re-enabled later if requested by verbosity level).
|
||||
global $CFG_GLPI;
|
||||
$CFG_GLPI = array_merge(
|
||||
$CFG_GLPI,
|
||||
[
|
||||
'debug_sql' => 0,
|
||||
'debug_vars' => 0,
|
||||
]
|
||||
);
|
||||
|
||||
global $GLPI;
|
||||
$GLPI = new GLPI();
|
||||
$GLPI->initLogger();
|
||||
$this->error_handler = $GLPI->initErrorHandler();
|
||||
|
||||
Config::detectRootDoc();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize database connection.
|
||||
*
|
||||
* @global DB $DB
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
private function initDb() {
|
||||
|
||||
if (!class_exists('DB', false) || !class_exists('mysqli', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
global $DB;
|
||||
$DB = new DB();
|
||||
$this->db = $DB;
|
||||
|
||||
if (!$this->db->connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
$checkdb = Config::displayCheckDbEngine();
|
||||
$message = ob_get_clean();
|
||||
if ($checkdb > 0) {
|
||||
throw new RuntimeException($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize GLPI session.
|
||||
* This is mandatory to init cache and load languages.
|
||||
*
|
||||
* @TODO Do not use session for console.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function initSession() {
|
||||
|
||||
if (!is_writable(GLPI_SESSION_DIR)) {
|
||||
throw new RuntimeException(
|
||||
sprintf(__('Cannot write in "%s" directory.'), GLPI_SESSION_DIR)
|
||||
);
|
||||
}
|
||||
|
||||
Session::setPath();
|
||||
Session::start();
|
||||
|
||||
// Default value for use mode
|
||||
$_SESSION['glpi_use_mode'] = Session::NORMAL_MODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize GLPI cache.
|
||||
*
|
||||
* @global Laminas\Cache\Storage\StorageInterface $GLPI_CACHE
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function initCache() {
|
||||
|
||||
global $GLPI_CACHE;
|
||||
$GLPI_CACHE = Config::getCache('cache_db');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize GLPI configuration.
|
||||
*
|
||||
* @global array $CFG_GLPI
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function initConfig() {
|
||||
|
||||
global $CFG_GLPI;
|
||||
$this->config = &$CFG_GLPI;
|
||||
|
||||
if (!($this->db instanceof DB) || !$this->db->connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
Config::loadLegacyConfiguration(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute and load output language.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
private function computeAndLoadOutputLang() {
|
||||
|
||||
// 1. Check in command line arguments
|
||||
$input = new ArgvInput();
|
||||
$lang = $input->getParameterOption('--lang', null, true);
|
||||
|
||||
if (null !== $lang && !$this->isLanguageValid($lang)) {
|
||||
// Unset requested lang if invalid
|
||||
$lang = null;
|
||||
}
|
||||
|
||||
// 2. Check in GLPI configuration
|
||||
if (null === $lang && array_key_exists('language', $this->config)
|
||||
&& $this->isLanguageValid($this->config['language'])) {
|
||||
$lang = $this->config['language'];
|
||||
}
|
||||
|
||||
// 3. Use default value
|
||||
if (null === $lang) {
|
||||
$lang = 'en_GB';
|
||||
}
|
||||
|
||||
$_SESSION['glpilanguage'] = $lang;
|
||||
|
||||
Session::loadLanguage('', $this->usePlugins());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a language is valid.
|
||||
*
|
||||
* @param string $language
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function isLanguageValid($language) {
|
||||
return is_array($this->config)
|
||||
&& array_key_exists('languages', $this->config)
|
||||
&& array_key_exists($language, $this->config['languages']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load active plugins.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function loadActivePlugins() {
|
||||
|
||||
if (!($this->db instanceof DB) || !$this->db->connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
$plugin = new Plugin();
|
||||
$plugin->init(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not plugins have to be used.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function usePlugins() {
|
||||
|
||||
$input = new ArgvInput();
|
||||
|
||||
try {
|
||||
$command = $this->find($this->getCommandName($input));
|
||||
if ($command instanceof ForceNoPluginsOptionCommandInterface) {
|
||||
return !$command->getNoPluginsOptionValue();
|
||||
}
|
||||
} catch (CommandNotFoundException $e) {
|
||||
// Command will not be found at this point if it is a plugin command
|
||||
$command = null; // Say hello to CS checker
|
||||
}
|
||||
|
||||
return !$input->hasParameterOption('--no-plugins', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if core mandatory requirements are OK.
|
||||
*
|
||||
* @return boolean true if requirements are OK, false otherwise
|
||||
*/
|
||||
private function checkCoreMandatoryRequirements(): bool {
|
||||
$db = property_exists($this, 'db') ? $this->db : null;
|
||||
|
||||
$requirements_manager = new RequirementsManager();
|
||||
$core_requirements = $requirements_manager->getCoreRequirementList(
|
||||
$db instanceof \DBmysql && $db->connected ? $db : null
|
||||
);
|
||||
|
||||
if ($core_requirements->hasMissingMandatoryRequirements()) {
|
||||
$message = __('Some mandatory system requirements are missing.')
|
||||
. ' '
|
||||
. __('Run "php bin/console glpi:system:check_requirements" for more details.');
|
||||
$this->output->writeln(
|
||||
'<error>' . $message . '</error>',
|
||||
OutputInterface::VERBOSITY_QUIET
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user