diff --git a/application/clipage.class.inc.php b/application/clipage.class.inc.php index 25153d17e..db348322f 100644 --- a/application/clipage.class.inc.php +++ b/application/clipage.class.inc.php @@ -29,9 +29,13 @@ require_once(APPROOT."/application/webpage.class.inc.php"); class CLIPage implements Page { - function __construct($s_title) + /** @var string */ + public $s_title; + + function __construct($s_title) { - } + $this->s_title = $s_title; + } public function output() { @@ -48,22 +52,22 @@ class CLIPage implements Page public function add($sText) { echo $sText; - } + } public function p($sText) { echo $sText."\n"; - } + } public function pre($sText) { echo $sText."\n"; - } + } public function add_comment($sText) { echo "#".$sText."\n"; - } + } public function table($aConfig, $aData, $aParams = array()) { @@ -93,5 +97,3 @@ class CLIPage implements Page } } } - -?> diff --git a/datamodels/2.x/itop-backup/backup.php b/datamodels/2.x/itop-backup/backup.php index 116f17564..4b93379ef 100644 --- a/datamodels/2.x/itop-backup/backup.php +++ b/datamodels/2.x/itop-backup/backup.php @@ -134,6 +134,8 @@ set_time_limit(0); if (utils::IsModeCLI()) { $oP = new CLIPage("iTop - Database Backup"); + + SetupUtils::CheckPhpAndExtensionsForCli($oP); } else { diff --git a/datamodels/2.x/itop-backup/check-backup.php b/datamodels/2.x/itop-backup/check-backup.php index 4f8a5cfed..4f17b32e1 100644 --- a/datamodels/2.x/itop-backup/check-backup.php +++ b/datamodels/2.x/itop-backup/check-backup.php @@ -250,6 +250,8 @@ catch(Exception $e) if (utils::IsModeCLI()) { + SetupUtils::CheckPhpAndExtensionsForCli(new CLIPage('Check backup utility')); + echo date('Y-m-d H:i:s')." - running check-backup utility\n"; try { diff --git a/setup/setuputils.class.inc.php b/setup/setuputils.class.inc.php index 2b260890c..c34921241 100644 --- a/setup/setuputils.class.inc.php +++ b/setup/setuputils.class.inc.php @@ -39,6 +39,49 @@ class CheckResult $this->sLabel = $sLabel; $this->sDescription = $sDescription; } + + /** + * @return string + * @since 2.7.1 2.8.0 N°2214 + */ + public function __toString() + { + $sPrintDesc = (empty($this->sDescription)) ? '' : " ({$this->sDescription})"; + return "{$this->sLabel}$sPrintDesc"; + } + + /** + * @param \CheckResult[] $aResults + * + * @return \CheckResult[] only elements that are error (iSeverity===ERROR) + * + * @since 2.7.1 2.8.0 N°2214 + */ + public static function KeepOnlyErrors($aResults) + { + return array_filter($aResults, + static function ($v) + { + if ($v->iSeverity === CheckResult::ERROR) { + return $v; + } + }, + ARRAY_FILTER_USE_BOTH); + } + + /** + * @param \CheckResult[] $aResults + * @return string[] + * @uses \CheckResult::__toString + * + * @since 2.7.1 2.8.0 N°2214 + */ + public static function FromObjetsToStrings($aResults) + { + return array_map(function($value) { + return $value->__toString(); + }, $aResults); + } } /** @@ -370,6 +413,37 @@ class SetupUtils return $aResult; } + /** + * @param \CLIPage $oCliPage + * @param int $iExitCode + * + * @since 2.7.1 2.8.0 N°2214 + */ + public static function CheckPhpAndExtensionsForCli($oCliPage, $iExitCode = -1) + { + $aPhpCheckResults = self::CheckPhpAndExtensions(); + $aPhpCheckErrors = CheckResult::KeepOnlyErrors($aPhpCheckResults); + if (empty($aPhpCheckErrors)) + { + return; + } + + $sMessageTitle = 'Error: PHP minimum requirements are not met !'; + $oCliPage->p($sMessageTitle); + $aPhpCheckErrorsForPrint = CheckResult::FromObjetsToStrings($aPhpCheckErrors); + foreach ($aPhpCheckErrorsForPrint as $sError) + { + $oCliPage->p(' * '.$sError); + } + $oCliPage->output(); + + // some CLI scripts are launched automatically + // we need a log so that we don't miss errors after migration ! + IssueLog::Error($oCliPage->s_title.' '.$sMessageTitle, 'CLI', $aPhpCheckErrorsForPrint); + + exit($iExitCode); + } + /** * @param CheckResult[] $aResult checks log */ diff --git a/synchro/synchro_exec.php b/synchro/synchro_exec.php index d212ca776..df22e9219 100644 --- a/synchro/synchro_exec.php +++ b/synchro/synchro_exec.php @@ -72,6 +72,7 @@ function ReadMandatoryParam($oP, $sParam, $sSanitizationFilter = 'parameter') if (utils::IsModeCLI()) { $oP = new CLIPage(Dict::S("TitleSynchroExecution")); + SetupUtils::CheckPhpAndExtensionsForCli($oP, -2); } else { diff --git a/synchro/synchro_import.php b/synchro/synchro_import.php index 0c065d03a..84b905fc0 100644 --- a/synchro/synchro_import.php +++ b/synchro/synchro_import.php @@ -255,6 +255,7 @@ class CLILikeWebPage extends WebPage if (utils::IsModeCLI()) { $oP = new CLIPage(Dict::S('TitleSynchroExecution')); + SetupUtils::CheckPhpAndExtensionsForCli($oP, -2); } else { diff --git a/webservices/cron.php b/webservices/cron.php index 145c758fe..b7717cede 100644 --- a/webservices/cron.php +++ b/webservices/cron.php @@ -60,7 +60,7 @@ function ReadMandatoryParam($oP, $sParam, $sSanitizationFilter = 'parameter') function UsageAndExit($oP) { - $bModeCLI = utils::IsModeCLI(); + $bModeCLI = ($oP instanceof CLIPage); if ($bModeCLI) { @@ -477,9 +477,12 @@ function ReorderProcesses(&$aProcesses, $aTasks, $oNow, $bVerbose, &$oP) set_time_limit(0); // Some background actions may really take long to finish (like backup) -if (utils::IsModeCLI()) +$bIsModeCLI = utils::IsModeCLI(); +if ($bIsModeCLI) { $oP = new CLIPage("iTop - cron"); + + SetupUtils::CheckPhpAndExtensionsForCli($oP, EXIT_CODE_FATAL); } else { @@ -497,7 +500,7 @@ catch (Exception $e) exit(EXIT_CODE_FATAL); } -if (utils::IsModeCLI()) +if ($bIsModeCLI) { // Next steps: // specific arguments: 'csvfile' diff --git a/webservices/export-v2.php b/webservices/export-v2.php index 1fd7d6f01..8b193fc9a 100644 --- a/webservices/export-v2.php +++ b/webservices/export-v2.php @@ -32,6 +32,12 @@ require_once(APPROOT.'/core/bulkexport.class.inc.php'); require_once(APPROOT.'/application/startup.inc.php'); + +const EXIT_CODE_ERROR = -1; +const EXIT_CODE_FATAL = -2; + + + function ReportErrorAndExit($sErrorMessage) { if (utils::IsModeCLI()) @@ -39,14 +45,14 @@ function ReportErrorAndExit($sErrorMessage) $oP = new CLIPage("iTop - Export"); $oP->p('ERROR: '.$sErrorMessage); $oP->output(); - exit(-1); + exit(EXIT_CODE_ERROR); } else { $oP = new WebPage("iTop - Export"); $oP->p('ERROR: '.$sErrorMessage); $oP->output(); - exit(-1); + exit(EXIT_CODE_ERROR); } } @@ -58,7 +64,7 @@ function ReportErrorAndUsage($sErrorMessage) $oP->p('ERROR: '.$sErrorMessage); Usage($oP); $oP->output(); - exit(-1); + exit(EXIT_CODE_ERROR); } else { @@ -66,7 +72,7 @@ function ReportErrorAndUsage($sErrorMessage) $oP->p('ERROR: '.$sErrorMessage); Usage($oP); $oP->output(); - exit(-1); + exit(EXIT_CODE_ERROR); } } @@ -565,6 +571,8 @@ function DoExport(WebPage $oP, BulkExport $oExporter, $bInteractive = false) ///////////////////////////////////////////////////////////////////////////// if (utils::IsModeCLI()) { + SetupUtils::CheckPhpAndExtensionsForCli(new CLIPage('iTop - Export')); + try { // Do this before loging, in order to allow setting user credentials from within the file @@ -573,7 +581,7 @@ if (utils::IsModeCLI()) catch(Exception $e) { echo "Error: ".$e->GetMessage()."
\n"; - exit(-2); + exit(EXIT_CODE_FATAL); } $sAuthUser = utils::ReadParam('auth_user', null, true /* Allow CLI */, 'raw_data'); diff --git a/webservices/export.php b/webservices/export.php index ee127ca32..f19d03eaf 100644 --- a/webservices/export.php +++ b/webservices/export.php @@ -29,6 +29,11 @@ require_once(APPROOT.'/application/excelexporter.class.inc.php'); require_once(APPROOT.'/application/startup.inc.php'); + +const EXIT_CODE_ERROR = -1; +const EXIT_CODE_FATAL = -2; + + try { // Do this before loging, in order to allow setting user credentials from within the file @@ -37,12 +42,15 @@ try catch(Exception $e) { echo "Error: ".$e->GetMessage()."
\n"; - exit -2; + exit(EXIT_CODE_FATAL); } if (utils::IsModeCLI()) { - $sAuthUser = utils::ReadParam('auth_user', null, true /* Allow CLI */, 'raw_data'); + $oP = new CLIPage("iTop - Export"); + SetupUtils::CheckPhpAndExtensionsForCli($oP, EXIT_CODE_FATAL); + + $sAuthUser = utils::ReadParam('auth_user', null, true /* Allow CLI */, 'raw_data'); $sAuthPwd = utils::ReadParam('auth_pwd', null, true /* Allow CLI */, 'raw_data'); if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd)) @@ -51,10 +59,9 @@ if (utils::IsModeCLI()) } else { - $oP = new CLIPage("iTop - Export"); - $oP->p("Access restricted or wrong credentials ('$sAuthUser')"); + $oP->p("Access restricted or wrong credentials ('$sAuthUser')"); $oP->output(); - exit -1; + exit(EXIT_CODE_ERROR); } } else @@ -74,7 +81,7 @@ if (utils::IsArchiveMode() && !UserRights::CanBrowseArchive()) $oP = new CLIPage("iTop - Export"); $oP->p("The user account is not authorized to access the archives"); $oP->output(); - exit -1; + exit(EXIT_CODE_ERROR); } $bLocalize = (utils::ReadParam('no_localize', 0) != 1); diff --git a/webservices/import.php b/webservices/import.php index c43071822..7907bcfcd 100644 --- a/webservices/import.php +++ b/webservices/import.php @@ -212,6 +212,7 @@ function ReadMandatoryParam($oP, $sParam, $sSanitizationFilter) if (utils::IsModeCLI()) { $oP = new CLIPage("iTop - Bulk import"); + SetupUtils::CheckPhpAndExtensionsForCli($oP, -2); } else {