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
{