Fix files using CrLf, convert them to Lf to have the whole repo using Lf

Warn your git config (core.autocrlf = input or true)
This commit is contained in:
Pierre Goiffon
2018-09-04 17:38:22 +02:00
parent cad18bee73
commit 40a4e6d7b0
378 changed files with 152833 additions and 152833 deletions

View File

@@ -1,208 +1,208 @@
<?php
// Copyright (C) 2010-2018 Combodo SARL
//
// This file is part of iTop.
//
// 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.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Does load data from XML files (currently used in the setup only)
*
* @copyright Copyright (C) 2010-2018 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**
* This page is called to perform "asynchronously" the setup actions
* parameters
* 'operation': one of 'compile_data_model', 'update_db_schema', 'after_db_creation', 'file'
*
* if 'operation' == 'update_db_schema':
* 'mode': install | upgrade
*
* if 'operation' == 'after_db_creation':
* 'mode': install | upgrade
*
* if 'operation' == 'file':
* 'file': string Name of the file to load
* 'session_status': string 'start', 'continue' or 'end'
* 'percent': integer 0..100 the percentage of completion once the file has been loaded
*/
define('SAFE_MINIMUM_MEMORY', 64*1024*1024);
require_once('../approot.inc.php');
require_once(APPROOT.'/application/utils.inc.php');
require_once(APPROOT.'/setup/setuppage.class.inc.php');
require_once(APPROOT.'/setup/moduleinstaller.class.inc.php');
ini_set('max_execution_time', max(3600, ini_get('max_execution_time'))); // Under Windows SQL/backup operations are part of the timeout and require extra time
date_default_timezone_set('Europe/Paris'); // Just to avoid a warning if the timezone is not set in php.ini
$sMemoryLimit = trim(ini_get('memory_limit'));
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
SetupPage::log_info("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 ($iMemoryLimit < SAFE_MINIMUM_MEMORY)
{
if (ini_set('memory_limit', SAFE_MINIMUM_MEMORY) === FALSE)
{
SetupPage::log_error("memory_limit is too small: $iMemoryLimit and can not be increased by the script itself.");
}
else
{
SetupPage::log_info("memory_limit increased from $iMemoryLimit to ".SAFE_MINIMUM_MEMORY.".");
}
}
}
define('PHP_FATAL_ERROR_TAG', 'phpfatalerror');
/**
* Handler for register_shutdown_function, to catch PHP errors
*/
function ShutdownCallback()
{
$error = error_get_last();
$bIsErrorToReport = (($error !== null) && ($error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR)));
if (!$bIsErrorToReport)
{
return;
}
$errno = $error["type"];
$errfile = $error["file"];
$errline = $error["line"];
$errstr = $error["message"];
$sLogMessage = "PHP error occured : msg=$errstr, no=$errno, file=$errfile, line=$errline";
SetupPage::log_error("Setup error: $sLogMessage");
echo '<'.PHP_FATAL_ERROR_TAG.'>'.$sLogMessage.'</'.PHP_FATAL_ERROR_TAG.'>';
}
function FatalErrorCatcher($sOutput)
{
if (preg_match('|<'.PHP_FATAL_ERROR_TAG.'>.*</'.PHP_FATAL_ERROR_TAG.'>|s', $sOutput, $aMatches))
{
header("HTTP/1.0 500 Internal server error.");
$errors = '';
foreach ($aMatches as $sMatch)
{
$errors .= strip_tags($sMatch)."\n";
}
$sOutput = "$errors\n";
// Logging to a file does not work if the whole memory is exhausted...
//SetupPage::log_error("Fatal error - in $__FILE__ , $errors");
}
return $sOutput;
}
//Define some bogus, invalid HTML tags that no sane
//person would ever put in an actual document and tell
//PHP to delimit fatal error warnings with them.
ini_set('error_prepend_string', '<'.PHP_FATAL_ERROR_TAG.'>');
ini_set('error_append_string', '</'.PHP_FATAL_ERROR_TAG.'>');
// callback on errors to log
register_shutdown_function('ShutdownCallback');
// Starts the capture of the ouput, and sets a filter to capture the fatal errors.
ob_start('FatalErrorCatcher'); // Start capturing the output, and pass it through the fatal error catcher
require_once(APPROOT.'/core/config.class.inc.php');
require_once(APPROOT.'/core/log.class.inc.php');
require_once(APPROOT.'/core/kpi.class.inc.php');
require_once(APPROOT.'/core/cmdbsource.class.inc.php');
require_once('./xmldataloader.class.inc.php');
require_once(APPROOT.'/application/ajaxwebpage.class.inc.php');
// Never cache this page
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Fri, 17 Jul 1970 05:00:00 GMT"); // Date in the past
/**
* Main program
*/
$sOperation = Utils::ReadParam('operation', '');
try
{
switch($sOperation)
{
case 'async_action':
ini_set('max_execution_time', max(240, ini_get('max_execution_time')));
// While running the setup it is desirable to see any error that may happen
ini_set('display_errors', true);
ini_set('display_startup_errors', true);
require_once(APPROOT.'/setup/wizardcontroller.class.inc.php');
require_once(APPROOT.'/setup/wizardsteps.class.inc.php');
$sClass = utils::ReadParam('step_class', '');
$sState = utils::ReadParam('step_state', '');
$sActionCode = utils::ReadParam('code', '');
$aParams = utils::ReadParam('params', array(), false, 'raw_data');
$oPage = new ajax_page('');
$oDummyController = new WizardController('');
if (is_subclass_of($sClass, 'WizardStep'))
{
/** @var WizardStep $oStep */
$oStep = new $sClass($oDummyController, $sState);
$sConfigFile = utils::GetConfigFilePath();
if (file_exists($sConfigFile) && !is_writable($sConfigFile) && $oStep->RequiresWritableConfig())
{
$oPage->error("<b>Error:</b> the configuration file '".$sConfigFile."' already exists and cannot be overwritten.");
$oPage->p("The wizard cannot modify the configuration file for you. If you want to upgrade ".ITOP_APPLICATION.", make sure that the file '<b>".realpath($sConfigFile)."</b>' can be modified by the web server.");
$oPage->output();
}
else
{
$oStep->AsyncAction($oPage, $sActionCode, $aParams);
}
}
$oPage->output();
break;
default:
throw(new Exception("Error unsupported operation '$sOperation'"));
}
}
catch(Exception $e)
{
header("HTTP/1.0 500 Internal server error.");
echo "<p>An error happened while processing the installation:</p>\n";
echo '<p>'.$e."</p>\n";
SetupPage::log_error("An error happened while processing the installation: ".$e);
}
if (function_exists('memory_get_peak_usage'))
{
if ($sOperation == 'file')
{
SetupPage::log_info("loading file '$sFileName', peak memory usage. ".memory_get_peak_usage());
}
else
{
SetupPage::log_info("operation '$sOperation', peak memory usage. ".memory_get_peak_usage());
}
}
<?php
// Copyright (C) 2010-2018 Combodo SARL
//
// This file is part of iTop.
//
// 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.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Does load data from XML files (currently used in the setup only)
*
* @copyright Copyright (C) 2010-2018 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**
* This page is called to perform "asynchronously" the setup actions
* parameters
* 'operation': one of 'compile_data_model', 'update_db_schema', 'after_db_creation', 'file'
*
* if 'operation' == 'update_db_schema':
* 'mode': install | upgrade
*
* if 'operation' == 'after_db_creation':
* 'mode': install | upgrade
*
* if 'operation' == 'file':
* 'file': string Name of the file to load
* 'session_status': string 'start', 'continue' or 'end'
* 'percent': integer 0..100 the percentage of completion once the file has been loaded
*/
define('SAFE_MINIMUM_MEMORY', 64*1024*1024);
require_once('../approot.inc.php');
require_once(APPROOT.'/application/utils.inc.php');
require_once(APPROOT.'/setup/setuppage.class.inc.php');
require_once(APPROOT.'/setup/moduleinstaller.class.inc.php');
ini_set('max_execution_time', max(3600, ini_get('max_execution_time'))); // Under Windows SQL/backup operations are part of the timeout and require extra time
date_default_timezone_set('Europe/Paris'); // Just to avoid a warning if the timezone is not set in php.ini
$sMemoryLimit = trim(ini_get('memory_limit'));
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
SetupPage::log_info("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 ($iMemoryLimit < SAFE_MINIMUM_MEMORY)
{
if (ini_set('memory_limit', SAFE_MINIMUM_MEMORY) === FALSE)
{
SetupPage::log_error("memory_limit is too small: $iMemoryLimit and can not be increased by the script itself.");
}
else
{
SetupPage::log_info("memory_limit increased from $iMemoryLimit to ".SAFE_MINIMUM_MEMORY.".");
}
}
}
define('PHP_FATAL_ERROR_TAG', 'phpfatalerror');
/**
* Handler for register_shutdown_function, to catch PHP errors
*/
function ShutdownCallback()
{
$error = error_get_last();
$bIsErrorToReport = (($error !== null) && ($error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR)));
if (!$bIsErrorToReport)
{
return;
}
$errno = $error["type"];
$errfile = $error["file"];
$errline = $error["line"];
$errstr = $error["message"];
$sLogMessage = "PHP error occured : msg=$errstr, no=$errno, file=$errfile, line=$errline";
SetupPage::log_error("Setup error: $sLogMessage");
echo '<'.PHP_FATAL_ERROR_TAG.'>'.$sLogMessage.'</'.PHP_FATAL_ERROR_TAG.'>';
}
function FatalErrorCatcher($sOutput)
{
if (preg_match('|<'.PHP_FATAL_ERROR_TAG.'>.*</'.PHP_FATAL_ERROR_TAG.'>|s', $sOutput, $aMatches))
{
header("HTTP/1.0 500 Internal server error.");
$errors = '';
foreach ($aMatches as $sMatch)
{
$errors .= strip_tags($sMatch)."\n";
}
$sOutput = "$errors\n";
// Logging to a file does not work if the whole memory is exhausted...
//SetupPage::log_error("Fatal error - in $__FILE__ , $errors");
}
return $sOutput;
}
//Define some bogus, invalid HTML tags that no sane
//person would ever put in an actual document and tell
//PHP to delimit fatal error warnings with them.
ini_set('error_prepend_string', '<'.PHP_FATAL_ERROR_TAG.'>');
ini_set('error_append_string', '</'.PHP_FATAL_ERROR_TAG.'>');
// callback on errors to log
register_shutdown_function('ShutdownCallback');
// Starts the capture of the ouput, and sets a filter to capture the fatal errors.
ob_start('FatalErrorCatcher'); // Start capturing the output, and pass it through the fatal error catcher
require_once(APPROOT.'/core/config.class.inc.php');
require_once(APPROOT.'/core/log.class.inc.php');
require_once(APPROOT.'/core/kpi.class.inc.php');
require_once(APPROOT.'/core/cmdbsource.class.inc.php');
require_once('./xmldataloader.class.inc.php');
require_once(APPROOT.'/application/ajaxwebpage.class.inc.php');
// Never cache this page
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Fri, 17 Jul 1970 05:00:00 GMT"); // Date in the past
/**
* Main program
*/
$sOperation = Utils::ReadParam('operation', '');
try
{
switch($sOperation)
{
case 'async_action':
ini_set('max_execution_time', max(240, ini_get('max_execution_time')));
// While running the setup it is desirable to see any error that may happen
ini_set('display_errors', true);
ini_set('display_startup_errors', true);
require_once(APPROOT.'/setup/wizardcontroller.class.inc.php');
require_once(APPROOT.'/setup/wizardsteps.class.inc.php');
$sClass = utils::ReadParam('step_class', '');
$sState = utils::ReadParam('step_state', '');
$sActionCode = utils::ReadParam('code', '');
$aParams = utils::ReadParam('params', array(), false, 'raw_data');
$oPage = new ajax_page('');
$oDummyController = new WizardController('');
if (is_subclass_of($sClass, 'WizardStep'))
{
/** @var WizardStep $oStep */
$oStep = new $sClass($oDummyController, $sState);
$sConfigFile = utils::GetConfigFilePath();
if (file_exists($sConfigFile) && !is_writable($sConfigFile) && $oStep->RequiresWritableConfig())
{
$oPage->error("<b>Error:</b> the configuration file '".$sConfigFile."' already exists and cannot be overwritten.");
$oPage->p("The wizard cannot modify the configuration file for you. If you want to upgrade ".ITOP_APPLICATION.", make sure that the file '<b>".realpath($sConfigFile)."</b>' can be modified by the web server.");
$oPage->output();
}
else
{
$oStep->AsyncAction($oPage, $sActionCode, $aParams);
}
}
$oPage->output();
break;
default:
throw(new Exception("Error unsupported operation '$sOperation'"));
}
}
catch(Exception $e)
{
header("HTTP/1.0 500 Internal server error.");
echo "<p>An error happened while processing the installation:</p>\n";
echo '<p>'.$e."</p>\n";
SetupPage::log_error("An error happened while processing the installation: ".$e);
}
if (function_exists('memory_get_peak_usage'))
{
if ($sOperation == 'file')
{
SetupPage::log_info("loading file '$sFileName', peak memory usage. ".memory_get_peak_usage());
}
else
{
SetupPage::log_info("operation '$sOperation', peak memory usage. ".memory_get_peak_usage());
}
}

