mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-12 23:14:18 +01:00
Merge branch 'support/3.2' into develop
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -25,7 +26,7 @@
|
||||
|
||||
use Combodo\iTop\Application\WebPage\WebPage;
|
||||
|
||||
define('SAFE_MINIMUM_MEMORY', 256*1024*1024);
|
||||
define('SAFE_MINIMUM_MEMORY', 256 * 1024 * 1024);
|
||||
|
||||
require_once('../approot.inc.php');
|
||||
require_once(APPROOT.'/application/application.inc.php');
|
||||
@@ -39,37 +40,28 @@ LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be
|
||||
require_once(APPROOT.'/setup/setuppage.class.inc.php');
|
||||
require_once(APPROOT.'/setup/xmldataloader.class.inc.php');
|
||||
|
||||
|
||||
function SetMemoryLimit($oP)
|
||||
{
|
||||
$sMemoryLimit = trim(ini_get('memory_limit'));
|
||||
if (empty($sMemoryLimit))
|
||||
{
|
||||
if (empty($sMemoryLimit)) {
|
||||
// On some PHP installations, memory_limit does not exist as a PHP setting!
|
||||
// (encountered on a 5.2.0 under Windows)
|
||||
// In that case, ini_set will not work, let's keep track of this and proceed with the data load
|
||||
$oP->p("No memory limit has been defined in this instance of PHP");
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p("No memory limit has been defined in this instance of PHP");
|
||||
} else {
|
||||
// Check that the limit will allow us to load the data
|
||||
//
|
||||
$iMemoryLimit = utils::ConvertToBytes($sMemoryLimit);
|
||||
if (!utils::IsMemoryLimitOk($iMemoryLimit, SAFE_MINIMUM_MEMORY))
|
||||
{
|
||||
if (ini_set('memory_limit', SAFE_MINIMUM_MEMORY) === FALSE)
|
||||
{
|
||||
$oP->p("memory_limit is too small: $iMemoryLimit and can not be increased by the script itself.");
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p("memory_limit increased from $iMemoryLimit to ".SAFE_MINIMUM_MEMORY.".");
|
||||
if (!utils::IsMemoryLimitOk($iMemoryLimit, SAFE_MINIMUM_MEMORY)) {
|
||||
if (ini_set('memory_limit', SAFE_MINIMUM_MEMORY) === false) {
|
||||
$oP->p("memory_limit is too small: $iMemoryLimit and can not be increased by the script itself.");
|
||||
} else {
|
||||
$oP->p("memory_limit increased from $iMemoryLimit to ".SAFE_MINIMUM_MEMORY.".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Main
|
||||
@@ -87,9 +79,7 @@ $sFileName = Utils::ReadParam('file', '', false, 'raw_data');
|
||||
|
||||
$oP = new WebPage("iTop - Backoffice data loader");
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
// Note: the data model must be loaded first
|
||||
$oDataLoader = new XMLDataLoader();
|
||||
|
||||
@@ -102,8 +92,7 @@ try
|
||||
|
||||
SetMemoryLimit($oP);
|
||||
|
||||
|
||||
// The XMLDataLoader constructor has initialized the DB, let's start a transaction
|
||||
// The XMLDataLoader constructor has initialized the DB, let's start a transaction
|
||||
CMDBSource::Query('START TRANSACTION');
|
||||
|
||||
$oP->p("Starting data load.");
|
||||
@@ -128,26 +117,21 @@ try
|
||||
}
|
||||
}
|
||||
$aWarnings = $oDataLoader->GetWarnings();
|
||||
if (count($aWarnings) > 0)
|
||||
{
|
||||
if (count($aWarnings) > 0) {
|
||||
$oP->p('Warnings ('.count($aWarnings).')');
|
||||
foreach ($aWarnings as $sMsg)
|
||||
{
|
||||
foreach ($aWarnings as $sMsg) {
|
||||
$oP->p(' * '.$sMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$oP->p("An error happened while loading the data: ".$e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
$oP->p("An error happened while loading the data: ".$e->getMessage());
|
||||
$oP->p("Aborting (no data written)...");
|
||||
CMDBSource::Query('ROLLBACK');
|
||||
}
|
||||
|
||||
if (function_exists('memory_get_peak_usage'))
|
||||
{
|
||||
if (function_exists('memory_get_peak_usage')) {
|
||||
$oP->p("Information: memory peak usage: ".memory_get_peak_usage());
|
||||
}
|
||||
|
||||
|
||||
@@ -41,12 +41,11 @@ require_once(APPROOT.'/application/startup.inc.php');
|
||||
|
||||
function GetSender($aHeaders)
|
||||
{
|
||||
$aResult = array('name' => '', 'email' => '');
|
||||
$aResult = ['name' => '', 'email' => ''];
|
||||
$aResult['name'] = $aHeaders['From'];
|
||||
$aMatches = array();
|
||||
if (preg_match('/\(([0-9a-zA-Z\._]+)@(.+)@(.+)\)/U', array_pop($aHeaders['Received']), $aMatches))
|
||||
{
|
||||
$aResult['email'] = $aMatches[1].'@'.$aMatches[2];
|
||||
$aMatches = [];
|
||||
if (preg_match('/\(([0-9a-zA-Z\._]+)@(.+)@(.+)\)/U', array_pop($aHeaders['Received']), $aMatches)) {
|
||||
$aResult['email'] = $aMatches[1].'@'.$aMatches[2];
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
@@ -61,16 +60,14 @@ function GetSender($aHeaders)
|
||||
function CreateTicket($sSenderEmail, $sSubject, $sBody)
|
||||
{
|
||||
$oTicket = null;
|
||||
try
|
||||
{
|
||||
try {
|
||||
$oContactSearch = new DBObjectSearch('Contact'); // Can be either a Person or a Team, but must be a valid Contact
|
||||
$oContactSearch->AddCondition('email', $sSenderEmail, '=');
|
||||
$oSet = new DBObjectSet($oContactSearch);
|
||||
if ($oSet->Count() == 1)
|
||||
{
|
||||
if ($oSet->Count() == 1) {
|
||||
$oContact = $oSet->Fetch();
|
||||
$oOrganization = MetaModel::GetObject('Organization', $oContact->Get('org_id'));
|
||||
$oTicket = new UserRequest;
|
||||
$oTicket = new UserRequest();
|
||||
$oTicket->Set('title', $sSubject);
|
||||
$oTicket->Set('description', $sBody);
|
||||
$oTicket->Set('org_id', $oOrganization->GetKey());
|
||||
@@ -86,14 +83,10 @@ function CreateTicket($sSenderEmail, $sSubject, $sBody)
|
||||
$sUserString = $oContact->GetName().', submitted by email';
|
||||
CMDBObject::SetTrackInfo($sUserString);
|
||||
$oTicket->DBInsert();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
echo "No contact found in iTop having the email: $sSenderEmail, email message ignored.\n";
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
echo "Error: exception ".$e->getMessage();
|
||||
$oTicket = null;
|
||||
}
|
||||
@@ -111,15 +104,14 @@ $oPop3->login(MAILBOX_ACCOUNT, MAILBOX_PASSWORD);
|
||||
// Note: it is expected that the sender of the email exists a valid contact as a 'Contact'
|
||||
// in iTop (identified by her/his email address), otherwise the ticket creation will fail
|
||||
$iNbMessages = $oPop3->numMsg();
|
||||
for($index = 1; $index <= $iNbMessages; $index++)
|
||||
{
|
||||
for ($index = 1; $index <= $iNbMessages; $index++) {
|
||||
$params['include_bodies'] = true;
|
||||
$params['decode_bodies'] = true;
|
||||
$params['decode_headers'] = true;
|
||||
$params['crlf'] = "\r\n";
|
||||
$aHeaders = $oPop3->getParsedHeaders($index);
|
||||
$aSender = GetSender($aHeaders);
|
||||
$oDecoder = new Mail_mimeDecode( $oPop3->getRawHeaders($index).$params['crlf'].$oPop3->getBody($index) );
|
||||
$oDecoder = new Mail_mimeDecode($oPop3->getRawHeaders($index).$params['crlf'].$oPop3->getBody($index));
|
||||
$oStructure = $oDecoder->decode($params);
|
||||
$sSubject = $aHeaders['Subject'];
|
||||
// Search for the text/plain body part
|
||||
@@ -129,19 +121,14 @@ for($index = 1; $index <= $iNbMessages; $index++)
|
||||
//echo "<pre>\n";
|
||||
//print_r($oStructure);
|
||||
//echo "</pre>\n";
|
||||
if (!isset($oStructure->parts) || count($oStructure->parts) == 0)
|
||||
{
|
||||
if (!isset($oStructure->parts) || count($oStructure->parts) == 0) {
|
||||
$sTextBody = $oStructure->body;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Find the first "part" of the body which is in text/plain
|
||||
while( ($iPartIndex < count($oStructure->parts)) && (!$bFound) )
|
||||
{
|
||||
while (($iPartIndex < count($oStructure->parts)) && (!$bFound)) {
|
||||
//echo "<p>Reading part $iPartIndex</p>\n";
|
||||
if ( ($oStructure->parts[$iPartIndex]->ctype_primary == 'text') &&
|
||||
($oStructure->parts[$iPartIndex]->ctype_secondary == 'plain') )
|
||||
{
|
||||
if (($oStructure->parts[$iPartIndex]->ctype_primary == 'text') &&
|
||||
($oStructure->parts[$iPartIndex]->ctype_secondary == 'plain')) {
|
||||
$sTextBody = $oStructure->parts[$iPartIndex]->body;
|
||||
$bFound = true;
|
||||
//echo "<p>Plain text found ! ($sTextBody)</p>\n";
|
||||
@@ -149,14 +136,11 @@ for($index = 1; $index <= $iNbMessages; $index++)
|
||||
$iPartIndex++;
|
||||
}
|
||||
// Try again but this time look for an HTML part
|
||||
if (!$bFound)
|
||||
{
|
||||
while( ($iPartIndex < count($oStructure->parts)) && (!$bFound) )
|
||||
{
|
||||
if (!$bFound) {
|
||||
while (($iPartIndex < count($oStructure->parts)) && (!$bFound)) {
|
||||
//echo "<p>Reading part $iPartIndex</p>\n";
|
||||
if ( ($oStructure->parts[$iPartIndex]->ctype_primary == 'text') &&
|
||||
($oStructure->parts[$iPartIndex]->ctype_secondary == 'html') )
|
||||
{
|
||||
if (($oStructure->parts[$iPartIndex]->ctype_primary == 'text') &&
|
||||
($oStructure->parts[$iPartIndex]->ctype_secondary == 'html')) {
|
||||
$sTextBody = $oStructure->parts[$iPartIndex]->body;
|
||||
$bFound = true;
|
||||
//echo "<p>HTML text found ! (".htmlentities($sTextBody, ENT_QUOTES, 'UTF-8').")</p>\n";
|
||||
@@ -171,11 +155,10 @@ for($index = 1; $index <= $iNbMessages; $index++)
|
||||
// name => 'john foo <john.foo@combodo.com>
|
||||
|
||||
$oTicket = CreateTicket($aSender['email'], $sSubject, $sTextBody);
|
||||
if ($oTicket != null)
|
||||
{
|
||||
if ($oTicket != null) {
|
||||
// Ticket created, delete the email
|
||||
$oPop3->deleteMsg($index);
|
||||
echo "Ticket: ".$oTicket->GetName()." created.\n";
|
||||
echo "Ticket: ".$oTicket->GetName()." created.\n";
|
||||
}
|
||||
}
|
||||
$oPop3->disconnect();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -27,8 +28,7 @@ require_once(__DIR__.'/../approot.inc.php');
|
||||
const EXIT_CODE_ERROR = -1;
|
||||
const EXIT_CODE_FATAL = -2;
|
||||
// early exit
|
||||
if (file_exists(READONLY_MODE_FILE))
|
||||
{
|
||||
if (file_exists(READONLY_MODE_FILE)) {
|
||||
echo "iTop is read-only. Exiting...\n";
|
||||
exit(EXIT_CODE_ERROR);
|
||||
}
|
||||
@@ -37,8 +37,7 @@ require_once(APPROOT.'/application/application.inc.php');
|
||||
require_once(APPROOT.'/core/background.inc.php');
|
||||
|
||||
$sConfigFile = APPCONF.ITOP_DEFAULT_ENV.'/'.ITOP_CONFIG_FILE;
|
||||
if (!file_exists($sConfigFile))
|
||||
{
|
||||
if (!file_exists($sConfigFile)) {
|
||||
echo "iTop is not yet installed. Exiting...\n";
|
||||
exit(EXIT_CODE_ERROR);
|
||||
}
|
||||
@@ -50,8 +49,7 @@ $oCtx = new ContextTag(ContextTag::TAG_CRON);
|
||||
function ReadMandatoryParam($oP, $sParam, $sSanitizationFilter = 'parameter')
|
||||
{
|
||||
$sValue = utils::ReadParam($sParam, null, true, $sSanitizationFilter);
|
||||
if (is_null($sValue))
|
||||
{
|
||||
if (is_null($sValue)) {
|
||||
$oP->p("ERROR: Missing argument '$sParam'\n");
|
||||
UsageAndExit($oP);
|
||||
}
|
||||
@@ -63,13 +61,10 @@ function UsageAndExit($oP)
|
||||
{
|
||||
$bModeCLI = ($oP instanceof CLIPage);
|
||||
|
||||
if ($bModeCLI)
|
||||
{
|
||||
if ($bModeCLI) {
|
||||
$oP->p("USAGE:\n");
|
||||
$oP->p("php cron.php --auth_user=<login> --auth_pwd=<password> [--param_file=<file>] [--verbose=1] [--debug=1] [--status_only=1]\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oP->p("Optional parameters: verbose, param_file, status_only\n");
|
||||
}
|
||||
$oP->output();
|
||||
@@ -93,7 +88,7 @@ function UsageAndExit($oP)
|
||||
function RunTask(BackgroundTask $oTask, $iTimeLimit)
|
||||
{
|
||||
$TaskClass = $oTask->Get('class_name');
|
||||
$oProcess = new $TaskClass;
|
||||
$oProcess = new $TaskClass();
|
||||
$oRefClass = new ReflectionClass(get_class($oProcess));
|
||||
$oDateStarted = new DateTime();
|
||||
$oDatePlanned = new DateTime($oTask->Get('next_run_date'));
|
||||
@@ -102,8 +97,7 @@ function RunTask(BackgroundTask $oTask, $iTimeLimit)
|
||||
|
||||
$sMessage = '';
|
||||
$oExceptionToThrow = null;
|
||||
try
|
||||
{
|
||||
try {
|
||||
// Record (when starting) that this task was started, just in case it crashes during the execution
|
||||
$oTask->Set('latest_run_date', $oDateStarted->format('Y-m-d H:i:s'));
|
||||
// Record the current user running the cron
|
||||
@@ -113,42 +107,30 @@ function RunTask(BackgroundTask $oTask, $iTimeLimit)
|
||||
// Time in seconds allowed to the task
|
||||
$iCurrTimeLimit = $iTimeLimit;
|
||||
// Compute allowed time
|
||||
if ($oRefClass->implementsInterface('iScheduledProcess') === false)
|
||||
{
|
||||
if ($oRefClass->implementsInterface('iScheduledProcess') === false) {
|
||||
// Periodic task, allow only X times ($iMaxTaskExecutionTime) its periodicity (GetPeriodicity())
|
||||
$iMaxTaskExecutionTime = MetaModel::GetConfig()->Get('cron_task_max_execution_time');
|
||||
$iTaskLimit = time() + $oProcess->GetPeriodicity() * $iMaxTaskExecutionTime;
|
||||
// If our proposed time limit is less than cron limit, and cron_task_max_execution_time is > 0
|
||||
if ($iTaskLimit < $iTimeLimit && $iMaxTaskExecutionTime > 0)
|
||||
{
|
||||
if ($iTaskLimit < $iTimeLimit && $iMaxTaskExecutionTime > 0) {
|
||||
$iCurrTimeLimit = $iTaskLimit;
|
||||
}
|
||||
}
|
||||
$sMessage = $oProcess->Process($iCurrTimeLimit);
|
||||
$oTask->Set('running', 0);
|
||||
}
|
||||
catch (MySQLHasGoneAwayException $e)
|
||||
{
|
||||
} catch (MySQLHasGoneAwayException $e) {
|
||||
throw $e;
|
||||
}
|
||||
catch (ProcessFatalException $e)
|
||||
{
|
||||
} catch (ProcessFatalException $e) {
|
||||
$oExceptionToThrow = $e;
|
||||
}
|
||||
catch (Exception $e) // we shouldn't get so much exceptions... but we need to handle legacy code, and cron.php has to keep running
|
||||
{
|
||||
if ($oTask->IsDebug())
|
||||
{
|
||||
$sMessage = 'Processing failed with message: '. $e->getMessage() . '. ' . $e->getTraceAsString();
|
||||
}
|
||||
else
|
||||
{
|
||||
$sMessage = 'Processing failed with message: '. $e->getMessage();
|
||||
} catch (Exception $e) { // we shouldn't get so much exceptions... but we need to handle legacy code, and cron.php has to keep running
|
||||
if ($oTask->IsDebug()) {
|
||||
$sMessage = 'Processing failed with message: '.$e->getMessage().'. '.$e->getTraceAsString();
|
||||
} else {
|
||||
$sMessage = 'Processing failed with message: '.$e->getMessage();
|
||||
}
|
||||
}
|
||||
$fDuration = microtime(true) - $fStart;
|
||||
if ($oTask->Get('total_exec_count') == 0)
|
||||
{
|
||||
if ($oTask->Get('total_exec_count') == 0) {
|
||||
// First execution
|
||||
$oTask->Set('first_run_date', $oDateStarted->format('Y-m-d H:i:s'));
|
||||
}
|
||||
@@ -158,20 +140,16 @@ function RunTask(BackgroundTask $oTask, $iTimeLimit)
|
||||
$oDateEnded = new DateTime();
|
||||
$oTask->Set('latest_run_date', $oDateEnded->format('Y-m-d H:i:s'));
|
||||
|
||||
if ($oRefClass->implementsInterface('iScheduledProcess'))
|
||||
{
|
||||
if ($oRefClass->implementsInterface('iScheduledProcess')) {
|
||||
// Schedules process do repeat at specific moments
|
||||
$oPlannedStart = $oProcess->GetNextOccurrence();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Background processes do repeat periodically
|
||||
$oPlannedStart = clone $oDatePlanned;
|
||||
// Let's schedule from the previous planned date of execution to avoid shift
|
||||
$oPlannedStart->modify($oProcess->GetPeriodicity().' seconds');
|
||||
$oEnd = new DateTime();
|
||||
while ($oPlannedStart->format('U') < $oEnd->format('U'))
|
||||
{
|
||||
while ($oPlannedStart->format('U') < $oEnd->format('U')) {
|
||||
// Next planned start is already in the past, increase it again by a period
|
||||
$oPlannedStart = $oPlannedStart->modify('+'.$oProcess->GetPeriodicity().' seconds');
|
||||
}
|
||||
@@ -180,8 +158,7 @@ function RunTask(BackgroundTask $oTask, $iTimeLimit)
|
||||
$oTask->Set('next_run_date', $oPlannedStart->format('Y-m-d H:i:s'));
|
||||
$oTask->DBUpdate();
|
||||
|
||||
if ($oExceptionToThrow)
|
||||
{
|
||||
if ($oExceptionToThrow) {
|
||||
throw $oExceptionToThrow;
|
||||
}
|
||||
|
||||
@@ -207,23 +184,21 @@ function RunTask(BackgroundTask $oTask, $iTimeLimit)
|
||||
* @throws \OQLException
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
function CronExec($oP, $bVerbose, $bDebug=false)
|
||||
function CronExec($oP, $bVerbose, $bDebug = false)
|
||||
{
|
||||
$iStarted = time();
|
||||
$iMaxDuration = MetaModel::GetConfig()->Get('cron_max_execution_time');
|
||||
$iTimeLimit = $iStarted + $iMaxDuration;
|
||||
$iCronSleep = MetaModel::GetConfig()->Get('cron_sleep');
|
||||
|
||||
if ($bVerbose)
|
||||
{
|
||||
if ($bVerbose) {
|
||||
$oP->p("Planned duration = $iMaxDuration seconds");
|
||||
$oP->p("Loop pause = $iCronSleep seconds");
|
||||
}
|
||||
|
||||
ReSyncProcesses($oP, $bVerbose, $bDebug);
|
||||
|
||||
while (time() < $iTimeLimit)
|
||||
{
|
||||
while (time() < $iTimeLimit) {
|
||||
CheckMaintenanceMode($oP);
|
||||
|
||||
$oNow = new DateTime();
|
||||
@@ -234,23 +209,19 @@ function CronExec($oP, $bVerbose, $bDebug=false)
|
||||
$oTasks = new DBObjectSet($oSearch, ['next_run_date' => true]);
|
||||
$bWorkDone = false;
|
||||
|
||||
if ($oTasks->CountExceeds(0))
|
||||
{
|
||||
if ($oTasks->CountExceeds(0)) {
|
||||
$bWorkDone = true;
|
||||
$aTasks = array();
|
||||
if ($bVerbose)
|
||||
{
|
||||
$aTasks = [];
|
||||
if ($bVerbose) {
|
||||
$sCount = $oTasks->Count();
|
||||
$oP->p("$sCount Tasks planned to run now ($sNow):");
|
||||
$oP->p('+---------------------------+---------+---------------------+---------------------+');
|
||||
$oP->p('| Task Class | Status | Last Run | Next Run |');
|
||||
$oP->p('+---------------------------+---------+---------------------+---------------------+');
|
||||
}
|
||||
while ($oTask = $oTasks->Fetch())
|
||||
{
|
||||
while ($oTask = $oTasks->Fetch()) {
|
||||
$aTasks[$oTask->Get('class_name')] = $oTask;
|
||||
if ($bVerbose)
|
||||
{
|
||||
if ($bVerbose) {
|
||||
$sTaskName = $oTask->Get('class_name');
|
||||
$sStatus = $oTask->Get('status');
|
||||
$sLastRunDate = $oTask->Get('latest_run_date');
|
||||
@@ -258,13 +229,11 @@ function CronExec($oP, $bVerbose, $bDebug=false)
|
||||
$oP->p(sprintf('| %1$-25.25s | %2$-7s | %3$-19s | %4$-19s |', $sTaskName, $sStatus, $sLastRunDate, $sNextRunDate));
|
||||
}
|
||||
}
|
||||
if ($bVerbose)
|
||||
{
|
||||
if ($bVerbose) {
|
||||
$oP->p('+---------------------------+---------+---------------------+---------------------+');
|
||||
}
|
||||
$aRunTasks = [];
|
||||
foreach ($aTasks as $oTask)
|
||||
{
|
||||
foreach ($aTasks as $oTask) {
|
||||
$sTaskClass = $oTask->Get('class_name');
|
||||
$aRunTasks[] = $sTaskClass;
|
||||
|
||||
@@ -273,66 +242,54 @@ function CronExec($oP, $bVerbose, $bDebug=false)
|
||||
CMDBObject::SetCurrentChangeFromParams("Background task ($sTaskClass)");
|
||||
|
||||
// Run the task and record its next run time
|
||||
if ($bVerbose)
|
||||
{
|
||||
if ($bVerbose) {
|
||||
$oNow = new DateTime();
|
||||
$oP->p(">> === ".$oNow->format('Y-m-d H:i:s').sprintf(" Starting:%-'=49s", ' '.$sTaskClass.' '));
|
||||
}
|
||||
try
|
||||
{
|
||||
try {
|
||||
$sMessage = RunTask($aTasks[$sTaskClass], $iTimeLimit);
|
||||
} catch (MySQLHasGoneAwayException $e)
|
||||
{
|
||||
} catch (MySQLHasGoneAwayException $e) {
|
||||
$oP->p("ERROR : 'MySQL has gone away' thrown when processing $sTaskClass (error_code=".$e->getCode().")");
|
||||
exit(EXIT_CODE_FATAL);
|
||||
} catch (ProcessFatalException $e)
|
||||
{
|
||||
} catch (ProcessFatalException $e) {
|
||||
$oP->p("ERROR : an exception was thrown when processing '$sTaskClass' (".$e->getInfoLog().")");
|
||||
IssueLog::Error("Cron.php error : an exception was thrown when processing '$sTaskClass' (".$e->getInfoLog().')');
|
||||
}
|
||||
if ($bVerbose)
|
||||
{
|
||||
if (!empty($sMessage))
|
||||
{
|
||||
if ($bVerbose) {
|
||||
if (!empty($sMessage)) {
|
||||
$oP->p("$sTaskClass: $sMessage");
|
||||
}
|
||||
$oEnd = new DateTime();
|
||||
$sNextRunDate = $oTask->Get('next_run_date');
|
||||
$oP->p("<< === ".$oEnd->format('Y-m-d H:i:s').sprintf(" End of: %-'=42s", ' '.$sTaskClass.' ')." Next: $sNextRunDate");
|
||||
}
|
||||
if (time() > $iTimeLimit)
|
||||
{
|
||||
if (time() > $iTimeLimit) {
|
||||
break 2;
|
||||
}
|
||||
CheckMaintenanceMode($oP);
|
||||
}
|
||||
|
||||
// Tasks to run later
|
||||
if ($bVerbose)
|
||||
{
|
||||
if ($bVerbose) {
|
||||
$oP->p('--');
|
||||
$oSearch = new DBObjectSearch('BackgroundTask');
|
||||
$oSearch->AddCondition('next_run_date', $sNow, '>');
|
||||
$oSearch->AddCondition('status', 'active');
|
||||
$oTasks = new DBObjectSet($oSearch, ['next_run_date' => true]);
|
||||
while ($oTask = $oTasks->Fetch())
|
||||
{
|
||||
if (!in_array($oTask->Get('class_name'), $aRunTasks))
|
||||
{
|
||||
while ($oTask = $oTasks->Fetch()) {
|
||||
if (!in_array($oTask->Get('class_name'), $aRunTasks)) {
|
||||
$oP->p(sprintf("-- Skipping task: %-'-40s", $oTask->Get('class_name').' ')." until: ".$oTask->Get('next_run_date'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($bVerbose && $bWorkDone)
|
||||
{
|
||||
if ($bVerbose && $bWorkDone) {
|
||||
$oP->p("Sleeping...\n");
|
||||
}
|
||||
sleep($iCronSleep);
|
||||
}
|
||||
if ($bVerbose)
|
||||
{
|
||||
if ($bVerbose) {
|
||||
$oP->p('');
|
||||
DisplayStatus($oP, ['next_run_date' => true]);
|
||||
$oP->p("Reached normal execution time limit (exceeded by ".(time() - $iTimeLimit)."s)");
|
||||
@@ -342,8 +299,9 @@ function CronExec($oP, $bVerbose, $bDebug=false)
|
||||
/**
|
||||
* @param WebPage $oP
|
||||
*/
|
||||
function CheckMaintenanceMode(Page $oP) {
|
||||
// Verify files instead of reloading the full config each time
|
||||
function CheckMaintenanceMode(Page $oP)
|
||||
{
|
||||
// Verify files instead of reloading the full config each time
|
||||
if (file_exists(MAINTENANCE_MODE_FILE) || file_exists(READONLY_MODE_FILE)) {
|
||||
$oP->p("Maintenance detected, exiting");
|
||||
exit(EXIT_CODE_ERROR);
|
||||
@@ -367,16 +325,22 @@ function DisplayStatus($oP, $aTaskOrderBy = [])
|
||||
$oP->p('+---------------------------+---------+---------------------+---------------------+--------+-----------+');
|
||||
$oP->p('| Task Class | Status | Last Run | Next Run | Nb Run | Avg. Dur. |');
|
||||
$oP->p('+---------------------------+---------+---------------------+---------------------+--------+-----------+');
|
||||
while ($oTask = $oTasks->Fetch())
|
||||
{
|
||||
while ($oTask = $oTasks->Fetch()) {
|
||||
$sTaskName = $oTask->Get('class_name');
|
||||
$sStatus = $oTask->Get('status');
|
||||
$sLastRunDate = $oTask->Get('latest_run_date');
|
||||
$sNextRunDate = $oTask->Get('next_run_date');
|
||||
$iNbRun = (int)$oTask->Get('total_exec_count');
|
||||
$sAverageRunTime = $oTask->Get('average_run_duration');
|
||||
$oP->p(sprintf('| %1$-25.25s | %2$-7s | %3$-19s | %4$-19s | %5$6d | %6$7s s |', $sTaskName, $sStatus,
|
||||
$sLastRunDate, $sNextRunDate, $iNbRun, $sAverageRunTime));
|
||||
$oP->p(sprintf(
|
||||
'| %1$-25.25s | %2$-7s | %3$-19s | %4$-19s | %5$6d | %6$7s s |',
|
||||
$sTaskName,
|
||||
$sStatus,
|
||||
$sLastRunDate,
|
||||
$sNextRunDate,
|
||||
$iNbRun,
|
||||
$sAverageRunTime
|
||||
));
|
||||
}
|
||||
$oP->p('+---------------------------+---------+---------------------+---------------------+--------+-----------+');
|
||||
}
|
||||
@@ -401,22 +365,19 @@ function ReSyncProcesses($oP, $bVerbose, $bDebug)
|
||||
//
|
||||
$oSearch = new DBObjectSearch('BackgroundTask');
|
||||
$oTasks = new DBObjectSet($oSearch);
|
||||
$aTasks = array();
|
||||
while ($oTask = $oTasks->Fetch())
|
||||
{
|
||||
$aTasks = [];
|
||||
while ($oTask = $oTasks->Fetch()) {
|
||||
$aTasks[$oTask->Get('class_name')] = $oTask;
|
||||
}
|
||||
$oNow = new DateTime();
|
||||
|
||||
$aProcesses = array();
|
||||
foreach (InterfaceDiscovery::GetInstance()->FindItopClasses(iProcess::class) as $sTaskClass)
|
||||
{
|
||||
$oProcess = new $sTaskClass;
|
||||
$aProcesses = [];
|
||||
foreach (InterfaceDiscovery::GetInstance()->FindItopClasses(iProcess::class) as $sTaskClass) {
|
||||
$oProcess = new $sTaskClass();
|
||||
$aProcesses[$sTaskClass] = $oProcess;
|
||||
|
||||
// Create missing entry if needed
|
||||
if (!array_key_exists($sTaskClass, $aTasks))
|
||||
{
|
||||
if (!array_key_exists($sTaskClass, $aTasks)) {
|
||||
// New entry, let's create a new BackgroundTask record, and plan the first execution
|
||||
$oTask = new BackgroundTask();
|
||||
$oTask->SetDebug($bDebug);
|
||||
@@ -426,41 +387,32 @@ function ReSyncProcesses($oP, $bVerbose, $bDebug)
|
||||
$oTask->Set('max_run_duration', 0);
|
||||
$oTask->Set('average_run_duration', 0);
|
||||
$oRefClass = new ReflectionClass($sTaskClass);
|
||||
if ($oRefClass->implementsInterface('iScheduledProcess'))
|
||||
{
|
||||
if ($oRefClass->implementsInterface('iScheduledProcess')) {
|
||||
$oNextOcc = $oProcess->GetNextOccurrence();
|
||||
$oTask->Set('next_run_date', $oNextOcc->format('Y-m-d H:i:s'));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Background processes do start asap, i.e. "now"
|
||||
$oTask->Set('next_run_date', $oNow->format('Y-m-d H:i:s'));
|
||||
}
|
||||
if ($bVerbose)
|
||||
{
|
||||
if ($bVerbose) {
|
||||
$oP->p('Creating record for: '.$sTaskClass);
|
||||
$oP->p('First execution planned at: '.$oTask->Get('next_run_date'));
|
||||
}
|
||||
$oTask->DBInsert();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/** @var \BackgroundTask $oTask */
|
||||
$oTask = $aTasks[$sTaskClass];
|
||||
if ($oTask->Get('next_run_date') == '3000-01-01 00:00:00')
|
||||
{
|
||||
if ($oTask->Get('next_run_date') == '3000-01-01 00:00:00') {
|
||||
// check for rescheduled tasks
|
||||
$oRefClass = new ReflectionClass($sTaskClass);
|
||||
if ($oRefClass->implementsInterface('iScheduledProcess'))
|
||||
{
|
||||
if ($oRefClass->implementsInterface('iScheduledProcess')) {
|
||||
$oNextOcc = $oProcess->GetNextOccurrence();
|
||||
$oTask->Set('next_run_date', $oNextOcc->format('Y-m-d H:i:s'));
|
||||
$oTask->DBUpdate();
|
||||
}
|
||||
}
|
||||
// Reactivate task if necessary
|
||||
if ($oTask->Get('status') == 'removed')
|
||||
{
|
||||
if ($oTask->Get('status') == 'removed') {
|
||||
$oTask->Set('status', 'active');
|
||||
$oTask->DBUpdate();
|
||||
}
|
||||
@@ -470,21 +422,17 @@ function ReSyncProcesses($oP, $bVerbose, $bDebug)
|
||||
}
|
||||
|
||||
// Remove all the tasks not having a valid class
|
||||
foreach ($aTasks as $oTask)
|
||||
{
|
||||
foreach ($aTasks as $oTask) {
|
||||
$sTaskClass = $oTask->Get('class_name');
|
||||
if (!class_exists($sTaskClass))
|
||||
{
|
||||
if (!class_exists($sTaskClass)) {
|
||||
$oTask->Set('status', 'removed');
|
||||
$oTask->DBUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
if ($bVerbose)
|
||||
{
|
||||
$aDisplayProcesses = array();
|
||||
foreach ($aProcesses as $oExecInstance)
|
||||
{
|
||||
if ($bVerbose) {
|
||||
$aDisplayProcesses = [];
|
||||
foreach ($aProcesses as $oExecInstance) {
|
||||
$aDisplayProcesses[] = get_class($oExecInstance);
|
||||
}
|
||||
$sDisplayProcesses = implode(', ', $aDisplayProcesses);
|
||||
@@ -500,58 +448,45 @@ function ReSyncProcesses($oP, $bVerbose, $bDebug)
|
||||
set_time_limit(0); // Some background actions may really take long to finish (like backup)
|
||||
|
||||
$bIsModeCLI = utils::IsModeCLI();
|
||||
if ($bIsModeCLI)
|
||||
{
|
||||
if ($bIsModeCLI) {
|
||||
$oP = new CLIPage("iTop - cron");
|
||||
|
||||
SetupUtils::CheckPhpAndExtensionsForCli($oP, EXIT_CODE_FATAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oP = new WebPage("iTop - cron");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
utils::UseParamFile();
|
||||
|
||||
$bVerbose = utils::ReadParam('verbose', false, true /* Allow CLI */);
|
||||
$bDebug = utils::ReadParam('debug', false, true /* Allow CLI */);
|
||||
|
||||
if ($bIsModeCLI)
|
||||
{
|
||||
if ($bIsModeCLI) {
|
||||
// Next steps:
|
||||
// specific arguments: 'csv file'
|
||||
//
|
||||
$sAuthUser = ReadMandatoryParam($oP, 'auth_user', 'raw_data');
|
||||
$sAuthPwd = ReadMandatoryParam($oP, 'auth_pwd', 'raw_data');
|
||||
if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd))
|
||||
{
|
||||
if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd)) {
|
||||
UserRights::Login($sAuthUser); // Login & set the user's language
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oP->p("Access wrong credentials ('$sAuthUser')");
|
||||
$oP->output();
|
||||
exit(EXIT_CODE_ERROR);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
LoginWebPage::DoLogin(); // Check user rights and prompt if needed
|
||||
}
|
||||
|
||||
if (!UserRights::IsAdministrator())
|
||||
{
|
||||
if (!UserRights::IsAdministrator()) {
|
||||
$oP->p("Access restricted to administrators");
|
||||
$oP->Output();
|
||||
exit(EXIT_CODE_ERROR);
|
||||
}
|
||||
|
||||
|
||||
if (utils::ReadParam('status_only', false, true /* Allow CLI */))
|
||||
{
|
||||
if (utils::ReadParam('status_only', false, true /* Allow CLI */)) {
|
||||
// Display status and exit
|
||||
DisplayStatus($oP);
|
||||
exit(0);
|
||||
@@ -559,54 +494,36 @@ try
|
||||
|
||||
require_once(APPROOT.'core/mutex.class.inc.php');
|
||||
$oP->p("Starting: ".time().' ('.date('Y-m-d H:i:s').')');
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
$oP->p("Error: ".$e->GetMessage());
|
||||
$oP->output();
|
||||
exit(EXIT_CODE_FATAL);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
$oMutex = new iTopMutex('cron');
|
||||
if (!MetaModel::DBHasAccess(ACCESS_ADMIN_WRITE))
|
||||
{
|
||||
if (!MetaModel::DBHasAccess(ACCESS_ADMIN_WRITE)) {
|
||||
$oP->p("A maintenance is ongoing");
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($oMutex->TryLock())
|
||||
{
|
||||
} else {
|
||||
if ($oMutex->TryLock()) {
|
||||
CronExec($oP, $bVerbose, $bDebug);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Exit silently
|
||||
$oP->p("Already running...");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
$oP->p("ERROR: '".$e->getMessage()."'");
|
||||
if ($bDebug)
|
||||
{
|
||||
if ($bDebug) {
|
||||
// Might contain verb parameters such a password...
|
||||
$oP->p($e->getTraceAsString());
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
} finally {
|
||||
try {
|
||||
$oMutex->Unlock();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
$oP->p("ERROR: '".$e->getMessage()."'");
|
||||
if ($bDebug)
|
||||
{
|
||||
if ($bDebug) {
|
||||
// Might contain verb parameters such a password...
|
||||
$oP->p($e->getTraceAsString());
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
@@ -35,15 +36,12 @@ const EXIT_CODE_FATAL = -2;
|
||||
|
||||
function ReportErrorAndExit($sErrorMessage)
|
||||
{
|
||||
if (utils::IsModeCLI())
|
||||
{
|
||||
if (utils::IsModeCLI()) {
|
||||
$oP = new CLIPage("iTop - Export");
|
||||
$oP->p('ERROR: '.utils::HtmlEntities($sErrorMessage));
|
||||
$oP->output();
|
||||
exit(EXIT_CODE_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oP = new WebPage("iTop - Export");
|
||||
$oP->add_http_headers();
|
||||
$oP->p('ERROR: '.utils::HtmlEntities($sErrorMessage));
|
||||
@@ -54,15 +52,13 @@ function ReportErrorAndExit($sErrorMessage)
|
||||
|
||||
function ReportErrorAndUsage($sErrorMessage)
|
||||
{
|
||||
if (utils::IsModeCLI())
|
||||
{
|
||||
if (utils::IsModeCLI()) {
|
||||
$oP = new CLIPage("iTop - Export");
|
||||
$oP->p('ERROR: '.$sErrorMessage);
|
||||
Usage($oP);
|
||||
$oP->output();
|
||||
exit(EXIT_CODE_ERROR);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$oP = new WebPage("iTop - Export");
|
||||
$oP->add_http_headers();
|
||||
$oP->p('ERROR: '.$sErrorMessage);
|
||||
@@ -74,42 +70,32 @@ function ReportErrorAndUsage($sErrorMessage)
|
||||
|
||||
function Usage(Page $oP)
|
||||
{
|
||||
if (Utils::IsModeCLI())
|
||||
{
|
||||
if (Utils::IsModeCLI()) {
|
||||
$oP->p('Usage: php '.basename(__FILE__).' --auth_user=<user> --auth_pwd=<password> --expression=<OQL Query> --query=<phrasebook_id> [--arg_xxx=<query_arguments>] [--no_localize=0|1] [--format=<format>] [--format-options...]');
|
||||
$oP->p("Parameters:");
|
||||
$oP->p(" * auth_user: the iTop user account for authentication");
|
||||
$oP->p(" * auth_pwd: the password of the iTop user account");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oP->p("Parameters:");
|
||||
}
|
||||
$oP->p(" * expression: an OQL expression (e.g. SELECT Contact WHERE name LIKE 'm%')");
|
||||
$oP->p(" * query: (alternative to 'expression') the id of an entry from the query phrasebook");
|
||||
if (Utils::IsModeCLI())
|
||||
{
|
||||
if (Utils::IsModeCLI()) {
|
||||
$oP->p(" * with_archive: (optional, defaults to 0) if set to 1 then the result set will include archived objects");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oP->p(" * with_archive: (optional, defaults to the current mode) if set to 1 then the result set will include archived objects");
|
||||
}
|
||||
$oP->p(" * arg_xxx: (needed if the query has parameters) the value of the parameter 'xxx'");
|
||||
$aSupportedFormats = BulkExport::FindSupportedFormats();
|
||||
$oP->p(" * format: (optional, default is html) the desired output format. Can be one of '".implode("', '", array_keys($aSupportedFormats))."'");
|
||||
foreach($aSupportedFormats as $sFormatCode => $sLabel)
|
||||
{
|
||||
foreach ($aSupportedFormats as $sFormatCode => $sLabel) {
|
||||
$oExporter = BulkExport::FindExporter($sFormatCode);
|
||||
if ($oExporter !== null)
|
||||
{
|
||||
if (!Utils::IsModeCLI())
|
||||
{
|
||||
if ($oExporter !== null) {
|
||||
if (!Utils::IsModeCLI()) {
|
||||
$oP->add('<hr/>');
|
||||
}
|
||||
$oExporter->DisplayUsage($oP);
|
||||
if (!Utils::IsModeCLI())
|
||||
{
|
||||
if (!Utils::IsModeCLI()) {
|
||||
$oP->add('</div>');
|
||||
}
|
||||
}
|
||||
@@ -248,19 +234,18 @@ EOF
|
||||
$sExpressionError = '';
|
||||
if (($sExpression === null) && ($sQueryId === null)) {
|
||||
$bExpressionIsValid = false;
|
||||
} else if ($sExpression !== '') {
|
||||
} elseif ($sExpression !== '') {
|
||||
try {
|
||||
$oExportSearch = DBObjectSearch::FromOQL($sExpression);
|
||||
$oExportSearch->UpdateContextFromUser();
|
||||
}
|
||||
catch (OQLException $e) {
|
||||
} catch (OQLException $e) {
|
||||
$bExpressionIsValid = false;
|
||||
$sExpressionError = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
if (!$bExpressionIsValid) {
|
||||
DisplayExpressionForm($oP, $sAction, $sExpression, $sExpressionError,$oForm);
|
||||
DisplayExpressionForm($oP, $sAction, $sExpression, $sExpressionError, $oForm);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -275,13 +260,12 @@ EOF
|
||||
$oExportSearch->UpdateContextFromUser();
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("query", $sQueryId));
|
||||
}
|
||||
$aFormPartsByFormat = array();
|
||||
$aAllFormParts = array();
|
||||
$aFormPartsByFormat = [];
|
||||
$aAllFormParts = [];
|
||||
if ($sFormat == null) {
|
||||
// No specific format chosen
|
||||
$sDefaultFormat = utils::ReadParam('format', 'xlsx');
|
||||
|
||||
|
||||
$oSelect = SelectUIBlockFactory::MakeForSelectWithLabel("format", Dict::S('Core:BulkExport:ExportFormatPrompt'), "format_selector");
|
||||
$oSelect->SetIsLabelBefore(true);
|
||||
$oForm->AddSubBlock($oSelect);
|
||||
@@ -390,7 +374,7 @@ EOF
|
||||
if ($sExpression === null) {
|
||||
// No expression supplied, let's check if phrasebook entry is given
|
||||
if ($sQueryId !== null) {
|
||||
$oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', array('query_id' => $sQueryId));
|
||||
$oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', ['query_id' => $sQueryId]);
|
||||
$oSearch->UpdateContextFromUser();
|
||||
$oQueries = new DBObjectSet($oSearch);
|
||||
if ($oQueries->Count() > 0) {
|
||||
@@ -412,7 +396,6 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($sFormat !== null) {
|
||||
$oExporter = BulkExport::FindExporter($sFormat);
|
||||
if ($oExporter === null) {
|
||||
@@ -452,7 +435,7 @@ function CheckParameters($sExpression, $sQueryId, $sFormat)
|
||||
|
||||
// Either $sExpression or $sQueryId must be specified
|
||||
if ($sExpression === null) {
|
||||
$oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', array('query_id' => $sQueryId));
|
||||
$oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', ['query_id' => $sQueryId]);
|
||||
$oSearch->UpdateContextFromUser();
|
||||
$oQueries = new DBObjectSet($oSearch);
|
||||
if ($oQueries->Count() > 0) {
|
||||
@@ -470,7 +453,7 @@ function CheckParameters($sExpression, $sQueryId, $sFormat)
|
||||
try {
|
||||
$oSearch = DBObjectSearch::FromOQL($sExpression);
|
||||
$oSearch->UpdateContextFromUser();
|
||||
$aArgs = array();
|
||||
$aArgs = [];
|
||||
foreach ($oSearch->GetQueryParams() as $sParam => $foo) {
|
||||
$value = utils::ReadParam('arg_'.$sParam, null, true, 'raw_data');
|
||||
if (!is_null($value)) {
|
||||
@@ -483,30 +466,23 @@ function CheckParameters($sExpression, $sQueryId, $sFormat)
|
||||
|
||||
$sFormat = utils::ReadParam('format', 'html', true /* Allow CLI */, 'raw_data');
|
||||
$oExporter = BulkExport::FindExporter($sFormat, $oSearch);
|
||||
if ($oExporter == null)
|
||||
{
|
||||
if ($oExporter == null) {
|
||||
$aSupportedFormats = BulkExport::FindSupportedFormats();
|
||||
ReportErrorAndExit("Invalid output format: '$sFormat'. The supported formats are: ".implode(', ', array_keys($aSupportedFormats)));
|
||||
}
|
||||
}
|
||||
catch(MissingQueryArgument $e)
|
||||
{
|
||||
} catch (MissingQueryArgument $e) {
|
||||
$oSearch = null;
|
||||
ReportErrorAndUsage("Invalid OQL query: '".utils::HtmlEntities($sExpression)."'.\n".utils::HtmlEntities($e->getMessage()));
|
||||
}
|
||||
catch(OQLException $e)
|
||||
{
|
||||
} catch (OQLException $e) {
|
||||
$oSearch = null;
|
||||
ReportErrorAndExit("Invalid OQL query: '".utils::HtmlEntities($sExpression)."'.\n".utils::HtmlEntities($e->getMessage()));
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
$oSearch = null;
|
||||
ReportErrorAndExit(utils::HtmlEntities($e->getMessage()));
|
||||
}
|
||||
|
||||
// update last export information if check parameters ok
|
||||
if($oQuery != null){
|
||||
if ($oQuery != null) {
|
||||
$oQuery->UpdateLastExportInformation();
|
||||
}
|
||||
|
||||
@@ -522,24 +498,18 @@ function DoExport(WebPage $oP, BulkExport $oExporter, $bInteractive = false)
|
||||
{
|
||||
$oExporter->SetHttpHeaders($oP);
|
||||
$exportResult = $oExporter->GetHeader();
|
||||
$aStatus = array();
|
||||
do
|
||||
{
|
||||
$aStatus = [];
|
||||
do {
|
||||
$exportResult .= $oExporter->GetNextChunk($aStatus);
|
||||
}
|
||||
while (($aStatus['code'] != 'done') && ($aStatus['code'] != 'error'));
|
||||
} while (($aStatus['code'] != 'done') && ($aStatus['code'] != 'error'));
|
||||
|
||||
if ($aStatus['code'] == 'error')
|
||||
{
|
||||
if ($aStatus['code'] == 'error') {
|
||||
$oExporter->Cleanup();
|
||||
ReportErrorAndExit("Export failed: '{$aStatus['message']}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$exportResult .= $oExporter->GetFooter();
|
||||
$sMimeType = $oExporter->GetMimeType();
|
||||
if (substr($sMimeType, 0, 5) == 'text/')
|
||||
{
|
||||
if (substr($sMimeType, 0, 5) == 'text/') {
|
||||
$sMimeType .= ';charset='.strtolower($oExporter->GetCharacterSet());
|
||||
}
|
||||
$oP->SetContentType($sMimeType);
|
||||
@@ -549,7 +519,6 @@ function DoExport(WebPage $oP, BulkExport $oExporter, $bInteractive = false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Command Line mode
|
||||
@@ -567,8 +536,7 @@ if (utils::IsModeCLI()) {
|
||||
try {
|
||||
// Do this before loging, in order to allow setting user credentials from within the file
|
||||
utils::UseParamFile();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
echo "Error: ".utils::HtmlEntities($e->getMessage())."<br/>\n";
|
||||
exit(EXIT_CODE_FATAL);
|
||||
}
|
||||
@@ -600,7 +568,7 @@ if (utils::IsModeCLI()) {
|
||||
}
|
||||
|
||||
if ($sExpression === null) {
|
||||
$oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', array('query_id' => $sQueryId));
|
||||
$oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', ['query_id' => $sQueryId]);
|
||||
$oSearch->UpdateContextFromUser();
|
||||
$oQueries = new DBObjectSet($oSearch);
|
||||
if ($oQueries->Count() > 0) {
|
||||
@@ -613,7 +581,7 @@ if (utils::IsModeCLI()) {
|
||||
try {
|
||||
$oSearch = DBObjectSearch::FromOQL($sExpression);
|
||||
$oSearch->UpdateContextFromUser();
|
||||
$aArgs = array();
|
||||
$aArgs = [];
|
||||
foreach ($oSearch->GetQueryParams() as $sParam => $foo) {
|
||||
$value = utils::ReadParam('arg_'.$sParam, null, true, 'raw_data');
|
||||
if (!is_null($value)) {
|
||||
@@ -626,8 +594,7 @@ if (utils::IsModeCLI()) {
|
||||
|
||||
$sFormat = utils::ReadParam('format', 'html', true /* Allow CLI */, 'raw_data');
|
||||
$oExporter = BulkExport::FindExporter($sFormat);
|
||||
if ($oExporter == null)
|
||||
{
|
||||
if ($oExporter == null) {
|
||||
$aSupportedFormats = BulkExport::FindSupportedFormats();
|
||||
ReportErrorAndExit("Invalid output format: '$sFormat'. The supported formats are: ".implode(', ', array_keys($aSupportedFormats)));
|
||||
}
|
||||
@@ -638,36 +605,25 @@ if (utils::IsModeCLI()) {
|
||||
$oExporter->ReadParameters();
|
||||
|
||||
$exportResult = $oExporter->GetHeader();
|
||||
$aStatus = array();
|
||||
$aStatus = [];
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
$exportResult .= $oExporter->GetNextChunk($aStatus);
|
||||
}
|
||||
while (($aStatus['code'] != 'done') && ($aStatus['code'] != 'error'));
|
||||
} while (($aStatus['code'] != 'done') && ($aStatus['code'] != 'error'));
|
||||
|
||||
if ($aStatus['code'] == 'error')
|
||||
{
|
||||
if ($aStatus['code'] == 'error') {
|
||||
ReportErrorAndExit("Export failed: '{$aStatus['message']}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$exportResult .= $oExporter->GetFooter();
|
||||
echo $exportResult;
|
||||
}
|
||||
$oExporter->Cleanup();
|
||||
|
||||
}
|
||||
catch(MissingQueryArgument $e)
|
||||
{
|
||||
} catch (MissingQueryArgument $e) {
|
||||
ReportErrorAndUsage("Invalid OQL query: '$sExpression'.\n".utils::HtmlEntities($e->getMessage()));
|
||||
}
|
||||
catch(OQLException $e)
|
||||
{
|
||||
} catch (OQLException $e) {
|
||||
ReportErrorAndExit("Invalid OQL query: '$sExpression'.\n".utils::HtmlEntities($e->getMessage()));
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
ReportErrorAndExit(utils::HtmlEntities($e->getMessage()));
|
||||
}
|
||||
|
||||
@@ -680,8 +636,7 @@ if (utils::IsModeCLI()) {
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
|
||||
// Main parameters
|
||||
@@ -722,14 +677,12 @@ try
|
||||
DoExport($oP, $oExporter, false);
|
||||
$oP->output();
|
||||
}
|
||||
}
|
||||
catch (BulkExportMissingParameterException $e) {
|
||||
} catch (BulkExportMissingParameterException $e) {
|
||||
$oP = new AjaxPage('iTop Export');
|
||||
$oP->add(utils::HtmlEntities($e->getMessage()));
|
||||
Usage($oP);
|
||||
$oP->output();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
$oP = new WebPage('iTop Export');
|
||||
$oP->add_http_headers();
|
||||
$oP->add('Error: '.utils::HtmlEntities($e->getMessage()));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -20,12 +21,10 @@
|
||||
if (isset($_REQUEST['debug'])) {
|
||||
if ($_REQUEST['debug'] == 'text') {
|
||||
header('Content-Type: text/plain; charset=UTF-8');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
header('Content-Type: application/xml; charset=UTF-8');
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// This is to make sure that the client will accept it....
|
||||
//
|
||||
header('Content-Type: application/xml; charset=UTF-8');
|
||||
@@ -47,8 +46,7 @@ require_once(APPROOT.'webservices/webservices.basic.php');
|
||||
$sServiceCategory = utils::ReadParam('service_category');
|
||||
if (!empty($sServiceCategory)) {
|
||||
$sRawFile = WebServicesBase::GetWSDLContents($sServiceCategory);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$sRawFile = WebServicesBase::GetWSDLContents();
|
||||
}
|
||||
|
||||
@@ -64,4 +62,3 @@ $sFinalFile = str_replace(
|
||||
);
|
||||
|
||||
echo $sFinalFile;
|
||||
?>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
@@ -16,9 +17,8 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Shows a usage of the SOAP queries
|
||||
* Shows a usage of the SOAP queries
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
@@ -36,29 +36,26 @@
|
||||
* @return bool|false|string
|
||||
* @throws \Exception
|
||||
*/
|
||||
function DoPostRequest($sUrl, $aData, $sOptionnalHeaders = null, &$aResponseHeaders = null, $aCurlOptions = array())
|
||||
function DoPostRequest($sUrl, $aData, $sOptionnalHeaders = null, &$aResponseHeaders = null, $aCurlOptions = [])
|
||||
{
|
||||
// $sOptionnalHeaders is a string containing additional HTTP headers that you would like to send in your request.
|
||||
|
||||
if (function_exists('curl_init'))
|
||||
{
|
||||
if (function_exists('curl_init')) {
|
||||
// If cURL is available, let's use it, since it provides a greater control over the various HTTP/SSL options
|
||||
// For instance fopen does not allow to work around the bug: http://stackoverflow.com/questions/18191672/php-curl-ssl-routinesssl23-get-server-helloreason1112
|
||||
// by setting the SSLVERSION to 3 as done below.
|
||||
$aHTTPHeaders = array();
|
||||
if ($sOptionnalHeaders !== null)
|
||||
{
|
||||
$aHTTPHeaders = [];
|
||||
if ($sOptionnalHeaders !== null) {
|
||||
$aHeaders = explode("\n", $sOptionnalHeaders);
|
||||
// N°3267 - Webservices: Fix optional headers not being taken into account
|
||||
// See https://www.php.net/curl_setopt CURLOPT_HTTPHEADER
|
||||
$aHTTPHeaders = array();
|
||||
foreach($aHeaders as $sHeaderString)
|
||||
{
|
||||
$aHTTPHeaders = [];
|
||||
foreach ($aHeaders as $sHeaderString) {
|
||||
$aHTTPHeaders[] = trim($sHeaderString);
|
||||
}
|
||||
}
|
||||
// Default options, can be overloaded/extended with the 4th parameter of this method, see above $aCurlOptions
|
||||
$aOptions = array(
|
||||
$aOptions = [
|
||||
CURLOPT_RETURNTRANSFER => true, // return the content of the request
|
||||
CURLOPT_HEADER => false, // don't return the headers in the output
|
||||
CURLOPT_FOLLOWLOCATION => true, // follow redirects
|
||||
@@ -76,74 +73,58 @@ function DoPostRequest($sUrl, $aData, $sOptionnalHeaders = null, &$aResponseHead
|
||||
CURLOPT_POST => count($aData),
|
||||
CURLOPT_POSTFIELDS => http_build_query($aData),
|
||||
CURLOPT_HTTPHEADER => $aHTTPHeaders,
|
||||
);
|
||||
];
|
||||
$aAllOptions = $aCurlOptions + $aOptions;
|
||||
$ch = curl_init($sUrl);
|
||||
curl_setopt_array($ch, $aAllOptions);
|
||||
$response = curl_exec($ch);
|
||||
$iErr = curl_errno($ch);
|
||||
$sErrMsg = curl_error( $ch );
|
||||
if ($iErr !== 0)
|
||||
{
|
||||
$sErrMsg = curl_error($ch);
|
||||
if ($iErr !== 0) {
|
||||
throw new Exception("Problem opening URL: $sUrl, $sErrMsg");
|
||||
}
|
||||
if (is_array($aResponseHeaders))
|
||||
{
|
||||
if (is_array($aResponseHeaders)) {
|
||||
$aHeaders = curl_getinfo($ch);
|
||||
foreach($aHeaders as $sCode => $sValue)
|
||||
{
|
||||
$sName = str_replace(' ' , '-', ucwords(str_replace('_', ' ', $sCode))); // Transform "content_type" into "Content-Type"
|
||||
foreach ($aHeaders as $sCode => $sValue) {
|
||||
$sName = str_replace(' ', '-', ucwords(str_replace('_', ' ', $sCode))); // Transform "content_type" into "Content-Type"
|
||||
$aResponseHeaders[$sName] = $sValue;
|
||||
}
|
||||
}
|
||||
curl_close( $ch );
|
||||
}
|
||||
else
|
||||
{
|
||||
curl_close($ch);
|
||||
} else {
|
||||
// cURL is not available let's try with streams and fopen...
|
||||
|
||||
$sData = http_build_query($aData);
|
||||
$aParams = array('http' => array(
|
||||
$aParams = ['http' => [
|
||||
'method' => 'POST',
|
||||
'content' => $sData,
|
||||
'header'=> "Content-type: application/x-www-form-urlencoded\r\nContent-Length: ".strlen($sData)."\r\n",
|
||||
));
|
||||
if ($sOptionnalHeaders !== null)
|
||||
{
|
||||
'header' => "Content-type: application/x-www-form-urlencoded\r\nContent-Length: ".strlen($sData)."\r\n",
|
||||
]];
|
||||
if ($sOptionnalHeaders !== null) {
|
||||
$aParams['http']['header'] .= $sOptionnalHeaders;
|
||||
}
|
||||
$ctx = stream_context_create($aParams);
|
||||
|
||||
$fp = @fopen($sUrl, 'rb', false, $ctx);
|
||||
if (!$fp)
|
||||
{
|
||||
if (!$fp) {
|
||||
global $php_errormsg;
|
||||
if (isset($php_errormsg))
|
||||
{
|
||||
if (isset($php_errormsg)) {
|
||||
throw new Exception("Wrong URL: $sUrl, $php_errormsg");
|
||||
}
|
||||
elseif ((strtolower(substr($sUrl, 0, 5)) == 'https') && !extension_loaded('openssl'))
|
||||
{
|
||||
} elseif ((strtolower(substr($sUrl, 0, 5)) == 'https') && !extension_loaded('openssl')) {
|
||||
throw new Exception("Cannot connect to $sUrl: missing module 'openssl'");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
throw new Exception("Wrong URL: $sUrl");
|
||||
}
|
||||
}
|
||||
$response = @stream_get_contents($fp);
|
||||
if ($response === false)
|
||||
{
|
||||
if ($response === false) {
|
||||
throw new Exception("Problem reading data from $sUrl, $php_errormsg");
|
||||
}
|
||||
if (is_array($aResponseHeaders))
|
||||
{
|
||||
if (is_array($aResponseHeaders)) {
|
||||
$aMeta = stream_get_meta_data($fp);
|
||||
$aHeaders = $aMeta['wrapper_data'];
|
||||
foreach($aHeaders as $sHeaderString)
|
||||
{
|
||||
if(preg_match('/^([^:]+): (.+)$/', $sHeaderString, $aMatches))
|
||||
{
|
||||
foreach ($aHeaders as $sHeaderString) {
|
||||
if (preg_match('/^([^:]+): (.+)$/', $sHeaderString, $aMatches)) {
|
||||
$aResponseHeaders[$aMatches[1]] = trim($aMatches[2]);
|
||||
}
|
||||
}
|
||||
@@ -161,208 +142,203 @@ function DoPostRequest($sUrl, $aData, $sOptionnalHeaders = null, &$aResponseHead
|
||||
// Define the operations to perform (one operation per call the rest service)
|
||||
//
|
||||
|
||||
$aOperations = array(
|
||||
array(
|
||||
$aOperations = [
|
||||
[
|
||||
'operation' => 'list_operations', // operation code
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'operation' => 'core/create', // operation code
|
||||
'comment' => 'Synchronization from blah...', // comment recorded in the change tracking log
|
||||
'class' => 'UserRequest',
|
||||
'output_fields' => 'id, friendlyname', // list of fields to show in the results (* or a,b,c)
|
||||
// Values for the object to create
|
||||
'fields' => array(
|
||||
'fields' => [
|
||||
'org_id' => "SELECT Organization WHERE name = 'Demo'",
|
||||
'caller_id' => array('name' => 'monet', 'first_name' => 'claude'),
|
||||
'caller_id' => ['name' => 'monet', 'first_name' => 'claude'],
|
||||
'title' => 'issue blah',
|
||||
'description' => 'something happened'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'description' => 'something happened',
|
||||
],
|
||||
],
|
||||
[
|
||||
'operation' => 'core/update', // operation code
|
||||
'comment' => 'Synchronization from blah...', // comment recorded in the change tracking log
|
||||
'class' => 'UserRequest',
|
||||
'key' => 'SELECT UserRequest WHERE id=1',
|
||||
'output_fields' => 'id, friendlyname, title', // list of fields to show in the results (* or a,b,c)
|
||||
// Values for the object to create
|
||||
'fields' => array(
|
||||
'fields' => [
|
||||
'title' => 'Issue #'.rand(0, 100),
|
||||
'contacts_list' => array(
|
||||
array(
|
||||
'contacts_list' => [
|
||||
[
|
||||
'role' => 'fireman #'.rand(0, 100),
|
||||
'contact_id' => array('finalclass' => 'Person', 'name' => 'monet', 'first_name' => 'claude'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
'contact_id' => ['finalclass' => 'Person', 'name' => 'monet', 'first_name' => 'claude'],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
// Rewrite the full CaseLog on an existing UserRequest with id=1, setting date and user (optional)
|
||||
array(
|
||||
[
|
||||
'operation' => 'core/update',
|
||||
'comment' => 'Synchronization from Client A', // comment recorded in the change tracking log
|
||||
'class' => 'UserRequest',
|
||||
'key' => 'SELECT UserRequest WHERE id=1',
|
||||
'output_fields' => 'id, friendlyname, title',
|
||||
'fields' => array(
|
||||
'public_log' => array(
|
||||
'items' => array(
|
||||
0 => array(
|
||||
'fields' => [
|
||||
'public_log' => [
|
||||
'items' => [
|
||||
0 => [
|
||||
'date' => '2001-02-01 23:59:59', //Allow to set the date of a true event, an alarm for eg.
|
||||
'user_login' => 'Alarm monitoring', //Free text
|
||||
'user_id' => 0, //0 is required for the user_login to be taken into account
|
||||
'message' => 'This is 1st entry as an <b>HTML</b> formatted<br>text',
|
||||
),
|
||||
1 => array(
|
||||
],
|
||||
1 => [
|
||||
'date' => '2001-02-02 00:00:00', //If ommitted set automatically.
|
||||
'user_login' => 'Alarm monitoring', //user=id=0 is missing so will be ignored
|
||||
'message' => 'Second entry in text format:
|
||||
with new line, but format not specified, so treated as HTML!, user_id=0 missing, so user_login ignored',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
// Add a Text entry in the HTML CaseLog of the UserRequest with id=1, setting date and user (optional)
|
||||
array(
|
||||
[
|
||||
'operation' => 'core/update', // operation code
|
||||
'comment' => 'Synchronization from Alarm Monitoring', // comment recorded in the change tracking log
|
||||
'class' => 'UserRequest',
|
||||
'key' => 1, // object id or OQL
|
||||
'output_fields' => 'id, friendlyname, title', // list of fields to show in the results (* or a,b,c)
|
||||
// Example of adding an entry into a CaseLog on an existing UserRequest
|
||||
'fields' => array(
|
||||
'public_log' => array(
|
||||
'add_item' => array(
|
||||
'fields' => [
|
||||
'public_log' => [
|
||||
'add_item' => [
|
||||
'user_login' => 'New Entry', //Free text
|
||||
'user_id' => 0, //0 is required for the user_login to be taken into account
|
||||
'format' => 'text', //If ommitted, source is expected to be HTML
|
||||
'message' => 'This text is not HTML formatted with 3 lines:
|
||||
new line
|
||||
3rd and last line',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
array(
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'operation' => 'core/get', // operation code
|
||||
'class' => 'UserRequest',
|
||||
'key' => 'SELECT UserRequest',
|
||||
'output_fields' => 'id, friendlyname, title, contacts_list', // list of fields to show in the results (* or a,b,c)
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'operation' => 'core/delete', // operation code
|
||||
'comment' => 'Cleanup for synchro with...', // comment recorded in the change tracking log
|
||||
'class' => 'UserRequest',
|
||||
'key' => 'SELECT UserRequest WHERE org_id = 2',
|
||||
'simulate' => true,
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'operation' => 'core/apply_stimulus', // operation code
|
||||
'comment' => 'Synchronization from blah...', // comment recorded in the change tracking log
|
||||
'class' => 'UserRequest',
|
||||
'key' => 1,
|
||||
'stimulus' => 'ev_assign',
|
||||
// Values to set
|
||||
'fields' => array(
|
||||
'fields' => [
|
||||
'team_id' => 15, // Helpdesk
|
||||
'agent_id' => 9 // Jules Verne
|
||||
),
|
||||
'agent_id' => 9, // Jules Verne
|
||||
],
|
||||
'output_fields' => 'id, friendlyname, title, contacts_list', // list of fields to show in the results (* or a,b,c)
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'operation' => 'core/get_related', // operation code
|
||||
'class' => 'Server',
|
||||
'key' => 'SELECT Server',
|
||||
'relation' => 'impacts', // relation code
|
||||
'depth' => 4, // max recursion depth
|
||||
),
|
||||
);
|
||||
$aOperations = array(
|
||||
array(
|
||||
],
|
||||
];
|
||||
$aOperations = [
|
||||
[
|
||||
'operation' => 'core/create', // operation code
|
||||
'comment' => 'Automatic creation of attachment blah blah...', // comment recorded in the change tracking log
|
||||
'class' => 'Attachment',
|
||||
'output_fields' => 'id, friendlyname', // list of fields to show in the results (* or a,b,c)
|
||||
// Values for the object to create
|
||||
'fields' => array(
|
||||
'fields' => [
|
||||
'item_class' => 'UserRequest',
|
||||
'item_id' => 1,
|
||||
'item_org_id' => 3,
|
||||
'contents' => array(
|
||||
'contents' => [
|
||||
'data' => 'iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAIAAAC0tAIdAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACmSURBVChTfZHRDYMwDESzQ2fqhHx3C3ao+MkW/WlnaFxfzk7sEnE6JHJ+NgaKZN2zLHVN2ssfkae0Da7FQ5PRk/ve4Hcx19Ie6CEGuh/6vMgNhwanHVUNbt73lUDbYJ+6pg8b3+m2RehsVPdMXyvQY+OVkB+Rrv64lUjb3nq+aCA6v4leRqtfaIgimr53atBy9PlfUhoh3fFCNDmErv9FWR6ylBL5AREbmHBnFj5lAAAAAElFTkSuQmCC',
|
||||
'filename' => 'myself.png',
|
||||
'mimetype' => 'image/png'
|
||||
),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'mimetype' => 'image/png',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'operation' => 'core/get', // operation code
|
||||
'class' => 'Attachment',
|
||||
'key' => 'SELECT Attachment',
|
||||
'output_fields' => '*',
|
||||
)
|
||||
);
|
||||
$aOperations = array(
|
||||
array(
|
||||
],
|
||||
];
|
||||
$aOperations = [
|
||||
[
|
||||
'operation' => 'core/update', // operation code
|
||||
'comment' => 'Synchronization from blah...', // comment recorded in the change tracking log
|
||||
'class' => 'Server',
|
||||
'key' => 'SELECT Server WHERE name="Server1"',
|
||||
'output_fields' => 'id, friendlyname, description', // list of fields to show in the results (* or a,b,c)
|
||||
// Values for the object to create
|
||||
'fields' => array(
|
||||
'fields' => [
|
||||
'description' => 'Issue #'.time(),
|
||||
),
|
||||
),
|
||||
);
|
||||
$aOperations = array(
|
||||
array(
|
||||
],
|
||||
],
|
||||
];
|
||||
$aOperations = [
|
||||
[
|
||||
'operation' => 'core/create', // operation code
|
||||
'comment' => 'Synchronization from blah...', // comment recorded in the change tracking log
|
||||
'class' => 'UserRequest',
|
||||
'output_fields' => 'id, friendlyname', // list of fields to show in the results (* or a,b,c)
|
||||
// Values for the object to create
|
||||
'fields' => array(
|
||||
'fields' => [
|
||||
'org_id' => "SELECT Organization WHERE name = 'Demo'",
|
||||
'caller_id' => array('name' => 'monet', 'first_name' => 'claude'),
|
||||
'caller_id' => ['name' => 'monet', 'first_name' => 'claude'],
|
||||
'title' => 'issue blah',
|
||||
'description' => 'something happened'
|
||||
),
|
||||
),
|
||||
);
|
||||
$aXXXOperations = array(
|
||||
array(
|
||||
'description' => 'something happened',
|
||||
],
|
||||
],
|
||||
];
|
||||
$aXXXOperations = [
|
||||
[
|
||||
'operation' => 'core/check_credentials', // operation code
|
||||
'user' => 'admin',
|
||||
'password' => 'admin',
|
||||
),
|
||||
);
|
||||
$aDeleteOperations = array(
|
||||
array(
|
||||
],
|
||||
];
|
||||
$aDeleteOperations = [
|
||||
[
|
||||
'operation' => 'core/delete', // operation code
|
||||
'comment' => 'Cleanup for synchro with...', // comment recorded in the change tracking log
|
||||
'class' => 'Server',
|
||||
'key' => 'SELECT Server',
|
||||
'simulate' => false,
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
|
||||
if (false)
|
||||
{
|
||||
if (false) {
|
||||
echo "Please edit the sample script and configure the server URL";
|
||||
exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$sUrl = "https://localhost/itop/webservices/rest.php?version=1.3";
|
||||
}
|
||||
|
||||
$aData = array();
|
||||
$aData = [];
|
||||
$aData['auth_user'] = 'rest';
|
||||
$aData['auth_pwd'] = 'rest';
|
||||
|
||||
|
||||
foreach ($aOperations as $iOp => $aOperation)
|
||||
{
|
||||
foreach ($aOperations as $iOp => $aOperation) {
|
||||
echo "======================================\n";
|
||||
echo "Operation #$iOp: ".$aOperation['operation']."\n";
|
||||
$aData['json_data'] = json_encode($aOperation);
|
||||
@@ -371,25 +347,18 @@ foreach ($aOperations as $iOp => $aOperation)
|
||||
echo "Input:\n";
|
||||
print_r($aOperation);
|
||||
$aResults = null;
|
||||
try
|
||||
{
|
||||
try {
|
||||
$response = DoPostRequest($sUrl, $aData);
|
||||
$aResults = json_decode($response);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
$response = $e->getMessage();
|
||||
}
|
||||
if ($aResults)
|
||||
{
|
||||
if ($aResults) {
|
||||
echo "--------------------------------------\n";
|
||||
echo "Reply:\n";
|
||||
print_r($aResults);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
echo "ERROR rest.php replied:\n";
|
||||
echo $response;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
@@ -16,9 +17,8 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Shows a usage of the SOAP queries
|
||||
* Shows a usage of the SOAP queries
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
@@ -31,17 +31,16 @@ $sWsdlUri = $sItopRoot.'/webservices/itop.wsdl.php';
|
||||
|
||||
$aSOAPMapping = SOAPMapping::GetMapping();
|
||||
|
||||
ini_set("soap.wsdl_cache_enabled","0");
|
||||
ini_set("soap.wsdl_cache_enabled", "0");
|
||||
$oSoapClient = new SoapClient(
|
||||
$sWsdlUri,
|
||||
array(
|
||||
[
|
||||
'trace' => 1,
|
||||
'classmap' => $aSOAPMapping, // defined in itopsoaptypes.class.inc.php
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
// The most simple service, returning a string
|
||||
//
|
||||
$sServerVersion = $oSoapClient->GetVersion();
|
||||
@@ -50,30 +49,29 @@ try
|
||||
// More complex ones, returning a SOAPResult structure
|
||||
// (run the page to know more about the returned data)
|
||||
//
|
||||
$oRes = $oSoapClient->CreateIncidentTicket
|
||||
(
|
||||
$oRes = $oSoapClient->CreateIncidentTicket(
|
||||
'admin', /* login */
|
||||
'admin', /* password */
|
||||
'Email server down', /* title */
|
||||
'HW found shutdown', /* description */
|
||||
null, /* caller */
|
||||
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', 'Demo'))), /* customer */
|
||||
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', 'NW Management'))), /* service */
|
||||
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', 'Troubleshooting'))), /* service subcategory */
|
||||
new SOAPExternalKeySearch([new SOAPSearchCondition('name', 'Demo')]), /* customer */
|
||||
new SOAPExternalKeySearch([new SOAPSearchCondition('name', 'NW Management')]), /* service */
|
||||
new SOAPExternalKeySearch([new SOAPSearchCondition('name', 'Troubleshooting')]), /* service subcategory */
|
||||
'', /* product */
|
||||
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', 'NW support'))), /* workgroup */
|
||||
array(
|
||||
new SOAPExternalKeySearch([new SOAPSearchCondition('name', 'NW support')]), /* workgroup */
|
||||
[
|
||||
new SOAPLinkCreationSpec(
|
||||
'Device',
|
||||
array(new SOAPSearchCondition('name', 'switch01')),
|
||||
array()
|
||||
[new SOAPSearchCondition('name', 'switch01')],
|
||||
[]
|
||||
),
|
||||
new SOAPLinkCreationSpec(
|
||||
'Server',
|
||||
array(new SOAPSearchCondition('name', 'dbserver1.demo.com')),
|
||||
array()
|
||||
[new SOAPSearchCondition('name', 'dbserver1.demo.com')],
|
||||
[]
|
||||
),
|
||||
), /* impacted cis */
|
||||
], /* impacted cis */
|
||||
'1', /* impact */
|
||||
'1' /* urgency */
|
||||
);
|
||||
@@ -84,44 +82,36 @@ try
|
||||
echo "</pre>\n";
|
||||
echo "</p>\n";
|
||||
|
||||
$oRes = $oSoapClient->SearchObjects
|
||||
(
|
||||
$oRes = $oSoapClient->SearchObjects(
|
||||
'admin', /* login */
|
||||
'admin', /* password */
|
||||
'SELECT URP_Profiles' /* oql */
|
||||
);
|
||||
|
||||
echo "<p>SearchObjects() returned:\n";
|
||||
if ($oRes->status)
|
||||
{
|
||||
if ($oRes->status) {
|
||||
$aResults = $oRes->result;
|
||||
|
||||
echo "<table>\n";
|
||||
|
||||
// Header made after the first line
|
||||
echo "<tr>\n";
|
||||
foreach ($aResults[0]->values as $aKeyValuePair)
|
||||
{
|
||||
foreach ($aResults[0]->values as $aKeyValuePair) {
|
||||
echo " <th>".$aKeyValuePair->key."</th>\n";
|
||||
}
|
||||
echo "</tr>\n";
|
||||
|
||||
foreach ($aResults as $iRow => $aData)
|
||||
{
|
||||
foreach ($aResults as $iRow => $aData) {
|
||||
echo "<tr>\n";
|
||||
foreach ($aData->values as $aKeyValuePair)
|
||||
{
|
||||
foreach ($aData->values as $aKeyValuePair) {
|
||||
echo " <td>".$aKeyValuePair->value."</td>\n";
|
||||
}
|
||||
echo "</tr>\n";
|
||||
}
|
||||
echo "</table>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$aErrors = array();
|
||||
foreach ($oRes->errors->messages as $oMessage)
|
||||
{
|
||||
} else {
|
||||
$aErrors = [];
|
||||
foreach ($oRes->errors->messages as $oMessage) {
|
||||
$aErrors[] = $oMessage->text;
|
||||
}
|
||||
$sErrorMsg = implode(', ', $aErrors);
|
||||
@@ -131,15 +121,12 @@ try
|
||||
//echo "</pre>\n";
|
||||
}
|
||||
echo "</p>\n";
|
||||
}
|
||||
catch(SoapFault $e)
|
||||
{
|
||||
echo "<h1>SoapFault Exception: {$e->getMessage()}</h1>\n";
|
||||
echo "<h2>Request</h2>\n";
|
||||
echo "<pre>\n";
|
||||
echo htmlspecialchars($oSoapClient->__getLastRequest())."\n";
|
||||
echo "</pre>";
|
||||
} catch (SoapFault $e) {
|
||||
echo "<h1>SoapFault Exception: {$e->getMessage()}</h1>\n";
|
||||
echo "<h2>Request</h2>\n";
|
||||
echo "<pre>\n";
|
||||
echo htmlspecialchars($oSoapClient->__getLastRequest())."\n";
|
||||
echo "</pre>";
|
||||
echo "<h2>Response</h2>";
|
||||
echo $oSoapClient->__getLastResponse()."\n";
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
@@ -16,7 +17,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Declarations required for the WSDL
|
||||
*
|
||||
@@ -24,7 +24,6 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
// Note: the attributes must have the same names (case sensitive) as in the WSDL specification
|
||||
//
|
||||
|
||||
@@ -40,7 +39,6 @@ class SOAPSearchCondition
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SOAPExternalKeySearch
|
||||
{
|
||||
public $conditions; // array of SOAPSearchCondition
|
||||
@@ -52,12 +50,15 @@ class SOAPExternalKeySearch
|
||||
|
||||
public function IsVoid()
|
||||
{
|
||||
if (is_null($this->conditions)) return true;
|
||||
if (count($this->conditions) == 0) return true;
|
||||
if (is_null($this->conditions)) {
|
||||
return true;
|
||||
}
|
||||
if (count($this->conditions) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SOAPAttributeValue
|
||||
{
|
||||
public $attcode; // string
|
||||
@@ -70,7 +71,6 @@ class SOAPAttributeValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SOAPLinkCreationSpec
|
||||
{
|
||||
public $class;
|
||||
@@ -85,7 +85,6 @@ class SOAPLinkCreationSpec
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SOAPLogMessage
|
||||
{
|
||||
public $text; // string
|
||||
@@ -96,7 +95,6 @@ class SOAPLogMessage
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SOAPResultLog
|
||||
{
|
||||
public $messages; // array of SOAPLogMessage
|
||||
@@ -107,7 +105,6 @@ class SOAPResultLog
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SOAPKeyValue
|
||||
{
|
||||
public $key; // string
|
||||
@@ -132,7 +129,6 @@ class SOAPResultMessage
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SOAPResult
|
||||
{
|
||||
public $status; // boolean
|
||||
@@ -163,12 +159,11 @@ class SOAPSimpleResult
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SOAPMapping
|
||||
{
|
||||
static function GetMapping()
|
||||
public static function GetMapping()
|
||||
{
|
||||
$aSOAPMapping = array(
|
||||
$aSOAPMapping = [
|
||||
'SearchCondition' => 'SOAPSearchCondition',
|
||||
'ExternalKeySearch' => 'SOAPExternalKeySearch',
|
||||
'AttributeValue' => 'SOAPAttributeValue',
|
||||
@@ -180,9 +175,7 @@ class SOAPMapping
|
||||
'ResultMessage' => 'SOAPResultMessage',
|
||||
'Result' => 'SOAPResult',
|
||||
'SimpleResult' => 'SOAPSimpleResult',
|
||||
);
|
||||
];
|
||||
return $aSOAPMapping;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -27,10 +28,9 @@ require_once(APPROOT.'/application/startup.inc.php');
|
||||
|
||||
require_once(APPROOT.'core/restservices.class.inc.php');
|
||||
|
||||
|
||||
/**
|
||||
* Result structure that is specific to the hardcoded verb 'list_operations'
|
||||
*/
|
||||
*/
|
||||
class RestResultListOperations extends RestResult
|
||||
{
|
||||
public $version;
|
||||
@@ -38,24 +38,25 @@ class RestResultListOperations extends RestResult
|
||||
|
||||
public function AddOperation($sVerb, $sDescription, $sServiceProviderClass)
|
||||
{
|
||||
$this->operations[] = array(
|
||||
$this->operations[] = [
|
||||
'verb' => $sVerb,
|
||||
'description' => $sDescription,
|
||||
'extension' => $sServiceProviderClass,
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('json_last_error_msg')) {
|
||||
function json_last_error_msg() {
|
||||
static $ERRORS = array(
|
||||
function json_last_error_msg()
|
||||
{
|
||||
static $ERRORS = [
|
||||
JSON_ERROR_NONE => 'No error',
|
||||
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
|
||||
JSON_ERROR_STATE_MISMATCH => 'State mismatch (invalid or malformed JSON)',
|
||||
JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
|
||||
JSON_ERROR_SYNTAX => 'Syntax error',
|
||||
JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded',
|
||||
);
|
||||
];
|
||||
|
||||
$error = json_last_error();
|
||||
return isset($ERRORS[$error]) ? $ERRORS[$error] : 'Unknown error';
|
||||
@@ -74,15 +75,14 @@ $sOperation = utils::ReadParam('operation', null);
|
||||
//read json_data parameter via as a string (standard behaviour)
|
||||
$sJsonString = utils::ReadParam('json_data', null, false, 'raw_data');
|
||||
|
||||
if (empty($sJsonString)){
|
||||
if (empty($sJsonString)) {
|
||||
//N °3455: read json_data parameter via a file passed by http protocol
|
||||
if(isset($_FILES['json_data']['tmp_name']))
|
||||
{
|
||||
if (isset($_FILES['json_data']['tmp_name'])) {
|
||||
$sTmpFilePath = $_FILES['json_data']['tmp_name'];
|
||||
if (is_file($sTmpFilePath)){
|
||||
if (is_file($sTmpFilePath)) {
|
||||
$sValue = file_get_contents($sTmpFilePath);
|
||||
unlink($sTmpFilePath);
|
||||
if (! empty($sValue)){
|
||||
if (! empty($sValue)) {
|
||||
$sJsonString = utils::Sanitize($sValue, null, 'raw_data');
|
||||
}
|
||||
}
|
||||
@@ -92,136 +92,111 @@ if (empty($sJsonString)){
|
||||
$sProvider = '';
|
||||
|
||||
$oKPI = new ExecutionKPI();
|
||||
try
|
||||
{
|
||||
try {
|
||||
utils::UseParamFile();
|
||||
|
||||
|
||||
$oKPI->ComputeAndReport('Data model loaded');
|
||||
|
||||
// N°6358 - force credentials for REST calls
|
||||
LoginWebPage::ResetSession(true);
|
||||
// N°6358 - force credentials for REST calls
|
||||
LoginWebPage::ResetSession(true);
|
||||
$iRet = LoginWebPage::DoLogin(false, false, LoginWebPage::EXIT_RETURN);
|
||||
$oKPI->ComputeAndReport('User login');
|
||||
$oKPI->ComputeAndReport('User login');
|
||||
|
||||
if ($iRet == LoginWebPage::EXIT_CODE_OK)
|
||||
{
|
||||
if ($iRet == LoginWebPage::EXIT_CODE_OK) {
|
||||
// Extra validation of the profile
|
||||
if ((MetaModel::GetConfig()->Get('secure_rest_services') == true) && !UserRights::HasProfile('REST Services User'))
|
||||
{
|
||||
if ((MetaModel::GetConfig()->Get('secure_rest_services') == true) && !UserRights::HasProfile('REST Services User')) {
|
||||
// Web services access is limited to the users with the profile REST Web Services
|
||||
$iRet = LoginWebPage::EXIT_CODE_NOTAUTHORIZED;
|
||||
}
|
||||
}
|
||||
if ($iRet != LoginWebPage::EXIT_CODE_OK)
|
||||
{
|
||||
switch($iRet)
|
||||
{
|
||||
if ($iRet != LoginWebPage::EXIT_CODE_OK) {
|
||||
switch ($iRet) {
|
||||
case LoginWebPage::EXIT_CODE_MISSINGLOGIN:
|
||||
throw new Exception("Missing parameter 'auth_user'", RestResult::MISSING_AUTH_USER);
|
||||
break;
|
||||
|
||||
throw new Exception("Missing parameter 'auth_user'", RestResult::MISSING_AUTH_USER);
|
||||
break;
|
||||
|
||||
case LoginWebPage::EXIT_CODE_MISSINGPASSWORD:
|
||||
throw new Exception("Missing parameter 'auth_pwd'", RestResult::MISSING_AUTH_PWD);
|
||||
break;
|
||||
|
||||
throw new Exception("Missing parameter 'auth_pwd'", RestResult::MISSING_AUTH_PWD);
|
||||
break;
|
||||
|
||||
case LoginWebPage::EXIT_CODE_WRONGCREDENTIALS:
|
||||
throw new Exception("Invalid login", RestResult::UNAUTHORIZED);
|
||||
break;
|
||||
|
||||
throw new Exception("Invalid login", RestResult::UNAUTHORIZED);
|
||||
break;
|
||||
|
||||
case LoginWebPage::EXIT_CODE_PORTALUSERNOTAUTHORIZED:
|
||||
throw new Exception("Portal user is not allowed", RestResult::UNAUTHORIZED);
|
||||
break;
|
||||
|
||||
throw new Exception("Portal user is not allowed", RestResult::UNAUTHORIZED);
|
||||
break;
|
||||
|
||||
case LoginWebPage::EXIT_CODE_NOTAUTHORIZED:
|
||||
throw new Exception("This user is not authorized to use the web services. (The profile REST Services User is required to access the REST web services)", RestResult::UNAUTHORIZED);
|
||||
break;
|
||||
|
||||
throw new Exception("This user is not authorized to use the web services. (The profile REST Services User is required to access the REST web services)", RestResult::UNAUTHORIZED);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception("Unknown authentication error (retCode=$iRet)", RestResult::UNAUTHORIZED);
|
||||
throw new Exception("Unknown authentication error (retCode=$iRet)", RestResult::UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
if ($sVersion == null)
|
||||
{
|
||||
if ($sVersion == null) {
|
||||
throw new Exception("Missing parameter 'version' (e.g. '1.0')", RestResult::MISSING_VERSION);
|
||||
}
|
||||
|
||||
if ($sJsonString == null)
|
||||
{
|
||||
if ($sJsonString == null) {
|
||||
throw new Exception("Missing parameter 'json_data'", RestResult::MISSING_JSON);
|
||||
}
|
||||
|
||||
if (is_string($sJsonString))
|
||||
{
|
||||
$aJsonData = @json_decode($sJsonString);
|
||||
}
|
||||
elseif(is_array($sJsonString))
|
||||
{
|
||||
$aJsonData = (object) $sJsonString;
|
||||
$sJsonString = json_encode($aJsonData);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aJsonData = null;
|
||||
}
|
||||
if (is_string($sJsonString)) {
|
||||
$aJsonData = @json_decode($sJsonString);
|
||||
} elseif (is_array($sJsonString)) {
|
||||
$aJsonData = (object) $sJsonString;
|
||||
$sJsonString = json_encode($aJsonData);
|
||||
} else {
|
||||
$aJsonData = null;
|
||||
}
|
||||
|
||||
if ($aJsonData == null)
|
||||
{
|
||||
throw new Exception('Parameter json_data is not a valid JSON structure', RestResult::INVALID_JSON);
|
||||
}
|
||||
if ($aJsonData == null) {
|
||||
throw new Exception('Parameter json_data is not a valid JSON structure', RestResult::INVALID_JSON);
|
||||
}
|
||||
|
||||
$oKPI->ComputeAndReport('Parameters validated');
|
||||
|
||||
|
||||
/** @var iRestServiceProvider[] $aProviders */
|
||||
$oKPI = new ExecutionKPI();
|
||||
$aProviders = array();
|
||||
foreach(get_declared_classes() as $sPHPClass)
|
||||
{
|
||||
$aProviders = [];
|
||||
foreach (get_declared_classes() as $sPHPClass) {
|
||||
$oRefClass = new ReflectionClass($sPHPClass);
|
||||
if ($oRefClass->implementsInterface('iRestServiceProvider'))
|
||||
{
|
||||
$aProviders[] = new $sPHPClass;
|
||||
if ($oRefClass->implementsInterface('iRestServiceProvider')) {
|
||||
$aProviders[] = new $sPHPClass();
|
||||
}
|
||||
}
|
||||
|
||||
$aOpToRestService = array(); // verb => $oRestServiceProvider
|
||||
$aOpToRestService = []; // verb => $oRestServiceProvider
|
||||
/** @var iRestServiceProvider $oRestSP */
|
||||
foreach ($aProviders as $oRestSP)
|
||||
{
|
||||
foreach ($aProviders as $oRestSP) {
|
||||
$aOperations = $oRestSP->ListOperations($sVersion);
|
||||
foreach ($aOperations as $aOpData)
|
||||
{
|
||||
$aOpToRestService[$aOpData['verb']] = array
|
||||
(
|
||||
foreach ($aOperations as $aOpData) {
|
||||
$aOpToRestService[$aOpData['verb']] =
|
||||
[
|
||||
'service_provider' => $oRestSP,
|
||||
'description' => $aOpData['description'],
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
$oKPI->ComputeAndReport('iRestServiceProvider loaded with operations');
|
||||
|
||||
if (count($aOpToRestService) == 0)
|
||||
{
|
||||
if (count($aOpToRestService) == 0) {
|
||||
throw new Exception("There is no service available for version '$sVersion'", RestResult::UNSUPPORTED_VERSION);
|
||||
}
|
||||
|
||||
|
||||
$sOperation = RestUtils::GetMandatoryParam($aJsonData, 'operation');
|
||||
if ($sOperation == 'list_operations')
|
||||
{
|
||||
if ($sOperation == 'list_operations') {
|
||||
$oResult = new RestResultListOperations();
|
||||
$oResult->message = "Operations: ".count($aOpToRestService);
|
||||
$oResult->version = $sVersion;
|
||||
foreach ($aOpToRestService as $sVerb => $aOpData)
|
||||
{
|
||||
foreach ($aOpToRestService as $sVerb => $aOpData) {
|
||||
$oResult->AddOperation($sVerb, $aOpData['description'], get_class($aOpData['service_provider']));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!array_key_exists($sOperation, $aOpToRestService))
|
||||
{
|
||||
} else {
|
||||
if (!array_key_exists($sOperation, $aOpToRestService)) {
|
||||
throw new Exception("Unknown verb '$sOperation' in version '$sVersion'", RestResult::UNKNOWN_OPERATION);
|
||||
}
|
||||
/** @var iRestServiceProvider $oRS */
|
||||
@@ -236,16 +211,11 @@ try
|
||||
$oResult = $oRS->ExecOperation($sVersion, $sOperation, $aJsonData);
|
||||
}
|
||||
$oKPI->ComputeAndReport('Operation finished');
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
$oResult = new RestResult();
|
||||
if ($e->GetCode() == 0)
|
||||
{
|
||||
if ($e->GetCode() == 0) {
|
||||
$oResult->code = RestResult::INTERNAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oResult->code = $e->GetCode();
|
||||
}
|
||||
$oResult->message = "Error: ".$e->GetMessage();
|
||||
@@ -256,23 +226,17 @@ catch(Exception $e)
|
||||
//
|
||||
$sResponse = json_encode($oResult);
|
||||
|
||||
|
||||
if ($sResponse === false)
|
||||
{
|
||||
if ($sResponse === false) {
|
||||
$oJsonIssue = new RestResult();
|
||||
$oJsonIssue->code = RestResult::INTERNAL_ERROR;
|
||||
$oJsonIssue->message = 'json encoding failed with message: '.json_last_error_msg().'. Full response structure for debugging purposes (print_r+bin2hex): '.bin2hex(print_r($oResult, true));
|
||||
$sResponse = json_encode($oJsonIssue);
|
||||
}
|
||||
|
||||
|
||||
$sCallback = utils::ReadParam('callback', null);
|
||||
if ($sCallback == null)
|
||||
{
|
||||
if ($sCallback == null) {
|
||||
$oP = new JsonPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oP = new JsonPPage($sCallback);
|
||||
}
|
||||
$oP->add_header('Access-Control-Allow-Origin: *');
|
||||
@@ -283,18 +247,16 @@ ExecutionKPI::ReportStats();
|
||||
|
||||
// Log usage
|
||||
//
|
||||
if (MetaModel::GetConfig()->Get('log_rest_service'))
|
||||
{
|
||||
if (MetaModel::GetConfig()->Get('log_rest_service')) {
|
||||
$oLog = new EventRestService();
|
||||
$oLog->SetTrim('userinfo', UserRights::GetUser());
|
||||
$oLog->Set('version', $sVersion);
|
||||
$oLog->Set('operation', $sOperation);
|
||||
$oLog->SetTrim('json_input', $sSanitizedJsonInput ?? $sJsonString);
|
||||
$oLog->SetTrim('json_input', $sSanitizedJsonInput ?? $sJsonString);
|
||||
|
||||
$oLog->Set('provider', $sProvider);
|
||||
$sMessage = $oResult->message;
|
||||
if (empty($oResult->message))
|
||||
{
|
||||
if (empty($oResult->message)) {
|
||||
$sMessage = 'Ok';
|
||||
}
|
||||
$oLog->SetTrim('message', $sMessage);
|
||||
@@ -303,7 +265,7 @@ if (MetaModel::GetConfig()->Get('log_rest_service'))
|
||||
$iUnescapeSlashAndUnicode = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
|
||||
$sJsonOuputWithPrettyPrinting = json_encode($oResult, $iUnescapeSlashAndUnicode | JSON_PRETTY_PRINT);
|
||||
$sJsonOutputWithoutPrettyPrinting = json_encode($oResult, $iUnescapeSlashAndUnicode);
|
||||
!StringFitsInLogField( $sJsonOuputWithPrettyPrinting) ?
|
||||
!StringFitsInLogField($sJsonOuputWithPrettyPrinting) ?
|
||||
$oLog->SetTrim('json_output', $sJsonOutputWithoutPrettyPrinting) : // too long, we don't make it pretty
|
||||
$oLog->SetTrim('json_output', $sJsonOuputWithPrettyPrinting);
|
||||
|
||||
@@ -316,4 +278,4 @@ if (MetaModel::GetConfig()->Get('log_rest_service'))
|
||||
function StringFitsInLogField(string $sLog): bool
|
||||
{
|
||||
return mb_strlen($sLog) <= 16383; // hardcoded value, see N°8260
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -27,59 +28,46 @@ require_once(APPROOT.'/application/startup.inc.php');
|
||||
// this file is generated dynamically with location = here
|
||||
$sWsdlUri = utils::GetAbsoluteUrlAppRoot().'webservices/itop.wsdl.php';
|
||||
$sServiceCategory = utils::ReadParam('service_category');
|
||||
if (!empty($sServiceCategory))
|
||||
{
|
||||
if (!empty($sServiceCategory)) {
|
||||
$sWsdlUri .= "?service_category=".$sServiceCategory;
|
||||
}
|
||||
|
||||
|
||||
ini_set("soap.wsdl_cache_enabled","0");
|
||||
ini_set("soap.wsdl_cache_enabled", "0");
|
||||
|
||||
$aSOAPMapping = SOAPMapping::GetMapping();
|
||||
$oSoapServer = new SoapServer
|
||||
(
|
||||
$oSoapServer = new SoapServer(
|
||||
$sWsdlUri,
|
||||
array(
|
||||
'classmap' => $aSOAPMapping
|
||||
)
|
||||
[
|
||||
'classmap' => $aSOAPMapping,
|
||||
]
|
||||
);
|
||||
// $oSoapServer->setPersistence(SOAP_PERSISTENCE_SESSION);
|
||||
if (!empty($sServiceCategory))
|
||||
{
|
||||
if (!empty($sServiceCategory)) {
|
||||
$sServiceClass = $sServiceCategory;
|
||||
if (!class_exists($sServiceClass))
|
||||
{
|
||||
if (!class_exists($sServiceClass)) {
|
||||
// not a valid class name (not a PHP class at all)
|
||||
throw new SoapFault("iTop SOAP server", "Invalid argument service_category: '$sServiceClass' is not a PHP class");
|
||||
}
|
||||
elseif (!is_subclass_of($sServiceClass, 'WebServicesBase'))
|
||||
{
|
||||
} elseif (!is_subclass_of($sServiceClass, 'WebServicesBase')) {
|
||||
// not a valid class name (not deriving from WebServicesBase)
|
||||
throw new SoapFault("iTop SOAP server", "Invalid argument service_category: '$sServiceClass' is not derived from WebServicesBase");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oSoapServer->setClass($sServiceClass, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oSoapServer->setClass('BasicServices', null);
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST")
|
||||
{
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
CMDBObject::SetTrackOrigin('webservice-soap');
|
||||
$oSoapServer->handle();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
echo "This SOAP server can handle the following functions: ";
|
||||
$aFunctions = $oSoapServer->getFunctions();
|
||||
echo "<ul>\n";
|
||||
foreach($aFunctions as $sFunc)
|
||||
{
|
||||
if ($sFunc == 'GetWSDLContents') continue;
|
||||
foreach ($aFunctions as $sFunc) {
|
||||
if ($sFunc == 'GetWSDLContents') {
|
||||
continue;
|
||||
}
|
||||
|
||||
echo "<li>$sFunc</li>\n";
|
||||
}
|
||||
@@ -88,10 +76,8 @@ else
|
||||
|
||||
echo "You may also want to try the following service categories: ";
|
||||
echo "<ul>\n";
|
||||
foreach(get_declared_classes() as $sPHPClass)
|
||||
{
|
||||
if (is_subclass_of($sPHPClass, 'WebServicesBase'))
|
||||
{
|
||||
foreach (get_declared_classes() as $sPHPClass) {
|
||||
if (is_subclass_of($sPHPClass, 'WebServicesBase')) {
|
||||
$sServiceCategory = $sPHPClass;
|
||||
$sSoapServerUri = utils::GetAbsoluteUrlAppRoot().'webservices/soapserver.php';
|
||||
$sSoapServerUri .= "?service_category=$sServiceCategory";
|
||||
@@ -100,4 +86,3 @@ else
|
||||
}
|
||||
echo "</ul>\n";
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -6,21 +6,18 @@ require_once(__DIR__.'/../approot.inc.php');
|
||||
use Combodo\iTop\Application\Status\Status;
|
||||
|
||||
//Do check Status
|
||||
try
|
||||
{
|
||||
new Status();
|
||||
$aResult = ['status' => STATUS_RUNNING, 'code' => RestResult::OK, 'message' => ''];
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$iCode = (defined('\RestResult::INTERNAL_ERROR')) ? RestResult::INTERNAL_ERROR : 100;
|
||||
$aResult = ['status' => STATUS_ERROR, 'code' => $iCode, 'message' => $e->getMessage()];
|
||||
http_response_code(500);
|
||||
try {
|
||||
new Status();
|
||||
$aResult = ['status' => STATUS_RUNNING, 'code' => RestResult::OK, 'message' => ''];
|
||||
} catch (Exception $e) {
|
||||
$iCode = (defined('\RestResult::INTERNAL_ERROR')) ? RestResult::INTERNAL_ERROR : 100;
|
||||
$aResult = ['status' => STATUS_ERROR, 'code' => $iCode, 'message' => $e->getMessage()];
|
||||
http_response_code(500);
|
||||
}
|
||||
|
||||
//Set headers, based on webservices/rest.php
|
||||
$sContentType = 'application/json';
|
||||
header('Content-type: ' . $sContentType);
|
||||
header('Content-type: '.$sContentType);
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
|
||||
//Output result
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
@@ -16,7 +17,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of iTop SOAP services
|
||||
*
|
||||
@@ -26,10 +26,9 @@
|
||||
|
||||
require_once(APPROOT.'/webservices/webservices.class.inc.php');
|
||||
|
||||
|
||||
class BasicServices extends WebServicesBase
|
||||
{
|
||||
static protected function GetWSDLFilePath()
|
||||
protected static function GetWSDLFilePath()
|
||||
{
|
||||
return APPROOT.'/webservices/itop.wsdl.tpl';
|
||||
}
|
||||
@@ -39,14 +38,11 @@ class BasicServices extends WebServicesBase
|
||||
*
|
||||
* @return string WebServiceResult
|
||||
*/
|
||||
static public function GetVersion()
|
||||
public static function GetVersion()
|
||||
{
|
||||
if (ITOP_REVISION == 'svn')
|
||||
{
|
||||
if (ITOP_REVISION == 'svn') {
|
||||
$sVersionString = ITOP_VERSION.' [dev]';
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// This is a build made from SVN, let display the full information
|
||||
$sVersionString = ITOP_VERSION_FULL." ".ITOP_BUILD_DATE;
|
||||
}
|
||||
@@ -56,8 +52,7 @@ class BasicServices extends WebServicesBase
|
||||
|
||||
public function CreateRequestTicket($sLogin, $sPassword, $sTitle, $sDescription, $oCallerDesc, $oCustomerDesc, $oServiceDesc, $oServiceSubcategoryDesc, $sProduct, $oWorkgroupDesc, $aSOAPImpactedCIs, $sImpact, $sUrgency)
|
||||
{
|
||||
if (!UserRights::CheckCredentials($sLogin, $sPassword))
|
||||
{
|
||||
if (!UserRights::CheckCredentials($sLogin, $sPassword)) {
|
||||
$oRes = new WebServiceResultFailedLogin($sLogin);
|
||||
$this->LogUsage(__FUNCTION__, $oRes);
|
||||
|
||||
@@ -71,15 +66,15 @@ class BasicServices extends WebServicesBase
|
||||
$aServiceSubcategoryDesc = self::SoapStructToExternalKeySearch($oServiceSubcategoryDesc);
|
||||
$aWorkgroupDesc = self::SoapStructToExternalKeySearch($oWorkgroupDesc);
|
||||
|
||||
$aImpactedCIs = array();
|
||||
if (is_null($aSOAPImpactedCIs)) $aSOAPImpactedCIs = array();
|
||||
foreach($aSOAPImpactedCIs as $oImpactedCIs)
|
||||
{
|
||||
$aImpactedCIs = [];
|
||||
if (is_null($aSOAPImpactedCIs)) {
|
||||
$aSOAPImpactedCIs = [];
|
||||
}
|
||||
foreach ($aSOAPImpactedCIs as $oImpactedCIs) {
|
||||
$aImpactedCIs[] = self::SoapStructToLinkCreationSpec($oImpactedCIs);
|
||||
}
|
||||
|
||||
$oRes = $this->_CreateResponseTicket
|
||||
(
|
||||
$oRes = $this->_CreateResponseTicket(
|
||||
'UserRequest',
|
||||
$sTitle,
|
||||
$sDescription,
|
||||
@@ -98,8 +93,7 @@ class BasicServices extends WebServicesBase
|
||||
|
||||
public function CreateIncidentTicket($sLogin, $sPassword, $sTitle, $sDescription, $oCallerDesc, $oCustomerDesc, $oServiceDesc, $oServiceSubcategoryDesc, $sProduct, $oWorkgroupDesc, $aSOAPImpactedCIs, $sImpact, $sUrgency)
|
||||
{
|
||||
if (!UserRights::CheckCredentials($sLogin, $sPassword))
|
||||
{
|
||||
if (!UserRights::CheckCredentials($sLogin, $sPassword)) {
|
||||
$oRes = new WebServiceResultFailedLogin($sLogin);
|
||||
$this->LogUsage(__FUNCTION__, $oRes);
|
||||
|
||||
@@ -107,29 +101,27 @@ class BasicServices extends WebServicesBase
|
||||
}
|
||||
UserRights::Login($sLogin);
|
||||
|
||||
|
||||
if (!class_exists('Incident'))
|
||||
{
|
||||
if (!class_exists('Incident')) {
|
||||
$oRes = new WebServiceResult();
|
||||
$oRes->LogError("The class Incident does not exist. Did you install the Incident Management (ITIL) module ?");
|
||||
return $oRes->ToSoapStructure();
|
||||
}
|
||||
|
||||
|
||||
$aCallerDesc = self::SoapStructToExternalKeySearch($oCallerDesc);
|
||||
$aCustomerDesc = self::SoapStructToExternalKeySearch($oCustomerDesc);
|
||||
$aServiceDesc = self::SoapStructToExternalKeySearch($oServiceDesc);
|
||||
$aServiceSubcategoryDesc = self::SoapStructToExternalKeySearch($oServiceSubcategoryDesc);
|
||||
$aWorkgroupDesc = self::SoapStructToExternalKeySearch($oWorkgroupDesc);
|
||||
|
||||
$aImpactedCIs = array();
|
||||
if (is_null($aSOAPImpactedCIs)) $aSOAPImpactedCIs = array();
|
||||
foreach($aSOAPImpactedCIs as $oImpactedCIs)
|
||||
{
|
||||
$aImpactedCIs = [];
|
||||
if (is_null($aSOAPImpactedCIs)) {
|
||||
$aSOAPImpactedCIs = [];
|
||||
}
|
||||
foreach ($aSOAPImpactedCIs as $oImpactedCIs) {
|
||||
$aImpactedCIs[] = self::SoapStructToLinkCreationSpec($oImpactedCIs);
|
||||
}
|
||||
|
||||
$oRes = $this->_CreateResponseTicket
|
||||
(
|
||||
$oRes = $this->_CreateResponseTicket(
|
||||
'Incident',
|
||||
$sTitle,
|
||||
$sDescription,
|
||||
@@ -145,11 +137,11 @@ class BasicServices extends WebServicesBase
|
||||
);
|
||||
return $oRes->ToSoapStructure();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create an ResponseTicket (Incident or UserRequest) from an external system
|
||||
* Some CIs might be specified (by their name/IP)
|
||||
*
|
||||
*
|
||||
* @param string sClass The class of the ticket: Incident or UserRequest
|
||||
* @param string sTitle
|
||||
* @param string sDescription
|
||||
@@ -170,8 +162,7 @@ class BasicServices extends WebServicesBase
|
||||
|
||||
$oRes = new WebServiceResult();
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
CMDBObject::SetTrackInfo('Administrator');
|
||||
|
||||
$oNewTicket = MetaModel::NewObject($sClass);
|
||||
@@ -180,48 +171,36 @@ class BasicServices extends WebServicesBase
|
||||
|
||||
$this->MyObjectSetExternalKey('org_id', 'customer', $aCustomerDesc, $oNewTicket, $oRes);
|
||||
$this->MyObjectSetExternalKey('caller_id', 'caller', $aCallerDesc, $oNewTicket, $oRes);
|
||||
|
||||
|
||||
$this->MyObjectSetExternalKey('service_id', 'service', $aServiceDesc, $oNewTicket, $oRes);
|
||||
if (!array_key_exists('service_id', $aServiceSubcategoryDesc))
|
||||
{
|
||||
if (!array_key_exists('service_id', $aServiceSubcategoryDesc)) {
|
||||
$aServiceSubcategoryDesc['service_id'] = $oNewTicket->Get('service_id');
|
||||
}
|
||||
$this->MyObjectSetExternalKey('servicesubcategory_id', 'servicesubcategory', $aServiceSubcategoryDesc, $oNewTicket, $oRes);
|
||||
if (MetaModel::IsValidAttCode($sClass, 'product'))
|
||||
{
|
||||
if (MetaModel::IsValidAttCode($sClass, 'product')) {
|
||||
// 1.x data models
|
||||
$this->MyObjectSetScalar('product', 'product', $sProduct, $oNewTicket, $oRes);
|
||||
}
|
||||
|
||||
if (MetaModel::IsValidAttCode($sClass, 'workgroup_id'))
|
||||
{
|
||||
if (MetaModel::IsValidAttCode($sClass, 'workgroup_id')) {
|
||||
// 1.x data models
|
||||
$this->MyObjectSetExternalKey('workgroup_id', 'workgroup', $aWorkgroupDesc, $oNewTicket, $oRes);
|
||||
}
|
||||
else if (MetaModel::IsValidAttCode($sClass, 'team_id'))
|
||||
{
|
||||
} elseif (MetaModel::IsValidAttCode($sClass, 'team_id')) {
|
||||
// 2.x data models
|
||||
$this->MyObjectSetExternalKey('team_id', 'workgroup', $aWorkgroupDesc, $oNewTicket, $oRes);
|
||||
}
|
||||
|
||||
|
||||
if (MetaModel::IsValidAttCode($sClass, 'ci_list'))
|
||||
{
|
||||
if (MetaModel::IsValidAttCode($sClass, 'ci_list')) {
|
||||
// 1.x data models
|
||||
$aDevicesNotFound = $this->AddLinkedObjects('ci_list', 'impacted_cis', 'FunctionalCI', $aImpactedCIs, $oNewTicket, $oRes);
|
||||
}
|
||||
else if (MetaModel::IsValidAttCode($sClass, 'functionalcis_list'))
|
||||
{
|
||||
} elseif (MetaModel::IsValidAttCode($sClass, 'functionalcis_list')) {
|
||||
// 2.x data models
|
||||
$aDevicesNotFound = $this->AddLinkedObjects('functionalcis_list', 'impacted_cis', 'FunctionalCI', $aImpactedCIs, $oNewTicket, $oRes);
|
||||
}
|
||||
|
||||
if (count($aDevicesNotFound) > 0)
|
||||
{
|
||||
|
||||
if (count($aDevicesNotFound) > 0) {
|
||||
$this->MyObjectSetScalar('description', 'n/a', $sDescription.' - Related CIs: '.implode(', ', $aDevicesNotFound), $oNewTicket, $oRes);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$this->MyObjectSetScalar('description', 'n/a', $sDescription, $oNewTicket, $oRes);
|
||||
}
|
||||
|
||||
@@ -229,13 +208,9 @@ class BasicServices extends WebServicesBase
|
||||
$this->MyObjectSetScalar('urgency', 'urgency', $sUrgency, $oNewTicket, $oRes);
|
||||
|
||||
$this->MyObjectInsert($oNewTicket, 'created', $oRes);
|
||||
}
|
||||
catch (CoreException $e)
|
||||
{
|
||||
} catch (CoreException $e) {
|
||||
$oRes->LogError($e->getMessage());
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
$oRes->LogError($e->getMessage());
|
||||
}
|
||||
|
||||
@@ -245,13 +220,12 @@ class BasicServices extends WebServicesBase
|
||||
|
||||
/**
|
||||
* Given an OQL, returns a set of objects (several objects could be on the same row)
|
||||
*
|
||||
*
|
||||
* @param string sOQL
|
||||
*/
|
||||
*/
|
||||
public function SearchObjects($sLogin, $sPassword, $sOQL)
|
||||
{
|
||||
if (!UserRights::CheckCredentials($sLogin, $sPassword))
|
||||
{
|
||||
if (!UserRights::CheckCredentials($sLogin, $sPassword)) {
|
||||
$oRes = new WebServiceResultFailedLogin($sLogin);
|
||||
$this->LogUsage(__FUNCTION__, $oRes);
|
||||
|
||||
@@ -266,22 +240,16 @@ class BasicServices extends WebServicesBase
|
||||
protected function _SearchObjects($sOQL)
|
||||
{
|
||||
$oRes = new WebServiceResult();
|
||||
try
|
||||
{
|
||||
try {
|
||||
$oSearch = DBObjectSearch::FromOQL($sOQL);
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
$aData = $oSet->ToArrayOfValues();
|
||||
foreach($aData as $iRow => $aRow)
|
||||
{
|
||||
foreach ($aData as $iRow => $aRow) {
|
||||
$oRes->AddResultRow("row_$iRow", $aRow);
|
||||
}
|
||||
}
|
||||
catch (CoreException $e)
|
||||
{
|
||||
} catch (CoreException $e) {
|
||||
$oRes->LogError($e->getMessage());
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
$oRes->LogError($e->getMessage());
|
||||
}
|
||||
|
||||
@@ -289,4 +257,3 @@ class BasicServices extends WebServicesBase
|
||||
return $oRes;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
@@ -16,7 +17,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of iTop SOAP services
|
||||
*
|
||||
@@ -24,7 +24,6 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
require_once(APPROOT.'/webservices/itopsoaptypes.class.inc.php');
|
||||
|
||||
/**
|
||||
@@ -34,7 +33,6 @@ require_once(APPROOT.'/webservices/itopsoaptypes.class.inc.php');
|
||||
*/
|
||||
class WebServiceResult
|
||||
{
|
||||
|
||||
/**
|
||||
* Overall status
|
||||
*
|
||||
@@ -71,37 +69,32 @@ class WebServiceResult
|
||||
public function __construct()
|
||||
{
|
||||
$this->m_bStatus = true;
|
||||
$this->m_aResult = array();
|
||||
$this->m_aErrors = array();
|
||||
$this->m_aWarnings = array();
|
||||
$this->m_aInfos = array();
|
||||
$this->m_aResult = [];
|
||||
$this->m_aErrors = [];
|
||||
$this->m_aWarnings = [];
|
||||
$this->m_aInfos = [];
|
||||
}
|
||||
|
||||
public function ToSoapStructure()
|
||||
{
|
||||
$aResults = array();
|
||||
foreach($this->m_aResult as $sLabel => $aData)
|
||||
{
|
||||
$aValues = array();
|
||||
foreach($aData as $sKey => $value)
|
||||
{
|
||||
$aResults = [];
|
||||
foreach ($this->m_aResult as $sLabel => $aData) {
|
||||
$aValues = [];
|
||||
foreach ($aData as $sKey => $value) {
|
||||
$aValues[] = new SOAPKeyValue($sKey, $value);
|
||||
}
|
||||
$aResults[] = new SoapResultMessage($sLabel, $aValues);
|
||||
}
|
||||
$aInfos = array();
|
||||
foreach($this->m_aInfos as $sMessage)
|
||||
{
|
||||
$aInfos = [];
|
||||
foreach ($this->m_aInfos as $sMessage) {
|
||||
$aInfos[] = new SoapLogMessage($sMessage);
|
||||
}
|
||||
$aWarnings = array();
|
||||
foreach($this->m_aWarnings as $sMessage)
|
||||
{
|
||||
$aWarnings = [];
|
||||
foreach ($this->m_aWarnings as $sMessage) {
|
||||
$aWarnings[] = new SoapLogMessage($sMessage);
|
||||
}
|
||||
$aErrors = array();
|
||||
foreach($this->m_aErrors as $sMessage)
|
||||
{
|
||||
$aErrors = [];
|
||||
foreach ($this->m_aErrors as $sMessage) {
|
||||
$aErrors[] = new SoapLogMessage($sMessage);
|
||||
}
|
||||
|
||||
@@ -135,11 +128,11 @@ class WebServiceResult
|
||||
public function AddResultObject($sLabel, $oObject)
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
$this->m_aResult[$sLabel] = array(
|
||||
$this->m_aResult[$sLabel] = [
|
||||
'id' => $oObject->GetKey(),
|
||||
'name' => $oObject->GetRawName(),
|
||||
'url' => $oAppContext->MakeObjectUrl(get_class($oObject), $oObject->GetKey(), null, false), // Raw URL without HTML tags
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,8 +176,11 @@ class WebServiceResult
|
||||
*/
|
||||
public function LogIssue($sDescription, $bIsStopper = true)
|
||||
{
|
||||
if ($bIsStopper) $this->LogError($sDescription);
|
||||
else $this->LogWarning($sDescription);
|
||||
if ($bIsStopper) {
|
||||
$this->LogError($sDescription);
|
||||
} else {
|
||||
$this->LogWarning($sDescription);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,8 +216,7 @@ class WebServiceResult
|
||||
public function GetReturnedDataAsText()
|
||||
{
|
||||
$sRet = '';
|
||||
foreach ($this->m_aResult as $sKey => $value)
|
||||
{
|
||||
foreach ($this->m_aResult as $sKey => $value) {
|
||||
$sRet .= "===== $sKey =====\n";
|
||||
$sRet .= print_r($value, true);
|
||||
}
|
||||
@@ -229,7 +224,6 @@ class WebServiceResult
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generic response of iTop SOAP services - failed login
|
||||
*
|
||||
@@ -251,13 +245,12 @@ class WebServiceResultFailedLogin extends WebServiceResult
|
||||
*/
|
||||
abstract class WebServicesBase
|
||||
{
|
||||
static public function GetWSDLContents($sServiceCategory = '')
|
||||
public static function GetWSDLContents($sServiceCategory = '')
|
||||
{
|
||||
if ($sServiceCategory == '')
|
||||
{
|
||||
if ($sServiceCategory == '') {
|
||||
$sServiceCategory = 'BasicServices';
|
||||
}
|
||||
$sWsdlFilePath = call_user_func(array($sServiceCategory, 'GetWSDLFilePath'));
|
||||
$sWsdlFilePath = call_user_func([$sServiceCategory, 'GetWSDLFilePath']);
|
||||
return file_get_contents($sWsdlFilePath);
|
||||
}
|
||||
|
||||
@@ -271,15 +264,14 @@ abstract class WebServicesBase
|
||||
*/
|
||||
protected function LogUsage($sVerb, $oRes)
|
||||
{
|
||||
if (!MetaModel::IsLogEnabledWebService()) return;
|
||||
if (!MetaModel::IsLogEnabledWebService()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$oLog = new EventWebService();
|
||||
if ($oRes->IsOk())
|
||||
{
|
||||
if ($oRes->IsOk()) {
|
||||
$oLog->Set('message', $sVerb.' was successfully invoked');
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oLog->Set('message', $sVerb.' returned errors');
|
||||
}
|
||||
$oLog->Set('userinfo', UserRights::GetUser());
|
||||
@@ -291,12 +283,11 @@ abstract class WebServicesBase
|
||||
$this->TrimAndSetValue($oLog, 'data', (string)$oRes->GetReturnedDataAsText());
|
||||
$oLog->DBInsertNoReload();
|
||||
}
|
||||
|
||||
|
||||
protected function TrimAndSetValue($oLog, $sAttCode, $sValue)
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($oLog), $sAttCode);
|
||||
if (is_object($oAttDef))
|
||||
{
|
||||
if (is_object($oAttDef)) {
|
||||
$iMaxSize = $oAttDef->GetMaxSize();
|
||||
if ($iMaxSize && (mb_strlen($sValue) > $iMaxSize)) {
|
||||
$sValue = mb_substr($sValue, 0, $iMaxSize);
|
||||
@@ -317,12 +308,9 @@ abstract class WebServicesBase
|
||||
protected function MyObjectSetScalar($sAttCode, $sParamName, $value, &$oTargetObj, &$oRes)
|
||||
{
|
||||
$res = $oTargetObj->CheckValue($sAttCode, $value);
|
||||
if ($res === true)
|
||||
{
|
||||
if ($res === true) {
|
||||
$oTargetObj->Set($sAttCode, $value);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// $res contains the error description
|
||||
$oRes->LogError("Unexpected value for parameter $sParamName: $res");
|
||||
}
|
||||
@@ -343,31 +331,24 @@ abstract class WebServicesBase
|
||||
|
||||
$bIsMandatory = !$oExtKey->IsNullAllowed();
|
||||
|
||||
if (is_null($aExtKeyDesc))
|
||||
{
|
||||
if ($bIsMandatory)
|
||||
{
|
||||
if (is_null($aExtKeyDesc)) {
|
||||
if ($bIsMandatory) {
|
||||
$oRes->LogError("Parameter $sParamName: found null for a mandatory key");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// skip silently
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($aExtKeyDesc) == 0)
|
||||
{
|
||||
if (count($aExtKeyDesc) == 0) {
|
||||
$oRes->LogIssue("Parameter $sParamName: no search condition has been specified", $bIsMandatory);
|
||||
return;
|
||||
}
|
||||
|
||||
$sKeyClass = $oExtKey->GetTargetClass();
|
||||
$oReconFilter = new DBObjectSearch($sKeyClass);
|
||||
foreach ($aExtKeyDesc as $sForeignAttCode => $value)
|
||||
{
|
||||
if (!MetaModel::IsValidFilterCode($sKeyClass, $sForeignAttCode))
|
||||
{
|
||||
foreach ($aExtKeyDesc as $sForeignAttCode => $value) {
|
||||
if (!MetaModel::IsValidFilterCode($sKeyClass, $sForeignAttCode)) {
|
||||
$aCodes = MetaModel::GetFiltersList($sKeyClass);
|
||||
$sMsg = "Parameter $sParamName: '$sForeignAttCode' is not a valid filter code for class '$sKeyClass', expecting a value in {".implode(', ', $aCodes)."}";
|
||||
$oRes->LogIssue($sMsg, $bIsMandatory);
|
||||
@@ -376,26 +357,24 @@ abstract class WebServicesBase
|
||||
$oReconFilter->AddCondition($sForeignAttCode, $value, '=');
|
||||
}
|
||||
$oExtObjects = new CMDBObjectSet($oReconFilter);
|
||||
switch($oExtObjects->Count())
|
||||
{
|
||||
case 0:
|
||||
$sMsg = "Parameter $sParamName: no match (searched: '".$oReconFilter->ToOQL(true)."')";
|
||||
$oRes->LogIssue($sMsg, $bIsMandatory);
|
||||
break;
|
||||
case 1:
|
||||
// Do change the external key attribute
|
||||
$oForeignObj = $oExtObjects->Fetch();
|
||||
$oTargetObj->Set($sAttCode, $oForeignObj->GetKey());
|
||||
switch ($oExtObjects->Count()) {
|
||||
case 0:
|
||||
$sMsg = "Parameter $sParamName: no match (searched: '".$oReconFilter->ToOQL(true)."')";
|
||||
$oRes->LogIssue($sMsg, $bIsMandatory);
|
||||
break;
|
||||
case 1:
|
||||
// Do change the external key attribute
|
||||
$oForeignObj = $oExtObjects->Fetch();
|
||||
$oTargetObj->Set($sAttCode, $oForeignObj->GetKey());
|
||||
|
||||
// Report it (no need to report if the object already had this value
|
||||
if (array_key_exists($sAttCode, $oTargetObj->ListChanges()))
|
||||
{
|
||||
$oRes->LogInfo("Parameter $sParamName: found match ".get_class($oForeignObj)."::".$oForeignObj->GetKey()." '".$oForeignObj->GetName()."'");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$sMsg = "Parameter $sParamName: Found ".$oExtObjects->Count()." matches (searched: '".$oReconFilter->ToOQL(true)."')";
|
||||
$oRes->LogIssue($sMsg, $bIsMandatory);
|
||||
// Report it (no need to report if the object already had this value
|
||||
if (array_key_exists($sAttCode, $oTargetObj->ListChanges())) {
|
||||
$oRes->LogInfo("Parameter $sParamName: found match ".get_class($oForeignObj)."::".$oForeignObj->GetKey()." '".$oForeignObj->GetName()."'");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$sMsg = "Parameter $sParamName: Found ".$oExtObjects->Count()." matches (searched: '".$oReconFilter->ToOQL(true)."')";
|
||||
$oRes->LogIssue($sMsg, $bIsMandatory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,34 +395,29 @@ abstract class WebServicesBase
|
||||
$sLinkClass = $oLinkAtt->GetLinkedClass();
|
||||
$sExtKeyToItem = $oLinkAtt->GetExtKeyToRemote();
|
||||
|
||||
$aItemsFound = array();
|
||||
$aItemsNotFound = array();
|
||||
|
||||
if (is_null($aLinkList))
|
||||
{
|
||||
$aItemsFound = [];
|
||||
$aItemsNotFound = [];
|
||||
|
||||
if (is_null($aLinkList)) {
|
||||
return $aItemsNotFound;
|
||||
}
|
||||
|
||||
foreach ($aLinkList as $aItemData)
|
||||
{
|
||||
if (!array_key_exists('class', $aItemData))
|
||||
{
|
||||
foreach ($aLinkList as $aItemData) {
|
||||
if (!array_key_exists('class', $aItemData)) {
|
||||
$oRes->LogWarning("Parameter $sParamName: missing 'class' specification");
|
||||
continue; // skip
|
||||
}
|
||||
$sTargetClass = $aItemData['class'];
|
||||
if (!MetaModel::IsValidClass($sTargetClass))
|
||||
{
|
||||
if (!MetaModel::IsValidClass($sTargetClass)) {
|
||||
$oRes->LogError("Parameter $sParamName: invalid class '$sTargetClass'");
|
||||
continue; // skip
|
||||
}
|
||||
if (!MetaModel::IsParentClass($sLinkedClass, $sTargetClass))
|
||||
{
|
||||
if (!MetaModel::IsParentClass($sLinkedClass, $sTargetClass)) {
|
||||
$oRes->LogError("Parameter $sParamName: '$sTargetClass' is not a child class of '$sLinkedClass'");
|
||||
continue; // skip
|
||||
}
|
||||
$oReconFilter = new DBObjectSearch($sTargetClass);
|
||||
$aCIStringDesc = array();
|
||||
$aCIStringDesc = [];
|
||||
foreach ($aItemData['search'] as $sAttCode => $value) {
|
||||
if (!MetaModel::IsValidFilterCode($sTargetClass, $sAttCode)) {
|
||||
$aCodes = MetaModel::GetFiltersList($sTargetClass);
|
||||
@@ -455,52 +429,42 @@ abstract class WebServicesBase
|
||||
// The attribute is one of our reconciliation key
|
||||
$oReconFilter->AddCondition($sAttCode, $value, '=');
|
||||
}
|
||||
if (count($aCIStringDesc) == 1)
|
||||
{
|
||||
if (count($aCIStringDesc) == 1) {
|
||||
// take the last and unique value to describe the object
|
||||
$sItemDesc = $value;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// describe the object by the given keys
|
||||
$sItemDesc = $sTargetClass.'('.implode('/', $aCIStringDesc).')';
|
||||
}
|
||||
|
||||
$oExtObjects = new CMDBObjectSet($oReconFilter);
|
||||
switch($oExtObjects->Count())
|
||||
{
|
||||
case 0:
|
||||
$oRes->LogWarning("Parameter $sParamName: object to link $sLinkedClass / $sItemDesc could not be found (searched: '".$oReconFilter->ToOQL(true)."')");
|
||||
$aItemsNotFound[] = $sItemDesc;
|
||||
break;
|
||||
case 1:
|
||||
$aItemsFound[] = array (
|
||||
'object' => $oExtObjects->Fetch(),
|
||||
'link_values' => @$aItemData['link_values'],
|
||||
'desc' => $sItemDesc,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
$oRes->LogWarning("Parameter $sParamName: Found ".$oExtObjects->Count()." matches for item '$sItemDesc' (searched: '".$oReconFilter->ToOQL(true)."')");
|
||||
$aItemsNotFound[] = $sItemDesc;
|
||||
switch ($oExtObjects->Count()) {
|
||||
case 0:
|
||||
$oRes->LogWarning("Parameter $sParamName: object to link $sLinkedClass / $sItemDesc could not be found (searched: '".$oReconFilter->ToOQL(true)."')");
|
||||
$aItemsNotFound[] = $sItemDesc;
|
||||
break;
|
||||
case 1:
|
||||
$aItemsFound[] = [
|
||||
'object' => $oExtObjects->Fetch(),
|
||||
'link_values' => @$aItemData['link_values'],
|
||||
'desc' => $sItemDesc,
|
||||
];
|
||||
break;
|
||||
default:
|
||||
$oRes->LogWarning("Parameter $sParamName: Found ".$oExtObjects->Count()." matches for item '$sItemDesc' (searched: '".$oReconFilter->ToOQL(true)."')");
|
||||
$aItemsNotFound[] = $sItemDesc;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($aItemsFound) > 0)
|
||||
{
|
||||
$aLinks = array();
|
||||
foreach($aItemsFound as $aItemData)
|
||||
{
|
||||
if (count($aItemsFound) > 0) {
|
||||
$aLinks = [];
|
||||
foreach ($aItemsFound as $aItemData) {
|
||||
$oLink = MetaModel::NewObject($sLinkClass);
|
||||
$oLink->Set($sExtKeyToItem, $aItemData['object']->GetKey());
|
||||
foreach($aItemData['link_values'] as $sKey => $value)
|
||||
{
|
||||
if(!MetaModel::IsValidAttCode($sLinkClass, $sKey))
|
||||
{
|
||||
foreach ($aItemData['link_values'] as $sKey => $value) {
|
||||
if (!MetaModel::IsValidAttCode($sLinkClass, $sKey)) {
|
||||
$oRes->LogWarning("Parameter $sParamName: Attaching item '".$aItemData['desc']."', the attribute code '$sKey' is not valid ; check the class '$sLinkClass'");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oLink->Set($sKey, $value);
|
||||
}
|
||||
}
|
||||
@@ -529,77 +493,71 @@ abstract class WebServicesBase
|
||||
*/
|
||||
protected function MyObjectInsert($oTargetObj, $sResultLabel, &$oRes)
|
||||
{
|
||||
if ($oRes->IsOk())
|
||||
{
|
||||
if ($oRes->IsOk()) {
|
||||
list($bRes, $aIssues) = $oTargetObj->CheckToWrite();
|
||||
if ($bRes)
|
||||
{
|
||||
if ($bRes) {
|
||||
$iId = $oTargetObj->DBInsertNoReload();
|
||||
$oRes->LogInfo("Created object ".get_class($oTargetObj)."::$iId");
|
||||
$oRes->AddResultObject($sResultLabel, $oTargetObj);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oRes->LogError("The ticket could not be created due to forbidden values (or inconsistent values)");
|
||||
foreach($aIssues as $iIssue => $sIssue)
|
||||
{
|
||||
foreach ($aIssues as $iIssue => $sIssue) {
|
||||
$oRes->LogError("Issue #$iIssue: $sIssue");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static protected function SoapStructToExternalKeySearch($oExternalKeySearch)
|
||||
protected static function SoapStructToExternalKeySearch($oExternalKeySearch)
|
||||
{
|
||||
if (is_null($oExternalKeySearch)) return null;
|
||||
if ($oExternalKeySearch->IsVoid()) return null;
|
||||
if (is_null($oExternalKeySearch)) {
|
||||
return null;
|
||||
}
|
||||
if ($oExternalKeySearch->IsVoid()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$aRes = array();
|
||||
foreach($oExternalKeySearch->conditions as $oSearchCondition)
|
||||
{
|
||||
$aRes = [];
|
||||
foreach ($oExternalKeySearch->conditions as $oSearchCondition) {
|
||||
$aRes[$oSearchCondition->attcode] = $oSearchCondition->value;
|
||||
}
|
||||
return $aRes;
|
||||
}
|
||||
|
||||
static protected function SoapStructToLinkCreationSpec(SoapLinkCreationSpec $oLinkCreationSpec)
|
||||
protected static function SoapStructToLinkCreationSpec(SoapLinkCreationSpec $oLinkCreationSpec)
|
||||
{
|
||||
$aRes = array
|
||||
(
|
||||
$aRes =
|
||||
[
|
||||
'class' => $oLinkCreationSpec->class,
|
||||
'search' => array(),
|
||||
'link_values' => array(),
|
||||
);
|
||||
'search' => [],
|
||||
'link_values' => [],
|
||||
];
|
||||
|
||||
foreach($oLinkCreationSpec->conditions as $oSearchCondition)
|
||||
{
|
||||
foreach ($oLinkCreationSpec->conditions as $oSearchCondition) {
|
||||
$aRes['search'][$oSearchCondition->attcode] = $oSearchCondition->value;
|
||||
}
|
||||
|
||||
foreach($oLinkCreationSpec->attributes as $oAttributeValue)
|
||||
{
|
||||
foreach ($oLinkCreationSpec->attributes as $oAttributeValue) {
|
||||
$aRes['link_values'][$oAttributeValue->attcode] = $oAttributeValue->value;
|
||||
}
|
||||
|
||||
return $aRes;
|
||||
}
|
||||
|
||||
static protected function SoapStructToAssociativeArray($aArrayOfAssocArray)
|
||||
protected static function SoapStructToAssociativeArray($aArrayOfAssocArray)
|
||||
{
|
||||
if (is_null($aArrayOfAssocArray)) return array();
|
||||
if (is_null($aArrayOfAssocArray)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$aRes = array();
|
||||
foreach($aArrayOfAssocArray as $aAssocArray)
|
||||
{
|
||||
$aRow = array();
|
||||
foreach ($aAssocArray as $oKeyValuePair)
|
||||
{
|
||||
$aRes = [];
|
||||
foreach ($aArrayOfAssocArray as $aAssocArray) {
|
||||
$aRow = [];
|
||||
foreach ($aAssocArray as $oKeyValuePair) {
|
||||
$aRow[$oKeyValuePair->key] = $oKeyValuePair->value;
|
||||
}
|
||||
$aRes[] = $aRow;
|
||||
$aRes[] = $aRow;
|
||||
}
|
||||
return $aRes;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
Reference in New Issue
Block a user