View File

@@ -1,285 +1,285 @@
<?php
// Copyright (C) 2010-2012 Combodo SARL
//
// This file is part of iTop.
//
// 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.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Emailing: helper for the admins to troubleshoot email issues
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**
* Wizard to configure and initialize the iTop application
*/
require_once('../approot.inc.php');
require_once(APPROOT.'/application/utils.inc.php');
require_once(APPROOT.'/core/email.class.inc.php');
require_once('./setuppage.class.inc.php');
require_once(APPROOT.'/application/startup.inc.php');
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be admin)
$sOperation = Utils::ReadParam('operation', 'step1');
$oP = new SetupPage('iTop email test utility');
/**
* Helper to check server setting required to send an email
*/
function CheckEmailSetting($oP)
{
$bRet = true;
if (function_exists('php_ini_loaded_file')) // PHP >= 5.2.4
{
$sPhpIniFile = php_ini_loaded_file();
}
else
{
$sPhpIniFile = 'php.ini';
}
$sTransport = MetaModel::GetConfig()->Get('email_transport');
switch($sTransport)
{
case 'PHPMail':
$oP->info("iTop is configured to use PHP's <a style=\"background:transparent;padding:0;color:#000;text-decoration:underline;\" href=\"http://www.php.net/manual/en/function.mail.php\" target=\"_blank\">mail</a> function to send emails.");
$bIsWindows = (array_key_exists('WINDIR', $_SERVER) || array_key_exists('windir', $_SERVER));
if ($bIsWindows)
{
$sSmtpServer = ini_get('SMTP');
if (empty($sSmtpServer))
{
$oP->error("The SMTP server is not defined. Please add the 'SMTP' directive into $sPhpIniFile");
$bRet = false;
}
else if (strcasecmp($sSmtpServer, 'localhost') == 0)
{
$oP->warning("Your SMTP server is configured to 'localhost'. You might want to set or change the 'SMTP' directive into $sPhpIniFile");
}
else
{
$oP->info("Your SMTP server: <strong>$sSmtpServer</strong>. To change this value, modify the 'SMTP' directive into $sPhpIniFile");
}
$iSmtpPort = (int) ini_get('smtp_port');
if (empty($iSmtpPort))
{
$oP->info("The SMTP port is not defined. Please add the 'smtp_port' directive into $sPhpIniFile");
$bRet = false;
}
else if ($iSmtpPort == 25)
{
$oP->info("Your SMTP port is configured to the default value: 25. You might want to set or change the 'smtp_port' directive into $sPhpIniFile");
}
else
{
$oP->info("Your SMTP port is configured to $iSmtpPort. You might want to set or change the 'smtp_port' directive into $sPhpIniFile");
}
}
else
{
// Not a windows system
$sSendMail = ini_get('sendmail_path');
if (empty($sSendMail))
{
$oP->error("The command to send mail is not defined. Please add the 'sendmail_path' directive into $sPhpIniFile. A recommended setting is <em>sendmail_path=sendmail -t -i</em>");
$bRet = false;
}
else
{
$oP->info("The command to send mail is: <strong>$sSendMail</strong>. To change this value, modify the 'sendmail_path' directive into $sPhpIniFile");
}
}
break;
case 'SMTP':
$oP->info("iTop is configured to use the <b>SMTP</b> transport.");
$sHost = MetaModel::GetConfig()->Get('email_transport_smtp.host');
$sPort = MetaModel::GetConfig()->Get('email_transport_smtp.port');
$sEncryption = MetaModel::GetConfig()->Get('email_transport_smtp.encryption');
$sDisplayEncryption = empty($sEncryption) ? '<em>no encryption</em> ' : $sEncryption;
$sUserName = MetaModel::GetConfig()->Get('email_transport_smtp.username');
$sDisplayUserName = empty($sUserName) ? '<em>no user</em> ' : $sUserName;
$sPassword = MetaModel::GetConfig()->Get('email_transport_smtp.password');
$sDisplayPassword = empty($sPassword) ? '<em>no password</em> ' : str_repeat('*', strlen($sPassword));
$oP->info("SMTP configuration (from config-itop.php): host: $sHost, port: $sPort, user: $sDisplayUserName, password: $sDisplayPassword, encryption: $sDisplayEncryption.");
if (($sHost == 'localhost') && ($sPort == '25') && ($sUserName == '') && ($sPassword == '') )
{
$oP->warning("The default settings may not be suitable for your environment. You may want to ajust these values by editing iTop's configuration file (".APPROOT."conf/production/config-itop.php).");
}
break;
case 'Null':
$oP->warning("iTop is configured to use the <b>Null</b> transport: emails sending will have no effect.");
$bRet = false;
break;
case 'LogFile':
$oP->warning("iTop is configured to use the <b>LogFile</b> transport: emails will <em>not</em> be sent but logged to the file: '".APPROOT."/log/mail.log'.");
$bRet = true;
break;
default:
$oP->error("Unknown transport '$sTransport' configured.");
$bRet = false;
}
if ($bRet)
{
$oP->ok("PHP settings are ok to proceed with a test of the email");
}
$bConfigAsync = MetaModel::GetConfig()->Get('email_asynchronous');
if ($bConfigAsync)
{
$oP->warning("iTop is configured to send emails <em>asynchronously</em>. Make sure that cron.php is scheduled to run in the background, otherwise regular emails will <em>not</em> be sent. For the purpose of this test, the email will be sent <em>synchronously</em>.");
}
return $bRet;
}
/**
* Display the form for the first step of the test wizard
* which consists in a basic check of the configuration and display of a form for testing
*/
function DisplayStep1(SetupPage $oP)
{
$sNextOperation = 'step2';
$oP->add("<h1>iTop email test</h1>\n");
$oP->add("<h2>Checking prerequisites</h2>\n");
if (CheckEmailSetting($oP))
{
$sRedStar = '<span class="hilite">*</span>';
$oP->add("<h2>Try to send an email</h2>\n");
$oP->add("<form method=\"post\" onSubmit=\"return DoSubmit('Sending an email...', 10)\">\n");
// Form goes here
$oP->add("<fieldset><legend>Test recipient</legend>\n");
$aForm = array();
$aForm[] = array(
'label' => "To$sRedStar:",
'input' => "<input id=\"to\" type=\"text\" name=\"to\" value=\"\">",
'help' => ' email address (e.g. john.foo@worldcompany.com)',
);
$aForm[] = array(
'label' => "From:",
'input' => "<input id=\"from\" type=\"text\" name=\"from\" value=\"\">",
'help' => ' defaults to the configuration param "email_default_sender_address" or "To" field.',
);
$oP->form($aForm);
$oP->add("</fieldset>\n");
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"$sNextOperation\">\n");
$oP->add("<div>\n");
$oP->add("<button style=\"float:left\" type=\"button\" onclick=\"window.location.reload()\">Refresh</button>\n");
$oP->add("<button style=\"float:right\" type=\"submit\">Next >></button>\n");
$oP->add("<div style=\"clear:both;\"></div>\n");
$oP->add("</div>\n");
$oP->add("</form>\n");
}
}
/**
* Display the form for the second step of the configuration wizard
* which consists in sending an email, which maybe a problem under Windows
*/
function DisplayStep2(SetupPage $oP, $sFrom, $sTo)
{
//$sNextOperation = 'step3';
$oP->add("<h1>iTop configuration wizard</h1>\n");
$oP->add("<h2>Step 2: send an email</h2>\n");
$oP->add("<p>Sending an email to '".htmlentities($sTo, ENT_QUOTES, 'utf-8')."'... (From: '".htmlentities($sFrom, ENT_QUOTES, 'utf-8')."')</p>\n");
$oP->add("<form method=\"post\">\n");
$oEmail = new Email();
$oEmail->SetRecipientTO($sTo);
$oEmail->SetRecipientFrom($sFrom);
$oEmail->SetSubject("Test iTop");
$oEmail->SetBody("<p>Hello,</p><p>The email function is now working fine.</p><p>You may now be able to use the notification function.</p><p>iTop</p>");
$iRes = $oEmail->Send($aIssues, true /* force synchronous exec */);
switch ($iRes)
{
case EMAIL_SEND_OK:
$sTransport = MetaModel::GetConfig()->Get('email_transport');
if ($sTransport == 'LogFile')
{
$oP->ok("The email has been logged into the file ".APPROOT."/log/mail.log.");
}
else
{
$oP->ok("The email has been sent, check your inbox for the incoming mail...");
}
$oP->add("<button onClick=\"window.history.back();\"><< Back</button>\n");
break;
case EMAIL_SEND_PENDING:
$oP->ok("Email queued");
$oP->add("<button onClick=\"window.history.back();\"><< Back</button>\n");
break;
case EMAIL_SEND_ERROR:
foreach ($aIssues as $sError)
{
$oP->error(htmlentities($sError, ENT_QUOTES, 'utf-8'));
}
$oP->add("<button onClick=\"window.history.back();\"><< Back</button>\n");
break;
}
}
/**
* Main program
*/
// #@# Init default timezone -> do not get a notice... to be improved !!!
// duplicated from 'attributedef.class.inc.php', needed here because mail() does
// generate a notice
date_default_timezone_set('Europe/Paris');
try
{
switch($sOperation)
{
case 'step1':
DisplayStep1($oP);
break;
case 'step2':
$oP->no_cache();
$sTo = Utils::ReadParam('to', '', false, 'raw_data');
$sFrom = Utils::ReadParam('from', '', false, 'raw_data');
DisplayStep2($oP, $sFrom, $sTo);
break;
default:
$oP->error("Error: unsupported operation '$sOperation'");
}
}
catch(Exception $e)
{
$oP->error("Error: '".htmlentities($e->getMessage(), ENT_QUOTES, 'utf-8')."'");
}
catch(CoreException $e)
{
$oP->error("Error: '".$e->getHtmlDesc()."'");
}
$oP->output();
?>
<?php
// Copyright (C) 2010-2012 Combodo SARL
//
// This file is part of iTop.
//
// 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.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Emailing: helper for the admins to troubleshoot email issues
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**
* Wizard to configure and initialize the iTop application
*/
require_once('../approot.inc.php');
require_once(APPROOT.'/application/utils.inc.php');
require_once(APPROOT.'/core/email.class.inc.php');
require_once('./setuppage.class.inc.php');
require_once(APPROOT.'/application/startup.inc.php');
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be admin)
$sOperation = Utils::ReadParam('operation', 'step1');
$oP = new SetupPage('iTop email test utility');
/**
* Helper to check server setting required to send an email
*/
function CheckEmailSetting($oP)
{
$bRet = true;
if (function_exists('php_ini_loaded_file')) // PHP >= 5.2.4
{
$sPhpIniFile = php_ini_loaded_file();
}
else
{
$sPhpIniFile = 'php.ini';
}
$sTransport = MetaModel::GetConfig()->Get('email_transport');
switch($sTransport)
{
case 'PHPMail':
$oP->info("iTop is configured to use PHP's <a style=\"background:transparent;padding:0;color:#000;text-decoration:underline;\" href=\"http://www.php.net/manual/en/function.mail.php\" target=\"_blank\">mail</a> function to send emails.");
$bIsWindows = (array_key_exists('WINDIR', $_SERVER) || array_key_exists('windir', $_SERVER));
if ($bIsWindows)
{
$sSmtpServer = ini_get('SMTP');
if (empty($sSmtpServer))
{
$oP->error("The SMTP server is not defined. Please add the 'SMTP' directive into $sPhpIniFile");
$bRet = false;
}
else if (strcasecmp($sSmtpServer, 'localhost') == 0)
{
$oP->warning("Your SMTP server is configured to 'localhost'. You might want to set or change the 'SMTP' directive into $sPhpIniFile");
}
else
{
$oP->info("Your SMTP server: <strong>$sSmtpServer</strong>. To change this value, modify the 'SMTP' directive into $sPhpIniFile");
}
$iSmtpPort = (int) ini_get('smtp_port');
if (empty($iSmtpPort))
{
$oP->info("The SMTP port is not defined. Please add the 'smtp_port' directive into $sPhpIniFile");
$bRet = false;
}
else if ($iSmtpPort == 25)
{
$oP->info("Your SMTP port is configured to the default value: 25. You might want to set or change the 'smtp_port' directive into $sPhpIniFile");
}
else
{
$oP->info("Your SMTP port is configured to $iSmtpPort. You might want to set or change the 'smtp_port' directive into $sPhpIniFile");
}
}
else
{
// Not a windows system
$sSendMail = ini_get('sendmail_path');
if (empty($sSendMail))
{
$oP->error("The command to send mail is not defined. Please add the 'sendmail_path' directive into $sPhpIniFile. A recommended setting is <em>sendmail_path=sendmail -t -i</em>");
$bRet = false;
}
else
{
$oP->info("The command to send mail is: <strong>$sSendMail</strong>. To change this value, modify the 'sendmail_path' directive into $sPhpIniFile");
}
}
break;
case 'SMTP':
$oP->info("iTop is configured to use the <b>SMTP</b> transport.");
$sHost = MetaModel::GetConfig()->Get('email_transport_smtp.host');
$sPort = MetaModel::GetConfig()->Get('email_transport_smtp.port');
$sEncryption = MetaModel::GetConfig()->Get('email_transport_smtp.encryption');
$sDisplayEncryption = empty($sEncryption) ? '<em>no encryption</em> ' : $sEncryption;
$sUserName = MetaModel::GetConfig()->Get('email_transport_smtp.username');
$sDisplayUserName = empty($sUserName) ? '<em>no user</em> ' : $sUserName;
$sPassword = MetaModel::GetConfig()->Get('email_transport_smtp.password');
$sDisplayPassword = empty($sPassword) ? '<em>no password</em> ' : str_repeat('*', strlen($sPassword));
$oP->info("SMTP configuration (from config-itop.php): host: $sHost, port: $sPort, user: $sDisplayUserName, password: $sDisplayPassword, encryption: $sDisplayEncryption.");
if (($sHost == 'localhost') && ($sPort == '25') && ($sUserName == '') && ($sPassword == '') )
{
$oP->warning("The default settings may not be suitable for your environment. You may want to ajust these values by editing iTop's configuration file (".APPROOT."conf/production/config-itop.php).");
}
break;
case 'Null':
$oP->warning("iTop is configured to use the <b>Null</b> transport: emails sending will have no effect.");
$bRet = false;
break;
case 'LogFile':
$oP->warning("iTop is configured to use the <b>LogFile</b> transport: emails will <em>not</em> be sent but logged to the file: '".APPROOT."/log/mail.log'.");
$bRet = true;
break;
default:
$oP->error("Unknown transport '$sTransport' configured.");
$bRet = false;
}
if ($bRet)
{
$oP->ok("PHP settings are ok to proceed with a test of the email");
}
$bConfigAsync = MetaModel::GetConfig()->Get('email_asynchronous');
if ($bConfigAsync)
{
$oP->warning("iTop is configured to send emails <em>asynchronously</em>. Make sure that cron.php is scheduled to run in the background, otherwise regular emails will <em>not</em> be sent. For the purpose of this test, the email will be sent <em>synchronously</em>.");
}
return $bRet;
}
/**
* Display the form for the first step of the test wizard
* which consists in a basic check of the configuration and display of a form for testing
*/
function DisplayStep1(SetupPage $oP)
{
$sNextOperation = 'step2';
$oP->add("<h1>iTop email test</h1>\n");
$oP->add("<h2>Checking prerequisites</h2>\n");
if (CheckEmailSetting($oP))
{
$sRedStar = '<span class="hilite">*</span>';
$oP->add("<h2>Try to send an email</h2>\n");
$oP->add("<form method=\"post\" onSubmit=\"return DoSubmit('Sending an email...', 10)\">\n");
// Form goes here
$oP->add("<fieldset><legend>Test recipient</legend>\n");
$aForm = array();
$aForm[] = array(
'label' => "To$sRedStar:",
'input' => "<input id=\"to\" type=\"text\" name=\"to\" value=\"\">",
'help' => ' email address (e.g. john.foo@worldcompany.com)',
);
$aForm[] = array(
'label' => "From:",
'input' => "<input id=\"from\" type=\"text\" name=\"from\" value=\"\">",
'help' => ' defaults to the configuration param "email_default_sender_address" or "To" field.',
);
$oP->form($aForm);
$oP->add("</fieldset>\n");
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"$sNextOperation\">\n");
$oP->add("<div>\n");
$oP->add("<button style=\"float:left\" type=\"button\" onclick=\"window.location.reload()\">Refresh</button>\n");
$oP->add("<button style=\"float:right\" type=\"submit\">Next >></button>\n");
$oP->add("<div style=\"clear:both;\"></div>\n");
$oP->add("</div>\n");
$oP->add("</form>\n");
}
}
/**
* Display the form for the second step of the configuration wizard
* which consists in sending an email, which maybe a problem under Windows
*/
function DisplayStep2(SetupPage $oP, $sFrom, $sTo)
{
//$sNextOperation = 'step3';
$oP->add("<h1>iTop configuration wizard</h1>\n");
$oP->add("<h2>Step 2: send an email</h2>\n");
$oP->add("<p>Sending an email to '".htmlentities($sTo, ENT_QUOTES, 'utf-8')."'... (From: '".htmlentities($sFrom, ENT_QUOTES, 'utf-8')."')</p>\n");
$oP->add("<form method=\"post\">\n");
$oEmail = new Email();
$oEmail->SetRecipientTO($sTo);
$oEmail->SetRecipientFrom($sFrom);
$oEmail->SetSubject("Test iTop");
$oEmail->SetBody("<p>Hello,</p><p>The email function is now working fine.</p><p>You may now be able to use the notification function.</p><p>iTop</p>");
$iRes = $oEmail->Send($aIssues, true /* force synchronous exec */);
switch ($iRes)
{
case EMAIL_SEND_OK:
$sTransport = MetaModel::GetConfig()->Get('email_transport');
if ($sTransport == 'LogFile')
{
$oP->ok("The email has been logged into the file ".APPROOT."/log/mail.log.");
}
else
{
$oP->ok("The email has been sent, check your inbox for the incoming mail...");
}
$oP->add("<button onClick=\"window.history.back();\"><< Back</button>\n");
break;
case EMAIL_SEND_PENDING:
$oP->ok("Email queued");
$oP->add("<button onClick=\"window.history.back();\"><< Back</button>\n");
break;
case EMAIL_SEND_ERROR:
foreach ($aIssues as $sError)
{
$oP->error(htmlentities($sError, ENT_QUOTES, 'utf-8'));
}
$oP->add("<button onClick=\"window.history.back();\"><< Back</button>\n");
break;
}
}
/**
* Main program
*/
// #@# Init default timezone -> do not get a notice... to be improved !!!
// duplicated from 'attributedef.class.inc.php', needed here because mail() does
// generate a notice
date_default_timezone_set('Europe/Paris');
try
{
switch($sOperation)
{
case 'step1':
DisplayStep1($oP);
break;
case 'step2':
$oP->no_cache();
$sTo = Utils::ReadParam('to', '', false, 'raw_data');
$sFrom = Utils::ReadParam('from', '', false, 'raw_data');
DisplayStep2($oP, $sFrom, $sTo);
break;
default:
$oP->error("Error: unsupported operation '$sOperation'");
}
}
catch(Exception $e)
{
$oP->error("Error: '".htmlentities($e->getMessage(), ENT_QUOTES, 'utf-8')."'");
}
catch(CoreException $e)
{
$oP->error("Error: '".$e->getHtmlDesc()."'");
}
$oP->output();
?>

File diff suppressed because it is too large Load Diff

View File

@@ -1,102 +1,102 @@
<?php
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
// 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.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Persistent class ModuleInstallation to record the installed modules
* Log of module installations
*
* @copyright Copyright (C) 2010-2017 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class ModuleInstallation extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "core,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_module_install",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("version", array("allowed_values"=>null, "sql"=>"version", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("installed", array("allowed_values"=>null, "sql"=>"installed", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("comment", array("allowed_values"=>null, "sql"=>"comment", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("parent_id", array("targetclass"=>"ModuleInstallation", "jointype"=> "", "allowed_values"=>null, "sql"=>"parent_id", "is_null_allowed"=>true, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'version', 'installed', 'comment', 'parent_id')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('name', 'version', 'installed', 'parent_id')); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
/**
* Persistent class ExtensionInstallation to record the installed extensions
* Log of extensions installations
*
* @copyright Copyright (C) 2017 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class ExtensionInstallation extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "core,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_extension_install",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("code", array("allowed_values"=>null, "sql"=>"code", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("label", array("allowed_values"=>null, "sql"=>"label", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("version", array("allowed_values"=>null, "sql"=>"version", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("source", array("allowed_values"=>null, "sql"=>"source", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("installed", array("allowed_values"=>null, "sql"=>"installed", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('code', 'label', 'version', 'installed', 'source')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('code', 'label', 'version', 'installed', 'source')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('standard_search', array('code', 'label', 'version', 'installed', 'source')); // Attributes to be displayed in the search form
}
}
<?php
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
// 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.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Persistent class ModuleInstallation to record the installed modules
* Log of module installations
*
* @copyright Copyright (C) 2010-2017 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class ModuleInstallation extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "core,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_module_install",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("version", array("allowed_values"=>null, "sql"=>"version", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("installed", array("allowed_values"=>null, "sql"=>"installed", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeText("comment", array("allowed_values"=>null, "sql"=>"comment", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalKey("parent_id", array("targetclass"=>"ModuleInstallation", "jointype"=> "", "allowed_values"=>null, "sql"=>"parent_id", "is_null_allowed"=>true, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('name', 'version', 'installed', 'comment', 'parent_id')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('name', 'version', 'installed', 'parent_id')); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
/**
* Persistent class ExtensionInstallation to record the installed extensions
* Log of extensions installations
*
* @copyright Copyright (C) 2017 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class ExtensionInstallation extends cmdbAbstractObject
{
public static function Init()
{
$aParams = array
(
"category" => "core,view_in_gui",
"key_type" => "autoincrement",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_extension_install",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("code", array("allowed_values"=>null, "sql"=>"code", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("label", array("allowed_values"=>null, "sql"=>"label", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("version", array("allowed_values"=>null, "sql"=>"version", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("source", array("allowed_values"=>null, "sql"=>"source", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDateTime("installed", array("allowed_values"=>null, "sql"=>"installed", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
// Display lists
MetaModel::Init_SetZListItems('details', array('code', 'label', 'version', 'installed', 'source')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('code', 'label', 'version', 'installed', 'source')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('standard_search', array('code', 'label', 'version', 'installed', 'source')); // Attributes to be displayed in the search form
}
}

View File

@@ -1,227 +1,227 @@
<?php
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
// 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.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
require_once(APPROOT.'setup/setuppage.class.inc.php');
/**
* Class ModuleInstaller
* Defines the API to implement module specific actions during the setup
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
abstract class ModuleInstallerAPI
{
public static function BeforeWritingConfig(Config $oConfiguration)
{
return $oConfiguration;
}
/**
* Handler called before creating or upgrading the database schema
* @param $oConfiguration Config The new configuration of the application
* @param $sPreviousVersion string Previous version number of the module (empty string in case of first install)
* @param $sCurrentVersion string Current version number of the module
*/
public static function BeforeDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{
}
/**
* Handler called after the creation/update of the database schema
* @param $oConfiguration Config The new configuration of the application
* @param $sPreviousVersion string Previous version number of the module (empty string in case of first install)
* @param $sCurrentVersion string Current version number of the module
*/
public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{
}
/**
* Handler called at the end of the setup of the database (profiles and admin accounts created), but before the data load
* @param $oConfiguration Config The new configuration of the application
* @param $sPreviousVersion string Previous version number of the module (empty string in case of first install)
* @param $sCurrentVersion string Current version number of the module
*/
public static function AfterDatabaseSetup(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{
}
/**
* Handler called at the end of the data load
* @param $oConfiguration Config The new configuration of the application
* @param $sPreviousVersion string Previous version number of the module (empty string in case of first install)
* @param $sCurrentVersion string Current version number of the module
*/
public static function AfterDataLoad(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{
}
/**
* Helper to complete the renaming of a class
* The renaming is made in the datamodel definition, but the name has to be changed in the DB as well
* Must be called after DB update, i.e within an implementation of AfterDatabaseCreation()
*
* @param string $sFrom Original name (already INVALID in the current datamodel)
* @param string $sTo New name (valid in the current datamodel)
* @return void
*/
public static function RenameClassInDB($sFrom, $sTo)
{
try
{
if (!MetaModel::IsStandaloneClass($sTo))
{
$sRootClass = MetaModel::GetRootClass($sTo);
$sTableName = MetaModel::DBGetTable($sRootClass);
$sFinalClassCol = MetaModel::DBGetClassField($sRootClass);
$sRepair = "UPDATE `$sTableName` SET `$sFinalClassCol` = '$sTo' WHERE `$sFinalClassCol` = BINARY '$sFrom'";
CMDBSource::Query($sRepair);
$iAffectedRows = CMDBSource::AffectedRows();
SetupPage::log_info("Renaming class in DB - final class from '$sFrom' to '$sTo': $iAffectedRows rows affected");
}
}
catch(Exception $e)
{
SetupPage::log_warning("Failed to rename class in DB - final class from '$sFrom' to '$sTo'. Reason: ".$e->getMessage());
}
}
/**
* Helper to modify an enum value
* The change is made in the datamodel definition, but the value has to be changed in the DB as well
* Must be called BEFORE DB update, i.e within an implementation of BeforeDatabaseCreation()
* This helper does change ONE value at a time
*
* @param string $sClass A valid class name
* @param string $sAttCode The enum attribute code
* @param string $sFrom Original value (already INVALID in the current datamodel)
* @param string $sTo New value (valid in the current datamodel)
* @return void
*/
public static function RenameEnumValueInDB($sClass, $sAttCode, $sFrom, $sTo)
{
try
{
if (!MetaModel::IsValidAttCode($sClass, $sAttCode))
{
SetupPage::log_warning("Changing enum in DB - $sClass::$sAttCode - from '$sFrom' to '$sTo' failed. Reason '$sAttCode' is not a valid attribute of the class '$sClass'.");
return;
}
$sOriginClass = MetaModel::GetAttributeOrigin($sClass, $sAttCode);
$sTableName = MetaModel::DBGetTable($sOriginClass);
$oAttDef = MetaModel::GetAttributeDef($sOriginClass, $sAttCode);
if ($oAttDef instanceof AttributeEnum)
{
$oValDef = $oAttDef->GetValuesDef();
if ($oValDef)
{
$aNewValues = array_keys($oValDef->GetValues(array(), ""));
if (in_array($sTo, $aNewValues))
{
$sEnumCol = $oAttDef->Get("sql");
$aFields = CMDBSource::QueryToArray("SHOW COLUMNS FROM `$sTableName` WHERE Field = '$sEnumCol'");
if (isset($aFields[0]['Type']))
{
$sColType = $aFields[0]['Type'];
// Note: the parsing should rely on str_getcsv (requires PHP 5.3) to cope with escaped string
if (preg_match("/^enum\(\'(.*)\'\)$/", $sColType, $aMatches))
{
$aCurrentValues = explode("','", $aMatches[1]);
}
}
if (!in_array($sFrom, $aNewValues))
{
if (!in_array($sTo, $aCurrentValues)) // if not already transformed!
{
$sNullSpec = $oAttDef->IsNullAllowed() ? 'NULL' : 'NOT NULL';
if (strtolower($sTo) == strtolower($sFrom))
{
SetupPage::log_info("Changing enum in DB - $sClass::$sAttCode from '$sFrom' to '$sTo' (just a change in the case)");
$aTargetValues = array();
foreach ($aCurrentValues as $sValue)
{
if ($sValue == $sFrom)
{
$sValue = $sTo;
}
$aTargetValues[] = $sValue;
}
$sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aTargetValues)).") $sNullSpec";
$sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition";
CMDBSource::Query($sRepair);
}
else
{
// 1st - Allow both values in the column definition
//
SetupPage::log_info("Changing enum in DB - $sClass::$sAttCode from '$sFrom' to '$sTo'");
$aAllValues = $aCurrentValues;
$aAllValues[] = $sTo;
$sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aAllValues)).") $sNullSpec";
$sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition";
CMDBSource::Query($sRepair);
// 2nd - Change the old value into the new value
//
$sRepair = "UPDATE `$sTableName` SET `$sEnumCol` = '$sTo' WHERE `$sEnumCol` = BINARY '$sFrom'";
CMDBSource::Query($sRepair);
$iAffectedRows = CMDBSource::AffectedRows();
SetupPage::log_info("Changing enum in DB - $iAffectedRows rows updated");
// 3rd - Remove the useless value from the column definition
//
$aTargetValues = array();
foreach ($aCurrentValues as $sValue)
{
if ($sValue == $sFrom)
{
$sValue = $sTo;
}
$aTargetValues[] = $sValue;
}
$sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aTargetValues)).") $sNullSpec";
$sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition";
CMDBSource::Query($sRepair);
SetupPage::log_info("Changing enum in DB - removed useless value '$sFrom'");
}
}
}
else
{
SetupPage::log_warning("Changing enum in DB - $sClass::$sAttCode - '$sFrom' is still a valid value (".implode(', ', $aNewValues).")");
}
}
else
{
SetupPage::log_warning("Changing enum in DB - $sClass::$sAttCode - '$sTo' is not a known value (".implode(', ', $aNewValues).")");
}
}
}
}
catch(Exception $e)
{
SetupPage::log_warning("Changing enum in DB - $sClass::$sAttCode - '$sTo' failed. Reason ".$e->getMessage());
}
}
}
<?php
// Copyright (C) 2010-2017 Combodo SARL
//
// This file is part of iTop.
//
// 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.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
require_once(APPROOT.'setup/setuppage.class.inc.php');
/**
* Class ModuleInstaller
* Defines the API to implement module specific actions during the setup
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
abstract class ModuleInstallerAPI
{
public static function BeforeWritingConfig(Config $oConfiguration)
{
return $oConfiguration;
}
/**
* Handler called before creating or upgrading the database schema
* @param $oConfiguration Config The new configuration of the application
* @param $sPreviousVersion string Previous version number of the module (empty string in case of first install)
* @param $sCurrentVersion string Current version number of the module
*/
public static function BeforeDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{
}
/**
* Handler called after the creation/update of the database schema
* @param $oConfiguration Config The new configuration of the application
* @param $sPreviousVersion string Previous version number of the module (empty string in case of first install)
* @param $sCurrentVersion string Current version number of the module
*/
public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{
}
/**
* Handler called at the end of the setup of the database (profiles and admin accounts created), but before the data load
* @param $oConfiguration Config The new configuration of the application
* @param $sPreviousVersion string Previous version number of the module (empty string in case of first install)
* @param $sCurrentVersion string Current version number of the module
*/
public static function AfterDatabaseSetup(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{
}
/**
* Handler called at the end of the data load
* @param $oConfiguration Config The new configuration of the application
* @param $sPreviousVersion string Previous version number of the module (empty string in case of first install)
* @param $sCurrentVersion string Current version number of the module
*/
public static function AfterDataLoad(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{
}
/**
* Helper to complete the renaming of a class
* The renaming is made in the datamodel definition, but the name has to be changed in the DB as well
* Must be called after DB update, i.e within an implementation of AfterDatabaseCreation()
*
* @param string $sFrom Original name (already INVALID in the current datamodel)
* @param string $sTo New name (valid in the current datamodel)
* @return void
*/
public static function RenameClassInDB($sFrom, $sTo)
{
try
{
if (!MetaModel::IsStandaloneClass($sTo))
{
$sRootClass = MetaModel::GetRootClass($sTo);
$sTableName = MetaModel::DBGetTable($sRootClass);
$sFinalClassCol = MetaModel::DBGetClassField($sRootClass);
$sRepair = "UPDATE `$sTableName` SET `$sFinalClassCol` = '$sTo' WHERE `$sFinalClassCol` = BINARY '$sFrom'";
CMDBSource::Query($sRepair);
$iAffectedRows = CMDBSource::AffectedRows();
SetupPage::log_info("Renaming class in DB - final class from '$sFrom' to '$sTo': $iAffectedRows rows affected");
}
}
catch(Exception $e)
{
SetupPage::log_warning("Failed to rename class in DB - final class from '$sFrom' to '$sTo'. Reason: ".$e->getMessage());
}
}
/**
* Helper to modify an enum value
* The change is made in the datamodel definition, but the value has to be changed in the DB as well
* Must be called BEFORE DB update, i.e within an implementation of BeforeDatabaseCreation()
* This helper does change ONE value at a time
*
* @param string $sClass A valid class name
* @param string $sAttCode The enum attribute code
* @param string $sFrom Original value (already INVALID in the current datamodel)
* @param string $sTo New value (valid in the current datamodel)
* @return void
*/
public static function RenameEnumValueInDB($sClass, $sAttCode, $sFrom, $sTo)
{
try
{
if (!MetaModel::IsValidAttCode($sClass, $sAttCode))
{
SetupPage::log_warning("Changing enum in DB - $sClass::$sAttCode - from '$sFrom' to '$sTo' failed. Reason '$sAttCode' is not a valid attribute of the class '$sClass'.");
return;
}
$sOriginClass = MetaModel::GetAttributeOrigin($sClass, $sAttCode);
$sTableName = MetaModel::DBGetTable($sOriginClass);
$oAttDef = MetaModel::GetAttributeDef($sOriginClass, $sAttCode);
if ($oAttDef instanceof AttributeEnum)
{
$oValDef = $oAttDef->GetValuesDef();
if ($oValDef)
{
$aNewValues = array_keys($oValDef->GetValues(array(), ""));
if (in_array($sTo, $aNewValues))
{
$sEnumCol = $oAttDef->Get("sql");
$aFields = CMDBSource::QueryToArray("SHOW COLUMNS FROM `$sTableName` WHERE Field = '$sEnumCol'");
if (isset($aFields[0]['Type']))
{
$sColType = $aFields[0]['Type'];
// Note: the parsing should rely on str_getcsv (requires PHP 5.3) to cope with escaped string
if (preg_match("/^enum\(\'(.*)\'\)$/", $sColType, $aMatches))
{
$aCurrentValues = explode("','", $aMatches[1]);
}
}
if (!in_array($sFrom, $aNewValues))
{
if (!in_array($sTo, $aCurrentValues)) // if not already transformed!
{
$sNullSpec = $oAttDef->IsNullAllowed() ? 'NULL' : 'NOT NULL';
if (strtolower($sTo) == strtolower($sFrom))
{
SetupPage::log_info("Changing enum in DB - $sClass::$sAttCode from '$sFrom' to '$sTo' (just a change in the case)");
$aTargetValues = array();
foreach ($aCurrentValues as $sValue)
{
if ($sValue == $sFrom)
{
$sValue = $sTo;
}
$aTargetValues[] = $sValue;
}
$sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aTargetValues)).") $sNullSpec";
$sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition";
CMDBSource::Query($sRepair);
}
else
{
// 1st - Allow both values in the column definition
//
SetupPage::log_info("Changing enum in DB - $sClass::$sAttCode from '$sFrom' to '$sTo'");
$aAllValues = $aCurrentValues;
$aAllValues[] = $sTo;
$sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aAllValues)).") $sNullSpec";
$sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition";
CMDBSource::Query($sRepair);
// 2nd - Change the old value into the new value
//
$sRepair = "UPDATE `$sTableName` SET `$sEnumCol` = '$sTo' WHERE `$sEnumCol` = BINARY '$sFrom'";
CMDBSource::Query($sRepair);
$iAffectedRows = CMDBSource::AffectedRows();
SetupPage::log_info("Changing enum in DB - $iAffectedRows rows updated");
// 3rd - Remove the useless value from the column definition
//
$aTargetValues = array();
foreach ($aCurrentValues as $sValue)
{
if ($sValue == $sFrom)
{
$sValue = $sTo;
}
$aTargetValues[] = $sValue;
}
$sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aTargetValues)).") $sNullSpec";
$sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition";
CMDBSource::Query($sRepair);
SetupPage::log_info("Changing enum in DB - removed useless value '$sFrom'");
}
}
}
else
{
SetupPage::log_warning("Changing enum in DB - $sClass::$sAttCode - '$sFrom' is still a valid value (".implode(', ', $aNewValues).")");
}
}
else
{
SetupPage::log_warning("Changing enum in DB - $sClass::$sAttCode - '$sTo' is not a known value (".implode(', ', $aNewValues).")");
}
}
}
}
catch(Exception $e)
{
SetupPage::log_warning("Changing enum in DB - $sClass::$sAttCode - '$sTo' failed. Reason ".$e->getMessage());
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,305 +1,305 @@
<?php
// Copyright (C) 2010-2012 Combodo SARL
//
// This file is part of iTop.
//
// 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.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Web page used for the setup
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT."/application/nicewebpage.class.inc.php");
require_once(APPROOT."setup/modulediscovery.class.inc.php");
require_once(APPROOT."setup/runtimeenv.class.inc.php");
define('INSTALL_LOG_FILE', APPROOT.'/log/setup.log');
class SetupPage extends NiceWebPage
{
public function __construct($sTitle)
{
parent::__construct($sTitle);
$this->add_linked_script("../js/jquery.blockUI.js");
$this->add_linked_script("../setup/setup.js");
$this->add_style("
body {
background-color: #eee;
margin: 0;
padding: 0;
font-size: 10pt;
overflow-y: auto;
}
#header {
width: 600px;
margin-left: auto;
margin-right: auto;
margin-top: 50px;
padding: 20px;
background: #f6f6f1;
height: 54px;
border-top: 1px solid #000;
border-left: 1px solid #000;
border-right: 1px solid #000;
}
#header img {
border: 0;
vertical-align: middle;
margin-right: 20px;
}
#header h1 {
vertical-align: middle;
height: 54px;
noline-height: 54px;
margin: 0;
}
#setup {
width: 600px;
margin-left: auto;
margin-right: auto;
padding: 20px;
background-color: #fff;
border-left: 1px solid #000;
border-right: 1px solid #000;
border-bottom: 1px solid #000;
}
.center {
text-align: center;
}
h1 {
color: #555555;
font-size: 16pt;
}
h2 {
color: #000;
font-size: 14pt;
}
h3 {
color: #1C94C4;
font-size: 12pt;
font-weight: bold;
}
.next {
width: 100%;
text-align: right;
}
.v-spacer {
padding-top: 1em;
}
button {
margin-top: 1em;
padding-left: 1em;
padding-right: 1em;
}
p.info {
padding-left: 50px;
background: url(../images/info-mid.png) no-repeat left -5px;
min-height: 48px;
}
p.ok {
padding-left: 50px;
background: url(../images/clean-mid.png) no-repeat left -8px;
min-height: 48px;
}
p.warning {
padding-left: 50px;
background: url(../images/messagebox_warning-mid.png) no-repeat left -5px;
min-height: 48px;
}
p.error {
padding-left: 50px;
background: url(../images/stop-mid.png) no-repeat left -5px;
min-height: 48px;
}
td.label {
text-align: left;
}
label.read-only {
color: #666;
cursor: text;
}
td.input {
text-align: left;
}
table.formTable {
border: 0;
cellpadding: 2px;
cellspacing: 0;
}
.wizlabel, .wizinput {
color: #000;
font-size: 10pt;
}
.wizhelp {
color: #333;
font-size: 8pt;
}
#progress {
border:1px solid #000000;
width: 180px;
height: 20px;
line-height: 20px;
text-align: center;
margin: 5px;
}
h3.clickable {
background: url(../images/plus.gif) no-repeat left;
padding-left:16px;
cursor: hand;
}
h3.clickable.open {
background: url(../images/minus.gif) no-repeat left;
padding-left:16px;
cursor: hand;
}
");
}
/**
* Overriden because the application is not fully loaded when the setup is being run
*/
public function GetAbsoluteUrlAppRoot()
{
return '../';
}
/**
* Overriden because the application is not fully loaded when the setup is being run
*/
public function GetAbsoluteUrlModulesRoot()
{
return $this->GetAbsoluteUrlAppRoot().utils::GetCurrentEnvironment();
}
/**
* Overriden because the application is not fully loaded when the setup is being run
*/
function GetApplicationContext()
{
return '';
}
public function info($sText)
{
$this->add("<p class=\"info\">$sText</p>\n");
$this->log_info($sText);
}
public function ok($sText)
{
$this->add("<p class=\"ok\">$sText</p>\n");
$this->log_ok($sText);
}
public function warning($sText)
{
$this->add("<p class=\"warning\">$sText</p>\n");
$this->log_warning($sText);
}
public function error($sText)
{
$this->add("<p class=\"error\">$sText</p>\n");
$this->log_error($sText);
}
public function form($aData)
{
$this->add("<table class=\"formTable\">\n");
foreach($aData as $aRow)
{
$this->add("<tr>\n");
if (isset($aRow['label']) && isset($aRow['input']) && isset($aRow['help']))
{
$this->add("<td class=\"wizlabel\">{$aRow['label']}</td>\n");
$this->add("<td class=\"wizinput\">{$aRow['input']}</td>\n");
$this->add("<td class=\"wizhelp\">{$aRow['help']}</td>\n");
}
else if (isset($aRow['label']) && isset($aRow['help']))
{
$this->add("<td colspan=\"2\" class=\"wizlabel\">{$aRow['label']}</td>\n");
$this->add("<td class=\"wizhelp\">{$aRow['help']}</td>\n");
}
else if (isset($aRow['label']) && isset($aRow['input']))
{
$this->add("<td class=\"wizlabel\">{$aRow['label']}</td>\n");
$this->add("<td colspan=\"2\" class=\"wizinput\">{$aRow['input']}</td>\n");
}
else if (isset($aRow['label']))
{
$this->add("<td colspan=\"3\" class=\"wizlabel\">{$aRow['label']}</td>\n");
}
$this->add("</tr>\n");
}
$this->add("</table>\n");
}
public function collapsible($sId, $sTitle, $aItems, $bOpen = true)
{
$this->add("<h3 class=\"clickable open\" id=\"{$sId}\">$sTitle</h3>");
$this->p('<ul id="'.$sId.'_list">');
foreach($aItems as $sItem)
{
$this->p("<li>$sItem</li>\n");
}
$this->p('</ul>');
$this->add_ready_script("$('#{$sId}').click( function() { $(this).toggleClass('open'); $('#{$sId}_list').toggle();} );\n");
if (!$bOpen)
{
$this->add_ready_script("$('#{$sId}').toggleClass('open'); $('#{$sId}_list').toggle();\n");
}
}
public function output()
{
$this->s_content = "<div id=\"header\"><h1><a href=\"http://www.combodo.com/itop\" target=\"_blank\"><img title=\"iTop by Combodo\" src=\"../images/itop-logo.png?t=".utils::GetCacheBusterTimestamp()."\"></a>&nbsp;".htmlentities($this->s_title, ENT_QUOTES, 'UTF-8')."</h1>\n</div><div id=\"setup\">{$this->s_content}\n</div>\n";
return parent::output();
}
public static function log_error($sText)
{
self::log("Error - ".$sText);
}
public static function log_warning($sText)
{
self::log("Warning - ".$sText);
}
public static function log_info($sText)
{
self::log("Info - ".$sText);
}
public static function log_ok($sText)
{
self::log("Ok - ".$sText);
}
public static function log($sText)
{
$hLogFile = @fopen(INSTALL_LOG_FILE, 'a');
if ($hLogFile !== false)
{
$sDate = date('Y-m-d H:i:s');
fwrite($hLogFile, "$sDate - $sText\n");
fclose($hLogFile);
}
}
} // End of class
<?php
// Copyright (C) 2010-2012 Combodo SARL
//
// This file is part of iTop.
//
// 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.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Web page used for the setup
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT."/application/nicewebpage.class.inc.php");
require_once(APPROOT."setup/modulediscovery.class.inc.php");
require_once(APPROOT."setup/runtimeenv.class.inc.php");
define('INSTALL_LOG_FILE', APPROOT.'/log/setup.log');
class SetupPage extends NiceWebPage
{
public function __construct($sTitle)
{
parent::__construct($sTitle);
$this->add_linked_script("../js/jquery.blockUI.js");
$this->add_linked_script("../setup/setup.js");
$this->add_style("
body {
background-color: #eee;
margin: 0;
padding: 0;
font-size: 10pt;
overflow-y: auto;
}
#header {
width: 600px;
margin-left: auto;
margin-right: auto;
margin-top: 50px;
padding: 20px;
background: #f6f6f1;
height: 54px;
border-top: 1px solid #000;
border-left: 1px solid #000;
border-right: 1px solid #000;
}
#header img {
border: 0;
vertical-align: middle;
margin-right: 20px;
}
#header h1 {
vertical-align: middle;
height: 54px;
noline-height: 54px;
margin: 0;
}
#setup {
width: 600px;
margin-left: auto;
margin-right: auto;
padding: 20px;
background-color: #fff;
border-left: 1px solid #000;
border-right: 1px solid #000;
border-bottom: 1px solid #000;
}
.center {
text-align: center;
}
h1 {
color: #555555;
font-size: 16pt;
}
h2 {
color: #000;
font-size: 14pt;
}
h3 {
color: #1C94C4;
font-size: 12pt;
font-weight: bold;
}
.next {
width: 100%;
text-align: right;
}
.v-spacer {
padding-top: 1em;
}
button {
margin-top: 1em;
padding-left: 1em;
padding-right: 1em;
}
p.info {
padding-left: 50px;
background: url(../images/info-mid.png) no-repeat left -5px;
min-height: 48px;
}
p.ok {
padding-left: 50px;
background: url(../images/clean-mid.png) no-repeat left -8px;
min-height: 48px;
}
p.warning {
padding-left: 50px;
background: url(../images/messagebox_warning-mid.png) no-repeat left -5px;
min-height: 48px;
}
p.error {
padding-left: 50px;
background: url(../images/stop-mid.png) no-repeat left -5px;
min-height: 48px;
}
td.label {
text-align: left;
}
label.read-only {
color: #666;
cursor: text;
}
td.input {
text-align: left;
}
table.formTable {
border: 0;
cellpadding: 2px;
cellspacing: 0;
}
.wizlabel, .wizinput {
color: #000;
font-size: 10pt;
}
.wizhelp {
color: #333;
font-size: 8pt;
}
#progress {
border:1px solid #000000;
width: 180px;
height: 20px;
line-height: 20px;
text-align: center;
margin: 5px;
}
h3.clickable {
background: url(../images/plus.gif) no-repeat left;
padding-left:16px;
cursor: hand;
}
h3.clickable.open {
background: url(../images/minus.gif) no-repeat left;
padding-left:16px;
cursor: hand;
}
");
}
/**
* Overriden because the application is not fully loaded when the setup is being run
*/
public function GetAbsoluteUrlAppRoot()
{
return '../';
}
/**
* Overriden because the application is not fully loaded when the setup is being run
*/
public function GetAbsoluteUrlModulesRoot()
{
return $this->GetAbsoluteUrlAppRoot().utils::GetCurrentEnvironment();
}
/**
* Overriden because the application is not fully loaded when the setup is being run
*/
function GetApplicationContext()
{
return '';
}
public function info($sText)
{
$this->add("<p class=\"info\">$sText</p>\n");
$this->log_info($sText);
}
public function ok($sText)
{
$this->add("<p class=\"ok\">$sText</p>\n");
$this->log_ok($sText);
}
public function warning($sText)
{
$this->add("<p class=\"warning\">$sText</p>\n");
$this->log_warning($sText);
}
public function error($sText)
{
$this->add("<p class=\"error\">$sText</p>\n");
$this->log_error($sText);
}
public function form($aData)
{
$this->add("<table class=\"formTable\">\n");
foreach($aData as $aRow)
{
$this->add("<tr>\n");
if (isset($aRow['label']) && isset($aRow['input']) && isset($aRow['help']))
{
$this->add("<td class=\"wizlabel\">{$aRow['label']}</td>\n");
$this->add("<td class=\"wizinput\">{$aRow['input']}</td>\n");
$this->add("<td class=\"wizhelp\">{$aRow['help']}</td>\n");
}
else if (isset($aRow['label']) && isset($aRow['help']))
{
$this->add("<td colspan=\"2\" class=\"wizlabel\">{$aRow['label']}</td>\n");
$this->add("<td class=\"wizhelp\">{$aRow['help']}</td>\n");
}
else if (isset($aRow['label']) && isset($aRow['input']))
{
$this->add("<td class=\"wizlabel\">{$aRow['label']}</td>\n");
$this->add("<td colspan=\"2\" class=\"wizinput\">{$aRow['input']}</td>\n");
}
else if (isset($aRow['label']))
{
$this->add("<td colspan=\"3\" class=\"wizlabel\">{$aRow['label']}</td>\n");
}
$this->add("</tr>\n");
}
$this->add("</table>\n");
}
public function collapsible($sId, $sTitle, $aItems, $bOpen = true)
{
$this->add("<h3 class=\"clickable open\" id=\"{$sId}\">$sTitle</h3>");
$this->p('<ul id="'.$sId.'_list">');
foreach($aItems as $sItem)
{
$this->p("<li>$sItem</li>\n");
}
$this->p('</ul>');
$this->add_ready_script("$('#{$sId}').click( function() { $(this).toggleClass('open'); $('#{$sId}_list').toggle();} );\n");
if (!$bOpen)
{
$this->add_ready_script("$('#{$sId}').toggleClass('open'); $('#{$sId}_list').toggle();\n");
}
}
public function output()
{
$this->s_content = "<div id=\"header\"><h1><a href=\"http://www.combodo.com/itop\" target=\"_blank\"><img title=\"iTop by Combodo\" src=\"../images/itop-logo.png?t=".utils::GetCacheBusterTimestamp()."\"></a>&nbsp;".htmlentities($this->s_title, ENT_QUOTES, 'UTF-8')."</h1>\n</div><div id=\"setup\">{$this->s_content}\n</div>\n";
return parent::output();
}
public static function log_error($sText)
{
self::log("Error - ".$sText);
}
public static function log_warning($sText)
{
self::log("Warning - ".$sText);
}
public static function log_info($sText)
{
self::log("Info - ".$sText);
}
public static function log_ok($sText)
{
self::log("Ok - ".$sText);
}
public static function log($sText)
{
$hLogFile = @fopen(INSTALL_LOG_FILE, 'a');
if ($hLogFile !== false)
{
$sDate = date('Y-m-d H:i:s');
fwrite($hLogFile, "$sDate - $sText\n");
fclose($hLogFile);
}
}
} // End of class

File diff suppressed because it is too large Load Diff

View File

@@ -1,449 +1,449 @@
<?php
// Copyright (C) 2010-2012 Combodo SARL
//
// This file is part of iTop.
//
// 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.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Load XML data from a set of files
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
define ('KEYS_CACHE_FILE', APPROOT.'data/keyscache.tmp');
/**
* Class to load sets of objects from XML files into the database
* XML files can be produced by the 'export' web service or by any other means
* Here is a simple example:
* $oLoader = new XMLDataLoader('../itop-config.php');
* $oLoader->StartSession();
* $oLoader->LoadFile('./organizations.xml');
* $oLoader->LoadFile('./locations.xml');
* $oLoader->EndSession();
*/
class XMLDataLoader
{
protected $m_aKeys;
protected $m_aObjectsCache;
protected $m_bSessionActive;
protected $m_oChange;
protected $m_sCacheFileName;
protected $m_aErrors;
protected $m_aWarnings;
protected $m_iCountCreated;
public function __construct()
{
$this->m_aKeys = array();
$this->m_aObjectsCache = array();
$this->m_oChange = null;
$this->m_sCacheFileName = KEYS_CACHE_FILE;
$this->LoadKeysCache();
$this->m_bSessionActive = true;
$this->m_aErrors = array();
$this->m_aWarnings = array();
$this->m_iCountCreated = 0;
}
public function StartSession($oChange)
{
// Do cleanup any existing cache file (shall not be necessary unless a setup was interrupted abruptely)
$this->ClearKeysCache();
$this->m_oChange = $oChange;
$this->m_bSessionActive = true;
}
public function EndSession($bStrict = false)
{
$this->ResolveExternalKeys();
$this->m_bSessionActive = false;
if (count($this->m_aErrors) > 0)
{
return false;
}
elseif ($bStrict && count($this->m_aWarnings) > 0)
{
return false;
}
else
{
return true;
}
}
public function GetErrors()
{
return $this->m_aErrors;
}
public function GetWarnings()
{
return $this->m_aWarnings;
}
public function GetCountCreated()
{
return $this->m_iCountCreated;
}
public function __destruct()
{
// Stopping in the middle of a session, let's save the context information
if ($this->m_bSessionActive)
{
$this->SaveKeysCache();
}
else
{
$this->ClearKeysCache();
}
}
/**
* Stores the keys & object cache in a file
*/
protected function SaveKeysCache()
{
if (!is_dir(APPROOT.'data'))
{
mkdir(APPROOT.'data');
}
$hFile = @fopen($this->m_sCacheFileName, 'w');
if ($hFile !== false)
{
$sData = serialize( array('keys' => $this->m_aKeys,
'objects' => $this->m_aObjectsCache,
'change' => $this->m_oChange,
'errors' => $this->m_aErrors,
'warnings' => $this->m_aWarnings,
));
fwrite($hFile, $sData);
fclose($hFile);
}
else
{
throw new Exception("Cannot write to file: '{$this->m_sCacheFileName}'");
}
}
/**
* Loads the keys & object cache from the tmp file
*/
protected function LoadKeysCache()
{
$sFileContent = @file_get_contents($this->m_sCacheFileName);
if (!empty($sFileContent))
{
$aCache = unserialize($sFileContent);
$this->m_aKeys = $aCache['keys'];
$this->m_aObjectsCache = $aCache['objects'];
$this->m_oChange = $aCache['change'];
$this->m_aErrors = $aCache['errors'];
$this->m_aWarnings = $aCache['warnings'];
}
}
/**
* Remove the tmp file used to store the keys cache
*/
protected function ClearKeysCache()
{
if(is_file($this->m_sCacheFileName))
{
unlink($this->m_sCacheFileName);
}
else
{
//echo "<p>Hm, it looks like the file does not exist!!!</p>";
}
$this->m_aKeys = array();
$this->m_aObjectsCache = array();
}
/**
* Helper function to load the objects from a standard XML file into the database
* @param $sFilePath string The full path to the XML file to load
* @param $bUpdateKeyCacheOnly bool Set to true to *just* update the keys cache but not reload the objects
*/
function LoadFile($sFilePath, $bUpdateKeyCacheOnly = false)
{
global $aKeys;
$oXml = simplexml_load_file($sFilePath);
$aReplicas = array();
foreach($oXml as $sClass => $oXmlObj)
{
if (!MetaModel::IsValidClass($sClass))
{
SetupPage::log_error("Unknown class - $sClass");
throw(new Exception("Unknown class - $sClass"));
}
$iSrcId = (integer)$oXmlObj['id']; // Mandatory to cast
// Import algorithm
// Here enumerate all the attributes of the object
// for all attribute that is neither an external field
// not an external key, assign it
// Store all external keys for further reference
// Create the object an store the correspondance between its newly created Id
// and its original Id
// Once all the objects have been created re-assign all the external keys to
// their actual Ids
$iExistingId = $this->GetObjectKey($sClass, $iSrcId);
if ($iExistingId != 0)
{
$oTargetObj = MetaModel::GetObject($sClass, $iExistingId);
}
else
{
$oTargetObj = MetaModel::NewObject($sClass);
}
foreach($oXmlObj as $sAttCode => $oSubNode)
{
if (!MetaModel::IsValidAttCode($sClass, $sAttCode))
{
$sMsg = "Unknown attribute code - $sClass/$sAttCode";
continue; // ignore silently...
//SetupPage::log_error($sMsg);
//throw(new Exception($sMsg));
}
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if (($oAttDef->IsWritable()) && ($oAttDef->IsScalar()))
{
if ($oAttDef->IsExternalKey())
{
if (substr(trim($oSubNode), 0, 6) == 'SELECT')
{
$sQuery = trim($oSubNode);
$oSet = new DBObjectSet(DBObjectSearch::FromOQL($sQuery));
$iMatches = $oSet->Count();
if ($iMatches == 1)
{
$oFoundObject = $oSet->Fetch();
$iExtKey = $oFoundObject->GetKey();
}
else
{
$sMsg = "Ext key not reconcilied - $sClass/$iSrcId - $sAttCode: '".$sQuery."' - found $iMatches matche(s)";
SetupPage::log_error($sMsg);
$this->m_aErrors[] = $sMsg;
$iExtKey = 0;
}
}
else
{
$iDstObj = (integer)($oSubNode);
// Attempt to find the object in the list of loaded objects
$iExtKey = $this->GetObjectKey($oAttDef->GetTargetClass(), $iDstObj);
if ($iExtKey == 0)
{
$iExtKey = -$iDstObj; // Convention: Unresolved keys are stored as negative !
$oTargetObj->RegisterAsDirty();
}
// here we allow external keys to be invalid because we will resolve them later on...
}
//$oTargetObj->CheckValue($sAttCode, $iExtKey);
$oTargetObj->Set($sAttCode, $iExtKey);
}
elseif ($oAttDef instanceof AttributeBlob)
{
$sMimeType = (string) $oSubNode->mimetype;
$sFileName = (string) $oSubNode->filename;
$data = base64_decode((string) $oSubNode->data);
$oDoc = new ormDocument($data, $sMimeType, $sFileName);
$oTargetObj->Set($sAttCode, $oDoc);
}
else
{
$value = (string)$oSubNode;
if ($value == '')
{
$value = $oAttDef->GetNullValue();
}
$res = $oTargetObj->CheckValue($sAttCode, $value);
if ($res !== true)
{
// $res contains the error description
$sMsg = "Value not allowed - $sClass/$iSrcId - $sAttCode: '".$oSubNode."' ; $res";
SetupPage::log_error($sMsg);
$this->m_aErrors[] = $sMsg;
}
$oTargetObj->Set($sAttCode, $value);
}
}
}
$this->StoreObject($sClass, $oTargetObj, $iSrcId, $bUpdateKeyCacheOnly, $bUpdateKeyCacheOnly);
}
return true;
}
/**
* Get the new ID of an object in the database given its original ID
* This may fail (return 0) if the object has not yet been created in the database
* This is why the order of the import may be important
*/
protected function GetObjectKey($sClass, $iSrcId)
{
if (isset($this->m_aKeys[$sClass]) && isset($this->m_aKeys[$sClass][$iSrcId]))
{
return $this->m_aKeys[$sClass][$iSrcId];
}
return 0;
}
/**
* Store an object in the database and remember the mapping
* between its original ID and the newly created ID in the database
*/
protected function StoreObject($sClass, $oTargetObj, $iSrcId, $bSearch = false, $bUpdateKeyCacheOnly = false)
{
$iObjId = 0;
try
{
if ($bSearch)
{
// Check if the object does not already exist, based on its usual reconciliation keys...
$aReconciliationKeys = MetaModel::GetReconcKeys($sClass);
if (count($aReconciliationKeys) > 0)
{
// Some reconciliation keys have been defined, use them to search for the object
$oSearch = new DBObjectSearch($sClass);
$iConditionsCount = 0;
foreach($aReconciliationKeys as $sAttCode)
{
if ($oTargetObj->Get($sAttCode) != '')
{
$oSearch->AddCondition($sAttCode, $oTargetObj->Get($sAttCode), '=');
$iConditionsCount++;
}
}
if ($iConditionsCount > 0) // Search only if there are some valid conditions...
{
$oSet = new DBObjectSet($oSearch);
if ($oSet->count() == 1)
{
// The object already exists, reuse it
$oExistingObject = $oSet->Fetch();
$iObjId = $oExistingObject->GetKey();
}
}
}
}
if ($iObjId == 0)
{
if($oTargetObj->IsNew())
{
if (!$bUpdateKeyCacheOnly)
{
$iObjId = $oTargetObj->DBInsertNoReload();
$this->m_iCountCreated++;
}
}
else
{
$iObjId = $oTargetObj->GetKey();
if (!$bUpdateKeyCacheOnly)
{
$oTargetObj->DBUpdate();
}
}
}
}
catch(Exception $e)
{
SetupPage::log_error("An object could not be recorded - $sClass/$iSrcId - ".$e->getMessage());
$this->m_aErrors[] = "An object could not be recorded - $sClass/$iSrcId - ".$e->getMessage();
}
$aParentClasses = MetaModel::EnumParentClasses($sClass);
$aParentClasses[] = $sClass;
foreach($aParentClasses as $sObjClass)
{
$this->m_aKeys[$sObjClass][$iSrcId] = $iObjId;
}
$this->m_aObjectsCache[$sClass][$iObjId] = $oTargetObj;
}
/**
* Maps an external key to its (newly created) value
*/
protected function ResolveExternalKeys()
{
foreach($this->m_aObjectsCache as $sClass => $oObjList)
{
foreach($oObjList as $oTargetObj)
{
$bChanged = false;
$sClass = get_class($oTargetObj);
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef)
{
if ( ($oAttDef->IsExternalKey()) && ($oTargetObj->Get($sAttCode) < 0) ) // Convention unresolved key = negative
{
$sTargetClass = $oAttDef->GetTargetClass();
$iTempKey = $oTargetObj->Get($sAttCode);
$iExtKey = $this->GetObjectKey($sTargetClass, -$iTempKey);
if ($iExtKey == 0)
{
$sMsg = "unresolved extkey in $sClass::".$oTargetObj->GetKey()."(".$oTargetObj->GetName().")::$sAttCode=$sTargetClass::$iTempKey";
SetupPage::log_warning($sMsg);
$this->m_aWarnings[] = $sMsg;
//echo "<pre>aKeys[".$sTargetClass."]:\n";
//print_r($this->m_aKeys[$sTargetClass]);
//echo "</pre>\n";
}
else
{
$bChanged = true;
$oTargetObj->Set($sAttCode, $iExtKey);
}
}
}
if ($bChanged)
{
try
{
if (is_subclass_of($oTargetObj, 'CMDBObject'))
{
$oTargetObj->DBUpdateTracked($this->m_oChange);
}
else
{
$oTargetObj->DBUpdate();
}
}
catch(Exception $e)
{
$this->m_aErrors[] = "The object changes could not be tracked - $sClass/$iExtKey - ".$e->getMessage();
}
}
}
}
return true;
}
}
?>
<?php
// Copyright (C) 2010-2012 Combodo SARL
//
// This file is part of iTop.
//
// 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.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* Load XML data from a set of files
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
define ('KEYS_CACHE_FILE', APPROOT.'data/keyscache.tmp');
/**
* Class to load sets of objects from XML files into the database
* XML files can be produced by the 'export' web service or by any other means
* Here is a simple example:
* $oLoader = new XMLDataLoader('../itop-config.php');
* $oLoader->StartSession();
* $oLoader->LoadFile('./organizations.xml');
* $oLoader->LoadFile('./locations.xml');
* $oLoader->EndSession();
*/
class XMLDataLoader
{
protected $m_aKeys;
protected $m_aObjectsCache;
protected $m_bSessionActive;
protected $m_oChange;
protected $m_sCacheFileName;
protected $m_aErrors;
protected $m_aWarnings;
protected $m_iCountCreated;
public function __construct()
{
$this->m_aKeys = array();
$this->m_aObjectsCache = array();
$this->m_oChange = null;
$this->m_sCacheFileName = KEYS_CACHE_FILE;
$this->LoadKeysCache();
$this->m_bSessionActive = true;
$this->m_aErrors = array();
$this->m_aWarnings = array();
$this->m_iCountCreated = 0;
}
public function StartSession($oChange)
{
// Do cleanup any existing cache file (shall not be necessary unless a setup was interrupted abruptely)
$this->ClearKeysCache();
$this->m_oChange = $oChange;
$this->m_bSessionActive = true;
}
public function EndSession($bStrict = false)
{
$this->ResolveExternalKeys();
$this->m_bSessionActive = false;
if (count($this->m_aErrors) > 0)
{
return false;
}
elseif ($bStrict && count($this->m_aWarnings) > 0)
{
return false;
}
else
{
return true;
}
}
public function GetErrors()
{
return $this->m_aErrors;
}
public function GetWarnings()
{
return $this->m_aWarnings;
}
public function GetCountCreated()
{
return $this->m_iCountCreated;
}
public function __destruct()
{
// Stopping in the middle of a session, let's save the context information
if ($this->m_bSessionActive)
{
$this->SaveKeysCache();
}
else
{
$this->ClearKeysCache();
}
}
/**
* Stores the keys & object cache in a file
*/
protected function SaveKeysCache()
{
if (!is_dir(APPROOT.'data'))
{
mkdir(APPROOT.'data');
}
$hFile = @fopen($this->m_sCacheFileName, 'w');
if ($hFile !== false)
{
$sData = serialize( array('keys' => $this->m_aKeys,
'objects' => $this->m_aObjectsCache,
'change' => $this->m_oChange,
'errors' => $this->m_aErrors,
'warnings' => $this->m_aWarnings,
));
fwrite($hFile, $sData);
fclose($hFile);
}
else
{
throw new Exception("Cannot write to file: '{$this->m_sCacheFileName}'");
}
}
/**
* Loads the keys & object cache from the tmp file
*/
protected function LoadKeysCache()
{
$sFileContent = @file_get_contents($this->m_sCacheFileName);
if (!empty($sFileContent))
{
$aCache = unserialize($sFileContent);
$this->m_aKeys = $aCache['keys'];
$this->m_aObjectsCache = $aCache['objects'];
$this->m_oChange = $aCache['change'];
$this->m_aErrors = $aCache['errors'];
$this->m_aWarnings = $aCache['warnings'];
}
}
/**
* Remove the tmp file used to store the keys cache
*/
protected function ClearKeysCache()
{
if(is_file($this->m_sCacheFileName))
{
unlink($this->m_sCacheFileName);
}
else
{
//echo "<p>Hm, it looks like the file does not exist!!!</p>";
}
$this->m_aKeys = array();
$this->m_aObjectsCache = array();
}
/**
* Helper function to load the objects from a standard XML file into the database
* @param $sFilePath string The full path to the XML file to load
* @param $bUpdateKeyCacheOnly bool Set to true to *just* update the keys cache but not reload the objects
*/
function LoadFile($sFilePath, $bUpdateKeyCacheOnly = false)
{
global $aKeys;
$oXml = simplexml_load_file($sFilePath);
$aReplicas = array();
foreach($oXml as $sClass => $oXmlObj)
{
if (!MetaModel::IsValidClass($sClass))
{
SetupPage::log_error("Unknown class - $sClass");
throw(new Exception("Unknown class - $sClass"));
}
$iSrcId = (integer)$oXmlObj['id']; // Mandatory to cast
// Import algorithm
// Here enumerate all the attributes of the object
// for all attribute that is neither an external field
// not an external key, assign it
// Store all external keys for further reference
// Create the object an store the correspondance between its newly created Id
// and its original Id
// Once all the objects have been created re-assign all the external keys to
// their actual Ids
$iExistingId = $this->GetObjectKey($sClass, $iSrcId);
if ($iExistingId != 0)
{
$oTargetObj = MetaModel::GetObject($sClass, $iExistingId);
}
else
{
$oTargetObj = MetaModel::NewObject($sClass);
}
foreach($oXmlObj as $sAttCode => $oSubNode)
{
if (!MetaModel::IsValidAttCode($sClass, $sAttCode))
{
$sMsg = "Unknown attribute code - $sClass/$sAttCode";
continue; // ignore silently...
//SetupPage::log_error($sMsg);
//throw(new Exception($sMsg));
}
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if (($oAttDef->IsWritable()) && ($oAttDef->IsScalar()))
{
if ($oAttDef->IsExternalKey())
{
if (substr(trim($oSubNode), 0, 6) == 'SELECT')
{
$sQuery = trim($oSubNode);
$oSet = new DBObjectSet(DBObjectSearch::FromOQL($sQuery));
$iMatches = $oSet->Count();
if ($iMatches == 1)
{
$oFoundObject = $oSet->Fetch();
$iExtKey = $oFoundObject->GetKey();
}
else
{
$sMsg = "Ext key not reconcilied - $sClass/$iSrcId - $sAttCode: '".$sQuery."' - found $iMatches matche(s)";
SetupPage::log_error($sMsg);
$this->m_aErrors[] = $sMsg;
$iExtKey = 0;
}
}
else
{
$iDstObj = (integer)($oSubNode);
// Attempt to find the object in the list of loaded objects
$iExtKey = $this->GetObjectKey($oAttDef->GetTargetClass(), $iDstObj);
if ($iExtKey == 0)
{
$iExtKey = -$iDstObj; // Convention: Unresolved keys are stored as negative !
$oTargetObj->RegisterAsDirty();
}
// here we allow external keys to be invalid because we will resolve them later on...
}
//$oTargetObj->CheckValue($sAttCode, $iExtKey);
$oTargetObj->Set($sAttCode, $iExtKey);
}
elseif ($oAttDef instanceof AttributeBlob)
{
$sMimeType = (string) $oSubNode->mimetype;
$sFileName = (string) $oSubNode->filename;
$data = base64_decode((string) $oSubNode->data);
$oDoc = new ormDocument($data, $sMimeType, $sFileName);
$oTargetObj->Set($sAttCode, $oDoc);
}
else
{
$value = (string)$oSubNode;
if ($value == '')
{
$value = $oAttDef->GetNullValue();
}
$res = $oTargetObj->CheckValue($sAttCode, $value);
if ($res !== true)
{
// $res contains the error description
$sMsg = "Value not allowed - $sClass/$iSrcId - $sAttCode: '".$oSubNode."' ; $res";
SetupPage::log_error($sMsg);
$this->m_aErrors[] = $sMsg;
}
$oTargetObj->Set($sAttCode, $value);
}
}
}
$this->StoreObject($sClass, $oTargetObj, $iSrcId, $bUpdateKeyCacheOnly, $bUpdateKeyCacheOnly);
}
return true;
}
/**
* Get the new ID of an object in the database given its original ID
* This may fail (return 0) if the object has not yet been created in the database
* This is why the order of the import may be important
*/
protected function GetObjectKey($sClass, $iSrcId)
{
if (isset($this->m_aKeys[$sClass]) && isset($this->m_aKeys[$sClass][$iSrcId]))
{
return $this->m_aKeys[$sClass][$iSrcId];
}
return 0;
}
/**
* Store an object in the database and remember the mapping
* between its original ID and the newly created ID in the database
*/
protected function StoreObject($sClass, $oTargetObj, $iSrcId, $bSearch = false, $bUpdateKeyCacheOnly = false)
{
$iObjId = 0;
try
{
if ($bSearch)
{
// Check if the object does not already exist, based on its usual reconciliation keys...
$aReconciliationKeys = MetaModel::GetReconcKeys($sClass);
if (count($aReconciliationKeys) > 0)
{
// Some reconciliation keys have been defined, use them to search for the object
$oSearch = new DBObjectSearch($sClass);
$iConditionsCount = 0;
foreach($aReconciliationKeys as $sAttCode)
{
if ($oTargetObj->Get($sAttCode) != '')
{
$oSearch->AddCondition($sAttCode, $oTargetObj->Get($sAttCode), '=');
$iConditionsCount++;
}
}
if ($iConditionsCount > 0) // Search only if there are some valid conditions...
{
$oSet = new DBObjectSet($oSearch);
if ($oSet->count() == 1)
{
// The object already exists, reuse it
$oExistingObject = $oSet->Fetch();
$iObjId = $oExistingObject->GetKey();
}
}
}
}
if ($iObjId == 0)
{
if($oTargetObj->IsNew())
{
if (!$bUpdateKeyCacheOnly)
{
$iObjId = $oTargetObj->DBInsertNoReload();
$this->m_iCountCreated++;
}
}
else
{
$iObjId = $oTargetObj->GetKey();
if (!$bUpdateKeyCacheOnly)
{
$oTargetObj->DBUpdate();
}
}
}
}
catch(Exception $e)
{
SetupPage::log_error("An object could not be recorded - $sClass/$iSrcId - ".$e->getMessage());
$this->m_aErrors[] = "An object could not be recorded - $sClass/$iSrcId - ".$e->getMessage();
}
$aParentClasses = MetaModel::EnumParentClasses($sClass);
$aParentClasses[] = $sClass;
foreach($aParentClasses as $sObjClass)
{
$this->m_aKeys[$sObjClass][$iSrcId] = $iObjId;
}
$this->m_aObjectsCache[$sClass][$iObjId] = $oTargetObj;
}
/**
* Maps an external key to its (newly created) value
*/
protected function ResolveExternalKeys()
{
foreach($this->m_aObjectsCache as $sClass => $oObjList)
{
foreach($oObjList as $oTargetObj)
{
$bChanged = false;
$sClass = get_class($oTargetObj);
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef)
{
if ( ($oAttDef->IsExternalKey()) && ($oTargetObj->Get($sAttCode) < 0) ) // Convention unresolved key = negative
{
$sTargetClass = $oAttDef->GetTargetClass();
$iTempKey = $oTargetObj->Get($sAttCode);
$iExtKey = $this->GetObjectKey($sTargetClass, -$iTempKey);
if ($iExtKey == 0)
{
$sMsg = "unresolved extkey in $sClass::".$oTargetObj->GetKey()."(".$oTargetObj->GetName().")::$sAttCode=$sTargetClass::$iTempKey";
SetupPage::log_warning($sMsg);
$this->m_aWarnings[] = $sMsg;
//echo "<pre>aKeys[".$sTargetClass."]:\n";
//print_r($this->m_aKeys[$sTargetClass]);
//echo "</pre>\n";
}
else
{
$bChanged = true;
$oTargetObj->Set($sAttCode, $iExtKey);
}
}
}
if ($bChanged)
{
try
{
if (is_subclass_of($oTargetObj, 'CMDBObject'))
{
$oTargetObj->DBUpdateTracked($this->m_oChange);
}
else
{
$oTargetObj->DBUpdate();
}
}
catch(Exception $e)
{
$this->m_aErrors[] = "The object changes could not be tracked - $sClass/$iExtKey - ".$e->getMessage();
}
}
}
}
return true;
}
}
?>