Compare commits

..

1 Commits

Author SHA1 Message Date
bruno-ds
80cb3a11db [WIP][POC] the PhpUnit tests can now build and use various environments
drawbacks: the application startup was emulated since it is not compatible with a custom env. when launched with the CLI (it rely on the session in an incompatible way)
2021-04-09 17:29:18 +02:00
140 changed files with 2104 additions and 3238 deletions

View File

@@ -90,7 +90,7 @@ ij_xml_attribute_wrap = normal
ij_xml_block_comment_at_first_column = true
ij_xml_keep_blank_lines = 2
ij_xml_keep_indents_on_empty_lines = false
ij_xml_keep_line_breaks = true
ij_xml_keep_line_breaks = false
ij_xml_keep_line_breaks_in_text = true
ij_xml_keep_whitespaces = false
ij_xml_keep_whitespaces_around_cdata = preserve
@@ -110,7 +110,6 @@ ij_shell_keep_column_alignment_padding = false
ij_shell_minify_program = false
ij_shell_redirect_followed_by_space = false
ij_shell_switch_cases_indented = false
ij_shell_use_unix_line_separator = true
[{*.cjs,*.js}]
indent_style = tab
@@ -280,17 +279,17 @@ ij_javascript_while_brace_force = always
ij_javascript_while_on_new_line = false
ij_javascript_wrap_comments = false
[{*.ctp, *.hphp, *.inc, *.module, *.php, *.php4, *.php5, *.phtml}]
[{*.ctp,*.hphp,*.inc,*.module,*.php,*.php4,*.php5,*.phtml}]
indent_style = tab
ij_continuation_indent_size = 4
ij_smart_tabs = true
ij_wrap_on_typing = false
ij_php_align_assignments = true
ij_php_align_assignments = false
ij_php_align_class_constants = false
ij_php_align_group_field_declarations = false
ij_php_align_inline_comments = false
ij_php_align_key_value_pairs = true
ij_php_align_multiline_array_initializer_expression = true
ij_php_align_key_value_pairs = false
ij_php_align_multiline_array_initializer_expression = false
ij_php_align_multiline_binary_operation = false
ij_php_align_multiline_chained_methods = false
ij_php_align_multiline_extends_list = false
@@ -515,7 +514,7 @@ ij_json_wrap_long_lines = false
indent_style = tab
ij_smart_tabs = true
ij_visual_guides = none
ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
ij_html_add_new_line_before_tags = body, div, p, form, h1, h2, h3
ij_html_align_attributes = true
ij_html_align_text = false
ij_html_attribute_wrap = normal
@@ -542,21 +541,7 @@ ij_html_space_inside_empty_tag = false
ij_html_text_wrap = normal
ij_html_uniform_ident = false
[{*.markdown,*.md}]
ij_visual_guides = none
ij_markdown_force_one_space_after_blockquote_symbol = true
ij_markdown_force_one_space_after_header_symbol = true
ij_markdown_force_one_space_after_list_bullet = true
ij_markdown_force_one_space_between_words = true
ij_markdown_keep_indents_on_empty_lines = false
ij_markdown_max_lines_around_block_elements = 1
ij_markdown_max_lines_around_header = 1
ij_markdown_max_lines_between_paragraphs = 1
ij_markdown_min_lines_around_block_elements = 1
ij_markdown_min_lines_around_header = 1
ij_markdown_min_lines_between_paragraphs = 1
[{*.yaml,*.yml}]
[{*.yaml, *.yml}]
indent_size = 2
ij_visual_guides = none
ij_yaml_align_values_properties = do_not_align

View File

@@ -1,22 +1,7 @@
<?php
/**
* script used to sort license file (useful for autogeneration)
*
* Requirements :
* * bash (on Windows, use Git Bash)
* * composer (if you use the phar version, mind to create a `Composer` alias !)
* * JQ command
* to install on Windows :
* `curl -L -o /usr/bin/jq.exe https://github.com/stedolan/jq/releases/latest/download/jq-win64.exe`
* this is a Windows port : https://stedolan.github.io/jq/
*
* Licenses sources :
* * `composer licenses --format json` (see https://getcomposer.org/doc/03-cli.md#licenses)
* * keep every existing nodes with `/licenses/license[11]/product/@scope` not in ['lib', 'datamodels']
* ⚠ If licenses were added manually, they might be removed by this tool ! Be very careful to check for the result before pushing !
*
* To launch, check requirements and run `php updateLicenses.php`
* The target license file path is in `$xmlFilePath`
* script used to sort license file (usefull for autogeneration)
* Example: php
*/
$iTopFolder = __DIR__ . "/../../" ;
@@ -66,83 +51,39 @@ function get_license_nodes($file_path)
$xp = new DOMXPath($dom);
$licenseList = $xp->query('/licenses/license');
$licenses = iterator_to_array($licenseList);
$licenses = iterator_to_array($licenseList);
usort($licenses, 'sort_by_product');
return $licenses;
}
/** @noinspection SuspiciousAssignmentsInspection */
function fix_product_name(DOMNode &$oProductNode)
{
$sProductNameOrig = $oProductNode->nodeValue;
// sample : `C:\Dev\wamp64\www\itop-27\.make\license/../..//lib/symfony/polyfill-ctype`
$sProductNameFixed = remove_dir_from_string($sProductNameOrig, 'lib/');
// sample : `C:\Dev\wamp64\www\itop-27\.make\license/../..//datamodels/2.x/authent-cas/vendor/apereo/phpcas`
$sProductNameFixed = remove_dir_from_string($sProductNameFixed, 'vendor/');
$oProductNode->nodeValue = $sProductNameFixed;
}
function remove_dir_from_string($sString, $sNeedle)
{
if (strpos($sString, $sNeedle) === false) {
return $sString;
}
$sStringTmp = strstr($sString, $sNeedle);
$sStringFixed = str_replace($sNeedle, '', $sStringTmp);
// DEBUG trace O:)
// echo "$sNeedle = $sString => $sStringFixed\n";
return $sStringFixed;
}
$old_licenses = get_license_nodes($xmlFilePath);
//generate file with updated licenses
$generated_license_file_path = __DIR__."/provfile.xml";
echo "- Generating licences...";
exec("bash ".__DIR__."/gen-community-license.sh $iTopFolder > ".$generated_license_file_path);
echo "OK!\n";
echo "- Get licenses nodes...";
exec("bash " . __DIR__ . "/gen-community-license.sh $iTopFolder > ". $generated_license_file_path);
$new_licenses = get_license_nodes($generated_license_file_path);
unlink($generated_license_file_path);
exec("rm -f ". $generated_license_file_path);
foreach ($old_licenses as $b) {
$aProductNode = get_product_node($b);
if (get_scope($aProductNode) !== "lib" && get_scope($aProductNode) !== "datamodels") {
if (get_scope($aProductNode) !== "lib" && get_scope($aProductNode) !== "datamodels" )
{
$new_licenses[] = $b;
}
}
usort($new_licenses, 'sort_by_product');
echo "OK!\n";
echo "- Overwritting Combodo license file...";
$new_dom = new DOMDocument("1.0");
$new_dom->formatOutput = true;
$root = $new_dom->createElement("licenses");
$new_dom->appendChild($root);
foreach ($new_licenses as $b) {
$node = $new_dom->importNode($b, true);
// N°3870 fix when running script in Windows
// fix should be in gen-community-license.sh but it is easier to do it here !
if (strncasecmp(PHP_OS, 'WIN', 3) === 0) {
$oProductNodeOrig = get_product_node($node);
fix_product_name($oProductNodeOrig);
}
$root->appendChild($node);
$node = $new_dom->importNode($b,true);
$root->appendChild($new_dom->importNode($b,true));
}
$new_dom->save($xmlFilePath);
echo "OK!\n";
$new_dom->save($xmlFilePath);

View File

@@ -1,77 +0,0 @@
<?php
/**
* Usage :
* `php changelog.php 2.7.4`
*
* As argument is passed the git ref (tag name or sha1) we want to use as reference
*
* Outputs :
*
* 1. List of bugs as CSV :
* bug ref;link
* Example :
* <code>
* Bug_ref;Bug_URL;sha1
* 1234;https://support.combodo.com/pages/UI.php?operation=details&class=Bug&id=1234;949b213f9|b1ca1f263|a1271da74
* </code>
*
* 2. List of commits sha1/message without bug ref
* Example :
* <code>
* sha1;subject
* a6aa183e2;:bookmark: Prepare 2.7.5
* </code>
*/
if (count($argv) === 1) {
echo '⚠ You must pass the base tag/sha1 as parameter';
exit(1);
}
$sBaseReference = $argv[1];
//--- Get log
$sGitLogCommand = 'git log --decorate --pretty="%h;%s" --date-order --no-merges '.$sBaseReference.'..HEAD';
$sGitLogRaw = shell_exec($sGitLogCommand);
//--- Analyze log
$aGitLogLines = preg_split('/\n/', trim($sGitLogRaw));;
$aLogLinesWithBugRef = [];
$aLogLineNoBug = [];
foreach ($aGitLogLines as $sLogLine) {
$sBugRef = preg_match('/[nN]°(\d{3,4})/', $sLogLine, $aLineBugRef);
if (($sBugRef === false) || empty($aLineBugRef)) {
$aLogLineNoBug[] = $sLogLine;
continue;
}
$iBugId = $aLineBugRef[1];
$sSha = substr($sLogLine, 0, 9);
if (array_key_exists($iBugId, $aLogLinesWithBugRef)) {
$aBugShaRefs = $aLogLinesWithBugRef[$iBugId];
$aBugShaRefs[] = $sSha;
$aLogLinesWithBugRef[$iBugId] = $aBugShaRefs;
} else {
$aLogLinesWithBugRef[$iBugId] = [$sSha];
}
}
$aBugsList = array_keys($aLogLinesWithBugRef);
sort($aBugsList, SORT_NUMERIC);
//-- Output results
echo "# Bugs included\n";
echo "Bug_ref;Bug_URL;sha1\n";
foreach ($aBugsList as $sBugRef) {
$sShaRefs = implode('|', $aLogLinesWithBugRef[$sBugRef]);
echo "{$sBugRef};https://support.combodo.com/pages/UI.php?operation=details&class=Bug&id={$sBugRef};$sShaRefs\n";
}
echo "\n";
echo "# Logs line without bug referenced\n";
echo "sha1;subject\n";
foreach ($aLogLineNoBug as $sLogLine) {
echo "$sLogLine\n";
}

View File

@@ -123,9 +123,8 @@ We would like to give a special thank you to the people from the community who c
- Lassiter, Dennis
- Lazcano, Federico
- Lucas, Jonathan
- Malik, Remie
- Mindêllo de Andrade, Lucas (a.k.a @rokam)
- Rosenke, Stephan
- Malik, Remie
- Rosenke, Stephan
- Seki, Shoji
- Shilov, Vladimir
- Tulio, Marco

View File

@@ -72,14 +72,15 @@ abstract class AbstractLoginFSMExtension implements iLoginFSMExtension
/**
* @inheritDoc
*/
abstract public function ListSupportedLoginModes();
public abstract function ListSupportedLoginModes();
/**
* @inheritDoc
*/
public function LoginAction($sLoginState, &$iErrorCode)
{
switch ($sLoginState) {
switch ($sLoginState)
{
case LoginWebPage::LOGIN_STATE_START:
return $this->OnStart($iErrorCode);

View File

@@ -354,15 +354,14 @@ JS
);
// Highlight code content created with CKEditor
// Note: We check for the <code> tag inside the <pre> tag to only target code from CKEditor, otherwise we might highlight some others things. See N°3810
$this->add_ready_script(
<<<JS
// Highlight code content for HTML AttributeText
$("[data-attribute-type='AttributeText'] .HTML pre > code").parent().each(function(i, block) {
$("[data-attribute-type='AttributeText'] .HTML pre").each(function(i, block) {
hljs.highlightBlock(block);
});
// Highlight code content for CaseLogs
$("[data-attribute-type='AttributeCaseLog'] .caselog_entry_html pre > code").parent().each(function(i, block) {
$("[data-attribute-type='AttributeCaseLog'] .caselog_entry_html pre").each(function(i, block) {
hljs.highlightBlock(block);
});
JS

View File

@@ -45,7 +45,7 @@ register_shutdown_function(function()
$sMessage = substr($sMessage, 0, $iStackTracePos);
}
}
IssueLog::error($sMessage, null, $err);
IssueLog::error($sMessage);
if (strpos($err['message'], 'Allowed memory size of') !== false)
{
$sLimit = ini_get('memory_limit');

View File

@@ -563,93 +563,48 @@ class utils
public static function ReadFromFile($sFileName)
{
if (!file_exists($sFileName)) {
return false;
}
if (!file_exists($sFileName)) return false;
return file_get_contents($sFileName);
}
/**
* @param mixed $value The value as read from php.ini (eg 256k, 2M, 1G etc.)
*
* @return int conversion to number of bytes
*
* @since 2.7.5 3.0.0 convert to int numeric values
*
* @link https://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes Shorthand bytes value reference in PHP.net FAQ
* Helper function to convert a value expressed in a 'user friendly format'
* as in php.ini, e.g. 256k, 2M, 1G etc. Into a number of bytes
* @param mixed $value The value as read from php.ini
* @return number
*/
public static function ConvertToBytes($value)
public static function ConvertToBytes( $value )
{
if (!is_numeric($value)) {
$iLength = strlen($value);
$iReturn = substr($value, 0, $iLength - 1);
$sUnit = strtoupper(substr($value, $iLength - 1));
switch ($sUnit) {
case 'G':
$iReturn *= 1024;
case 'M':
$iReturn *= 1024;
case 'K':
$iReturn *= 1024;
}
} else {
$iReturn = (int)$value;
}
return $iReturn;
}
/**
* Checks if the memory limit is at least what is required
*
* @param int $iMemoryLimit set limit in bytes, use {@link utils::ConvertToBytes()} to convert current php.ini value
* @param int $iRequiredLimit required limit in bytes
*
* @return bool
*/
public static function IsMemoryLimitOk($iMemoryLimit, $iRequiredLimit)
{
if ($iMemoryLimit === -1) {
// -1 means : no limit (see https://www.php.net/manual/fr/ini.core.php#ini.memory-limit)
return true;
}
return ($iMemoryLimit >= $iRequiredLimit);
}
/**
* Set memory_limit to required value
*
* @param string $sRequiredLimit required limit, for example '512M'
*
* @return bool|null null if nothing was done, true if modifying memory_limit was successful, false otherwise
*
* @uses utils::ConvertToBytes()
* @uses \ini_get('memory_limit')
* @uses \ini_set()
* @uses utils::ConvertToBytes()
*
* @since 2.7.5 N°3806
*/
public static function SetMinMemoryLimit($sRequiredLimit)
{
$iRequiredLimit = static::ConvertToBytes($sRequiredLimit);
$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
return false;
}
$iMemoryLimit = static::ConvertToBytes($sMemoryLimit);
if (static::IsMemoryLimitOk($iMemoryLimit, $iRequiredLimit)) {
return null;
}
return ini_set('memory_limit', $iRequiredLimit);
}
$iReturn = $value;
if ( !is_numeric( $value ) )
{
$iLength = strlen( $value );
$iReturn = substr( $value, 0, $iLength - 1 );
$sUnit = strtoupper( substr( $value, $iLength - 1 ) );
switch ( $sUnit )
{
case 'G':
$iReturn *= 1024;
case 'M':
$iReturn *= 1024;
case 'K':
$iReturn *= 1024;
}
}
return $iReturn;
}
/**
* Checks if the memory limit is at least what is required
*
* @param int $memoryLimit set limit in bytes
* @param int $requiredLimit required limit in bytes
* @return bool
*/
public static function IsMemoryLimitOk($memoryLimit, $requiredLimit)
{
return ($memoryLimit >= $requiredLimit) || ($memoryLimit == -1);
}
/**
* Format a value into a more friendly format (KB, MB, GB, TB) instead a juste a Bytes amount.
@@ -778,7 +733,7 @@ class utils
* @throws \ConfigException
* @throws \CoreException
*
* @since 2.7.0 N°2478 this method will now always call {@link MetaModel::GetConfig} first, and cache in this class is only set when loading from disk
* @since 2.7.0 N°2478 always call {@link MetaModel::GetConfig} first, cache is only set when loading from disk
*/
public static function GetConfig()
{

View File

@@ -12,7 +12,7 @@
"ext-soap": "*",
"combodo/tcpdf": "6.3.5",
"nikic/php-parser": "^3.1",
"pear/archive_tar": "1.4.13",
"pear/archive_tar": "1.4.10",
"pelago/emogrifier": "2.1.0",
"scssphp/scssphp": "1.0.6",
"swiftmailer/swiftmailer": "5.4.12",

26
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "8c7f3127435b1afb67965369c50d0898",
"content-hash": "27af144ea2acf2c138f587052a4ceddc",
"packages": [
{
"name": "combodo/tcpdf",
@@ -168,16 +168,16 @@
},
{
"name": "pear/archive_tar",
"version": "1.4.13",
"version": "1.4.10",
"source": {
"type": "git",
"url": "https://github.com/pear/Archive_Tar.git",
"reference": "2b87b41178cc6d4ad3cba678a46a1cae49786011"
"reference": "bbb4f10f71a1da2715ec6d9a683f4f23c507a49b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pear/Archive_Tar/zipball/2b87b41178cc6d4ad3cba678a46a1cae49786011",
"reference": "2b87b41178cc6d4ad3cba678a46a1cae49786011",
"url": "https://api.github.com/repos/pear/Archive_Tar/zipball/bbb4f10f71a1da2715ec6d9a683f4f23c507a49b",
"reference": "bbb4f10f71a1da2715ec6d9a683f4f23c507a49b",
"shasum": ""
},
"require": {
@@ -230,21 +230,7 @@
"archive",
"tar"
],
"support": {
"issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Archive_Tar",
"source": "https://github.com/pear/Archive_Tar"
},
"funding": [
{
"url": "https://github.com/mrook",
"type": "github"
},
{
"url": "https://www.patreon.com/michielrook",
"type": "patreon"
}
],
"time": "2021-02-16T10:50:50+00:00"
"time": "2020-09-15T14:13:23+00:00"
},
{
"name": "pear/console_getopt",

View File

@@ -39,7 +39,6 @@ class MySQLException extends CoreException
*/
public function __construct($sIssue, $aContext, $oException = null, $oMysqli = null)
{
if ($oException != null)
{
$aContext['mysql_errno'] = $oException->getCode();
@@ -59,11 +58,6 @@ class MySQLException extends CoreException
$aContext['mysql_error'] = CMDBSource::GetError();
}
parent::__construct($sIssue, $aContext);
//if is connection error, don't log the default message with password in
if (mysqli_connect_errno()) {
error_log($this->message);
error_reporting(0);
}
}
}
@@ -154,7 +148,6 @@ class CMDBSource
/** @var mysqli $m_oMysqli */
protected static $m_oMysqli;
protected static $oMySQLiForQuery;
/**
* @var int number of level for nested transactions : 0 if no transaction was ever opened, +1 for each 'START TRANSACTION' sent
@@ -221,7 +214,6 @@ class CMDBSource
self::$m_sDBTlsCA = empty($sTlsCA) ? null : $sTlsCA;
self::$m_oMysqli = self::GetMysqliInstance($sServer, $sUser, $sPwd, $sSource, $bTlsEnabled, $sTlsCA, true);
self::SetMySQLiForQuery(self::$m_oMysqli);
}
/**
@@ -239,6 +231,8 @@ class CMDBSource
public static function GetMysqliInstance(
$sDbHost, $sUser, $sPwd, $sSource = '', $bTlsEnabled = false, $sTlsCa = null, $bCheckTlsAfterConnection = false
) {
$oMysqli = null;
$sServer = null;
$iPort = null;
self::InitServerAndPort($sDbHost, $sServer, $iPort);
@@ -268,7 +262,7 @@ class CMDBSource
}
catch(mysqli_sql_exception $e)
{
throw new MySQLException('Could not connect to the DB server', array('host' => $sServer, 'user' => $sUser),$e);
throw new MySQLException('Could not connect to the DB server', array('host' => $sServer, 'user' => $sUser), $e);
}
if ($bTlsEnabled
@@ -536,24 +530,6 @@ class CMDBSource
return self::$m_oMysqli;
}
/**
* @return
*/
private static function GetMySQLiForQuery()
{
return self::$oMySQLiForQuery;
}
/**
* Used for test purpose (mysqli mock)
* @param $oMySQLi
*/
private static function SetMySQLiForQuery($oMySQLi)
{
self::$oMySQLiForQuery = $oMySQLi;
}
public static function GetErrNo()
{
if (self::$m_oMysqli->errno != 0)
@@ -689,15 +665,10 @@ class CMDBSource
*/
private static function DBQuery($sSql)
{
$sShortSQL = substr(preg_replace("/\s+/", " ", substr($sSql, 0, 180)), 0, 150);
if (substr_compare($sShortSQL, "SELECT", 0, strlen("SELECT")) !== 0) {
IssueLog::Trace("$sShortSQL", 'cmdbsource');
}
$oKPI = new ExecutionKPI();
try
{
$oResult = self::GetMySQLiForQuery()->query($sSql);
$oResult = self::$m_oMysqli->query($sSql);
}
catch (mysqli_sql_exception $e)
{
@@ -761,7 +732,7 @@ class CMDBSource
);
DeadLockLog::Info($sMessage, $iMySqlErrorNo, $aLogContext);
IssueLog::Error($sMessage, LogChannels::DEADLOCK, $e->getMessage());
IssueLog::Error($sMessage, 'DeadLock', $e->getMessage());
}
/**
@@ -777,15 +748,10 @@ class CMDBSource
*/
private static function StartTransaction()
{
$aStackTrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT , 3);
$sCaller = 'From '.$aStackTrace[1]['file'].'('.$aStackTrace[1]['line'].'): '.$aStackTrace[2]['class'].'->'.$aStackTrace[2]['function'].'()';
$bHasExistingTransactions = self::IsInsideTransaction();
if (!$bHasExistingTransactions)
{
IssueLog::Trace("START TRANSACTION $sCaller", 'cmdbsource');
self::DBQuery('START TRANSACTION');
} else {
IssueLog::Trace("Ignore nested (".self::$m_iTransactionLevel.") START TRANSACTION $sCaller", 'cmdbsource');
}
self::AddTransactionLevel();
@@ -803,12 +769,9 @@ class CMDBSource
*/
private static function Commit()
{
$aStackTrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT , 3);
$sCaller = 'From '.$aStackTrace[1]['file'].'('.$aStackTrace[1]['line'].'): '.$aStackTrace[2]['class'].'->'.$aStackTrace[2]['function'].'()';
if (!self::IsInsideTransaction())
{
// should not happen !
IssueLog::Error("No Transaction COMMIT $sCaller", 'cmdbsource');
throw new MySQLNoTransactionException('Trying to commit transaction whereas none have been started !', null);
}
@@ -816,10 +779,8 @@ class CMDBSource
if (self::IsInsideTransaction())
{
IssueLog::Trace("Ignore nested (".self::$m_iTransactionLevel.") COMMIT $sCaller", 'cmdbsource');
return;
}
IssueLog::Trace("COMMIT $sCaller", 'cmdbsource');
self::DBQuery('COMMIT');
}
@@ -838,22 +799,17 @@ class CMDBSource
*/
private static function Rollback()
{
$aStackTrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT , 3);
$sCaller = 'From '.$aStackTrace[1]['file'].'('.$aStackTrace[1]['line'].'): '.$aStackTrace[2]['class'].'->'.$aStackTrace[2]['function'].'()';
if (!self::IsInsideTransaction())
{
// should not happen !
IssueLog::Error("No Transaction ROLLBACK $sCaller", 'cmdbsource');
throw new MySQLNoTransactionException('Trying to commit transaction whereas none have been started !', null);
}
self::RemoveLastTransactionLevel();
if (self::IsInsideTransaction())
{
IssueLog::Trace("Ignore nested (".self::$m_iTransactionLevel.") ROLLBACK $sCaller", 'cmdbsource');
return;
}
IssueLog::Trace("ROLLBACK $sCaller", 'cmdbsource');
self::DBQuery('ROLLBACK');
}
@@ -903,17 +859,6 @@ class CMDBSource
self::$m_iTransactionLevel = 0;
}
public static function IsDeadlockException(Exception $e)
{
while ($e instanceof Exception) {
if (($e instanceof MySQLException) && ($e->getCode() == 1213)) {
return true;
}
$e = $e->getPrevious();
}
return false;
}
/**
*
* @deprecated 2.7.0 N°1627 use ItopCounter instead
@@ -977,7 +922,7 @@ class CMDBSource
$oKPI = new ExecutionKPI();
try
{
$oResult = self::GetMySQLiForQuery()->query($sSql);
$oResult = self::$m_oMysqli->query($sSql);
}
catch(mysqli_sql_exception $e)
{
@@ -1017,7 +962,7 @@ class CMDBSource
$oKPI = new ExecutionKPI();
try
{
$oResult = self::GetMySQLiForQuery()->query($sSql);
$oResult = self::$m_oMysqli->query($sSql);
}
catch(mysqli_sql_exception $e)
{
@@ -1099,7 +1044,7 @@ class CMDBSource
{
try
{
$oResult = self::GetMySQLiForQuery()->query($sSql);
$oResult = self::$m_oMysqli->query($sSql);
}
catch(mysqli_sql_exception $e)
{
@@ -1586,7 +1531,7 @@ class CMDBSource
$sSql = "SELECT * FROM `$sTable`";
try
{
$oResult = self::GetMySQLiForQuery()->query($sSql);
$oResult = self::$m_oMysqli->query($sSql);
}
catch(mysqli_sql_exception $e)
{

View File

@@ -149,14 +149,14 @@ class CoreCannotSaveObjectException extends CoreException
*
* @param array $aContextData containing at least those keys : issues, id, class
*/
public function __construct($aContextData, $oPrevious = null)
public function __construct($aContextData)
{
$this->aIssues = $aContextData['issues'];
$this->iObjectId = $aContextData['id'];
$this->sObjectClass = $aContextData['class'];
$sIssues = implode(', ', $this->aIssues);
parent::__construct($sIssues, $aContextData, '', $oPrevious);
parent::__construct($sIssues, $aContextData);
}
/**

View File

@@ -2739,72 +2739,50 @@ abstract class DBObject implements iDisplay
}
}
$iTransactionRetry = 1;
$bIsTransactionEnabled = MetaModel::GetConfig()->Get('db_core_transactions_enabled');
if ($bIsTransactionEnabled)
try
{
// TODO Deep clone this object before the transaction (to use it in case of rollback)
// $iTransactionRetryCount = MetaModel::GetConfig()->Get('db_core_transactions_retry_count');
$iTransactionRetryCount = 1;
$iTransactionRetryDelay = MetaModel::GetConfig()->Get('db_core_transactions_retry_delay_ms');
$iTransactionRetry = $iTransactionRetryCount;
}
while ($iTransactionRetry > 0) {
try {
$iTransactionRetry--;
if ($bIsTransactionEnabled) {
CMDBSource::Query('START TRANSACTION');
}
// First query built upon on the root class, because the ID must be created first
$this->m_iKey = $this->DBInsertSingleTable($sRootClass);
// Then do the leaf class, if different from the root class
if ($sClass != $sRootClass) {
$this->DBInsertSingleTable($sClass);
}
// Then do the other classes
foreach (MetaModel::EnumParentClasses($sClass) as $sParentClass) {
if ($sParentClass == $sRootClass) {
continue;
}
$this->DBInsertSingleTable($sParentClass);
}
$this->OnObjectKeyReady();
$this->DBWriteLinks();
$this->WriteExternalAttributes();
if ($bIsTransactionEnabled) {
CMDBSource::Query('COMMIT');
}
break;
if ($bIsTransactionEnabled)
{
CMDBSource::Query('START TRANSACTION');
}
catch (Exception $e) {
IssueLog::Error($e->getMessage());
if ($bIsTransactionEnabled)
// First query built upon on the root class, because the ID must be created first
$this->m_iKey = $this->DBInsertSingleTable($sRootClass);
// Then do the leaf class, if different from the root class
if ($sClass != $sRootClass)
{
$this->DBInsertSingleTable($sClass);
}
// Then do the other classes
foreach (MetaModel::EnumParentClasses($sClass) as $sParentClass)
{
if ($sParentClass == $sRootClass)
{
CMDBSource::Query('ROLLBACK');
if (!CMDBSource::IsInsideTransaction() && CMDBSource::IsDeadlockException($e))
{
// Deadlock found when trying to get lock; try restarting transaction (only in main transaction)
if ($iTransactionRetry > 0)
{
// wait and retry
IssueLog::Error("Insert TRANSACTION Retrying...");
usleep(random_int(1, 5) * 1000 * $iTransactionRetryDelay * ($iTransactionRetryCount - $iTransactionRetry));
continue;
}
else
{
IssueLog::Error("Insert Deadlock TRANSACTION prevention failed.");
}
}
continue;
}
throw $e;
$this->DBInsertSingleTable($sParentClass);
}
$this->OnObjectKeyReady();
$this->DBWriteLinks();
$this->WriteExternalAttributes();
if ($bIsTransactionEnabled)
{
CMDBSource::Query('COMMIT');
}
}
catch (Exception $e)
{
if ($bIsTransactionEnabled)
{
CMDBSource::Query('ROLLBACK');
}
throw $e;
}
$this->m_bIsInDB = true;
@@ -3145,11 +3123,13 @@ abstract class DBObject implements iDisplay
array(), $aParams);
while ($oTrigger = $oSet->Fetch())
{
/** @var \TriggerOnObjectUpdate $oTrigger */
try {
/** @var \Trigger $oTrigger */
try
{
$oTrigger->DoActivate($this->ToArgs('this'));
}
catch (Exception $e) {
catch(Exception $e)
{
utils::EnrichRaisedException($oTrigger, $e);
}
}
@@ -3178,11 +3158,9 @@ abstract class DBObject implements iDisplay
$bIsTransactionEnabled = MetaModel::GetConfig()->Get('db_core_transactions_enabled');
if ($bIsTransactionEnabled)
{
// TODO Deep clone this object before the transaction (to use it in case of rollback)
// $iTransactionRetryCount = MetaModel::GetConfig()->Get('db_core_transactions_retry_count');
$iTransactionRetryCount = 1;
$iIsTransactionRetryCount = MetaModel::GetConfig()->Get('db_core_transactions_retry_count');
$iIsTransactionRetryDelay = MetaModel::GetConfig()->Get('db_core_transactions_retry_delay_ms');
$iTransactionRetry = $iTransactionRetryCount;
$iTransactionRetry = $iIsTransactionRetryCount;
}
while ($iTransactionRetry > 0)
{
@@ -3250,6 +3228,13 @@ abstract class DBObject implements iDisplay
$this->DBWriteLinks();
$this->WriteExternalAttributes();
// following lines are resetting changes (so after this {@see DBObject::ListChanges()} won't return changes anymore)
// new values are already in the object (call {@see DBObject::Get()} to get them)
// call {@see DBObject::ListPreviousValuesForUpdatedAttributes()} to get changed fields and previous values
$this->m_bDirty = false;
$this->m_aTouchedAtt = array();
$this->m_aModifiedAtt = array();
if (count($aChanges) != 0)
{
$this->RecordAttChanges($aChanges, $aOriginalValues);
@@ -3263,18 +3248,18 @@ abstract class DBObject implements iDisplay
}
catch (MySQLException $e)
{
IssueLog::Error($e->getMessage());
if ($bIsTransactionEnabled)
{
CMDBSource::Query('ROLLBACK');
if (!CMDBSource::IsInsideTransaction() && CMDBSource::IsDeadlockException($e))
if ($e->getCode() == 1213)
{
// Deadlock found when trying to get lock; try restarting transaction (only in main transaction)
// Deadlock found when trying to get lock; try restarting transaction
IssueLog::Error($e->getMessage());
if ($iTransactionRetry > 0)
{
// wait and retry
IssueLog::Error("Update TRANSACTION Retrying...");
usleep(random_int(1, 5) * 1000 * $iIsTransactionRetryDelay * ($iTransactionRetryCount - $iTransactionRetry));
usleep(random_int(1, 5) * 1000 * $iIsTransactionRetryDelay * ($iIsTransactionRetryCount - $iTransactionRetry));
continue;
}
else
@@ -3288,11 +3273,10 @@ abstract class DBObject implements iDisplay
'id' => $this->GetKey(),
'class' => get_class($this),
'issues' => $aErrors
), $e);
));
}
catch (CoreCannotSaveObjectException $e)
{
IssueLog::Error($e->getMessage());
if ($bIsTransactionEnabled)
{
CMDBSource::Query('ROLLBACK');
@@ -3301,7 +3285,6 @@ abstract class DBObject implements iDisplay
}
catch (Exception $e)
{
IssueLog::Error($e->getMessage());
if ($bIsTransactionEnabled)
{
CMDBSource::Query('ROLLBACK');
@@ -3315,13 +3298,6 @@ abstract class DBObject implements iDisplay
}
}
// following lines are resetting changes (so after this {@see DBObject::ListChanges()} won't return changes anymore)
// new values are already in the object (call {@see DBObject::Get()} to get them)
// call {@see DBObject::ListPreviousValuesForUpdatedAttributes()} to get changed fields and previous values
$this->m_bDirty = false;
$this->m_aTouchedAtt = array();
$this->m_aModifiedAtt = array();
try
{
$this->AfterUpdate();
@@ -3520,11 +3496,9 @@ abstract class DBObject implements iDisplay
$bIsTransactionEnabled = MetaModel::GetConfig()->Get('db_core_transactions_enabled');
if ($bIsTransactionEnabled)
{
// TODO Deep clone this object before the transaction (to use it in case of rollback)
// $iTransactionRetryCount = MetaModel::GetConfig()->Get('db_core_transactions_retry_count');
$iTransactionRetryCount = 1;
$iTransactionRetryDelay = MetaModel::GetConfig()->Get('db_core_transactions_retry_delay_ms');
$iTransactionRetry = $iTransactionRetryCount;
$iIsTransactionRetryCount = MetaModel::GetConfig()->Get('db_core_transactions_retry_count');
$iIsTransactionRetryDelay = MetaModel::GetConfig()->Get('db_core_transactions_retry_delay_ms');
$iTransactionRetry = $iIsTransactionRetryCount;
}
while ($iTransactionRetry > 0)
{
@@ -3547,18 +3521,18 @@ abstract class DBObject implements iDisplay
}
catch (MySQLException $e)
{
IssueLog::Error($e->getMessage());
if ($bIsTransactionEnabled)
{
CMDBSource::Query('ROLLBACK');
if (!CMDBSource::IsInsideTransaction() && CMDBSource::IsDeadlockException($e))
if ($e->getCode() == 1213)
{
// Deadlock found when trying to get lock; try restarting transaction
IssueLog::Error($e->getMessage());
if ($iTransactionRetry > 0)
{
// wait and retry
IssueLog::Error("Delete TRANSACTION Retrying...");
usleep(random_int(1, 5) * 1000 * $iTransactionRetryDelay * ($iTransactionRetryCount - $iTransactionRetry));
usleep(random_int(1, 5) * 1000 * $iIsTransactionRetryDelay * ($iIsTransactionRetryCount - $iTransactionRetry));
continue;
}
else
@@ -3735,22 +3709,16 @@ abstract class DBObject implements iDisplay
/**
* Apply a stimulus (workflow)
*
* @api
*
* @param string $sStimulusCode
* @param bool $bDoNotWrite if true we won't save the object !
*
*
* @api
*
* @param string $sStimulusCode
* @param bool $bDoNotWrite
*
* @return bool
*
*
* @throws CoreException
* @throws CoreUnexpectedValue
*
* @uses \AttributeStopWatch::Start
* @uses \AttributeStopWatch::Stop
* @uses \DBObject::DBWrite
* @uses \TriggerOnStateLeave::DoActivate
* @uses \TriggerOnStateEnter::DoActivate
*/
public function ApplyStimulus($sStimulusCode, $bDoNotWrite = false)
{
@@ -3874,7 +3842,8 @@ abstract class DBObject implements iDisplay
}
}
if (!$bDoNotWrite) {
if (!$bDoNotWrite)
{
$this->DBWrite();
}
@@ -3882,26 +3851,30 @@ abstract class DBObject implements iDisplay
$aParams = array(
'class_list' => MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL),
'previous_state' => $sPreviousState,
'new_state' => $sNewState,
);
'new_state' => $sNewState);
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateLeave AS t WHERE t.target_class IN (:class_list) AND t.state=:previous_state"), array(), $aParams);
while ($oTrigger = $oSet->Fetch()) {
/** @var \TriggerOnStateLeave $oTrigger */
try {
while ($oTrigger = $oSet->Fetch())
{
/** @var \Trigger $oTrigger */
try
{
$oTrigger->DoActivate($this->ToArgs('this'));
}
catch (Exception $e) {
catch(Exception $e)
{
utils::EnrichRaisedException($oTrigger, $e);
}
}
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateEnter AS t WHERE t.target_class IN (:class_list) AND t.state=:new_state"), array(), $aParams);
while ($oTrigger = $oSet->Fetch()) {
/** @var \TriggerOnStateEnter $oTrigger */
try {
while ($oTrigger = $oSet->Fetch())
{
/** @var \Trigger $oTrigger */
try{
$oTrigger->DoActivate($this->ToArgs('this'));
}
catch (Exception $e) {
catch(Exception $e)
{
utils::EnrichRaisedException($oTrigger, $e);
}
}

View File

@@ -1004,8 +1004,10 @@ abstract class DBSearch
}
/**
* Generate a SQL query from the current search
*
* Generate a SQL query from the current search
*
* @internal
*
* @param array $aOrderBy Array of '[<classalias>.]attcode' => bAscending
* @param array $aArgs
* @param null $aAttToLoad
@@ -1013,16 +1015,12 @@ abstract class DBSearch
* @param int $iLimitCount
* @param int $iLimitStart
* @param bool $bGetCount
* @param bool $bBeautifulSQL
*
* @return string
* @throws \ConfigException
* @throws \CoreException
* @throws \MissingQueryArgument
* @internal
*
* @throws CoreException
* @throws Exception
* @throws MissingQueryArgument
*/
public function MakeSelectQuery($aOrderBy = array(), $aArgs = array(), $aAttToLoad = null, $aExtendedDataSpec = null, $iLimitCount = 0, $iLimitStart = 0, $bGetCount = false, $bBeautifulSQL = true)
public function MakeSelectQuery($aOrderBy = array(), $aArgs = array(), $aAttToLoad = null, $aExtendedDataSpec = null, $iLimitCount = 0, $iLimitStart = 0, $bGetCount = false)
{
// Check the order by specification, and prefix with the class alias
// and make sure that the ordering columns are going to be selected
@@ -1087,7 +1085,8 @@ abstract class DBSearch
}
try
{
$sRes = $oSQLQuery->RenderSelect($aOrderSpec, $aScalarArgs, $iLimitCount, $iLimitStart, $bGetCount, $bBeautifulSQL);
// $bBeautifulSQL = self::$m_bTraceQueries || self::$m_bDebugQuery || self::$m_bIndentQueries;
$sRes = $oSQLQuery->RenderSelect($aOrderSpec, $aScalarArgs, $iLimitCount, $iLimitStart, $bGetCount, true);
if ($sClassAlias == '_itop_')
{
IssueLog::Info('SQL Query (_itop_): '.$sRes);

View File

@@ -176,29 +176,31 @@ class InlineImage extends DBObject
$sOQL = 'SELECT InlineImage WHERE temp_id = :temp_id';
$oSearch = DBObjectSearch::FromOQL($sOQL);
$oSet = new DBObjectSet($oSearch, array(), array('temp_id' => $sTempId));
$aInlineImagesId = array();
while ($oInlineImage = $oSet->Fetch()) {
$aInlineImagesId[] = $oInlineImage->GetKey();
$aInlineImagesId = array();
while($oInlineImage = $oSet->Fetch())
{
$aInlineImagesId[] = $oInlineImage->GetKey();
$oInlineImage->SetItem($oObject);
$oInlineImage->Set('temp_id', '');
$oInlineImage->DBUpdate();
}
IssueLog::Trace('FinalizeInlineImages (see $aInlineImagesId for the id list)', LogChannels::INLINE_IMAGE, array(
'$sObjectClass' => get_class($oObject),
'$sTransactionId' => $iTransactionId,
'$sTempId' => $sTempId,
'$aInlineImagesId' => $aInlineImagesId,
'$sUser' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
));
IssueLog::Trace('FinalizeInlineImages (see $aInlineImagesId for the id list)', 'InlineImage', array(
'$sObjectClass' => get_class($oObject),
'$sTransactionId' => $iTransactionId,
'$sTempId' => $sTempId,
'$aInlineImagesId' => $aInlineImagesId,
'$sUser' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
));
}
else {
IssueLog::Trace('FinalizeInlineImages "error" $iTransactionId is null', LogChannels::INLINE_IMAGE, array(
'$sObjectClass' => get_class($oObject),
'$sTransactionId' => $iTransactionId,
'$sUser' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
));
else
{
IssueLog::Trace('FinalizeInlineImages "error" $iTransactionId is null', 'InlineImage', array(
'$sObjectClass' => get_class($oObject),
'$sTransactionId' => $iTransactionId,
'$sUser' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
));
}
}
@@ -218,12 +220,12 @@ class InlineImage extends DBObject
$aInlineImagesId[] = $oInlineImage->GetKey();
$oInlineImage->DBDelete();
}
IssueLog::Trace('OnFormCancel', LogChannels::INLINE_IMAGE, array(
'$sTempId' => $sTempId,
'$aInlineImagesId' => $aInlineImagesId,
'$sUser' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
));
IssueLog::Trace('OnFormCancel', 'InlineImage', array(
'$sTempId' => $sTempId,
'$aInlineImagesId' => $aInlineImagesId,
'$sUser' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
));
}
/**
@@ -563,17 +565,17 @@ JS
protected function AfterInsert()
{
IssueLog::Trace(__METHOD__, LogChannels::INLINE_IMAGE, array(
'id' => $this->GetKey(),
'expire' => $this->Get('expire'),
'temp_id' => $this->Get('temp_id'),
'item_class' => $this->Get('item_class'),
'item_id' => $this->Get('item_id'),
'item_org_id' => $this->Get('item_org_id'),
'secret' => $this->Get('secret'),
'user' => $sUser = UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
IssueLog::Trace(__METHOD__, 'InlineImage', array(
'id' => $this->GetKey(),
'expire' => $this->Get('expire'),
'temp_id' => $this->Get('temp_id'),
'item_class' => $this->Get('item_class'),
'item_id' => $this->Get('item_id'),
'item_org_id' => $this->Get('item_org_id'),
'secret' => $this->Get('secret'),
'user' => $sUser = UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
));
parent::AfterInsert();
@@ -581,17 +583,17 @@ JS
protected function AfterUpdate()
{
IssueLog::Trace(__METHOD__, LogChannels::INLINE_IMAGE, array(
'id' => $this->GetKey(),
'expire' => $this->Get('expire'),
'temp_id' => $this->Get('temp_id'),
'item_class' => $this->Get('item_class'),
'item_id' => $this->Get('item_id'),
'item_org_id' => $this->Get('item_org_id'),
'secret' => $this->Get('secret'),
'user' => $sUser = UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
IssueLog::Trace(__METHOD__, 'InlineImage', array(
'id' => $this->GetKey(),
'expire' => $this->Get('expire'),
'temp_id' => $this->Get('temp_id'),
'item_class' => $this->Get('item_class'),
'item_id' => $this->Get('item_id'),
'item_org_id' => $this->Get('item_org_id'),
'secret' => $this->Get('secret'),
'user' => $sUser = UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
));
parent::AfterUpdate();
@@ -599,17 +601,17 @@ JS
protected function AfterDelete()
{
IssueLog::Trace(__METHOD__, LogChannels::INLINE_IMAGE, array(
'id' => $this->GetKey(),
'expire' => $this->Get('expire'),
'temp_id' => $this->Get('temp_id'),
'item_class' => $this->Get('item_class'),
'item_id' => $this->Get('item_id'),
'item_org_id' => $this->Get('item_org_id'),
'secret' => $this->Get('secret'),
'user' => $sUser = UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
IssueLog::Trace(__METHOD__, 'InlineImage', array(
'id' => $this->GetKey(),
'expire' => $this->Get('expire'),
'temp_id' => $this->Get('temp_id'),
'item_class' => $this->Get('item_class'),
'item_id' => $this->Get('item_id'),
'item_org_id' => $this->Get('item_org_id'),
'secret' => $this->Get('secret'),
'user' => $sUser = UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
));
parent::AfterDelete();

View File

@@ -398,10 +398,10 @@ class MonthlyRotatingLogFileNameBuilder extends RotatingLogFileNameBuilder
*/
protected function GetFileSuffix($oDate)
{
$sMonthYear = $oDate->format('o');
$sMonthNumber = $oDate->format('m');
$sWeekYear = $oDate->format('o');
$sWeekNumber = $oDate->format('m');
return $sMonthYear.'-month'.$sMonthNumber;
return $sWeekYear.'-month'.$sWeekNumber;
}
/**
@@ -502,7 +502,6 @@ class FileLog
protected function Write($sText, $sLevel = '', $sChannel = '', $aContext = array())
{
$sTextPrefix = empty($sLevel) ? '' : (str_pad($sLevel, 7).' | ');
$sTextPrefix .= str_pad(UserRights::GetUserId(), 5)." | ";
$sTextSuffix = empty($sChannel) ? '' : " | $sChannel";
$sText = "{$sTextPrefix}{$sText}{$sTextSuffix}";
$sLogFilePath = $this->oFileNameBuilder->GetLogFilePath();
@@ -517,9 +516,12 @@ class FileLog
{
flock($hLogFile, LOCK_EX);
$sDate = date('Y-m-d H:i:s');
if (empty($aContext)) {
if (empty($aContext))
{
fwrite($hLogFile, "$sDate | $sText\n");
} else {
}
else
{
$sContext = var_export($aContext, true);
fwrite($hLogFile, "$sDate | $sText\n$sContext\n");
}
@@ -530,21 +532,6 @@ class FileLog
}
}
/**
* Simple enum like class to factorize channels values as constants
* Channels are used especially as parameters in {@see \LogAPI} methods
*
* @since 2.7.5 3.0.0 N°4012
*/
class LogChannels
{
const DEADLOCK = 'DeadLock';
const INLINE_IMAGE = 'InlineImage';
const PORTAL = 'portal';
}
abstract class LogAPI
{
const CHANNEL_DEFAULT = '';
@@ -556,11 +543,11 @@ abstract class LogAPI
const LEVEL_DEBUG = 'Debug';
const LEVEL_TRACE = 'Trace';
/**
* @see GetMinLogLevel
* @var string default log level, can be overrided
* @see GetMinLogLevel
* @since 2.7.1 N°2977
*/
const LEVEL_DEFAULT = self::LEVEL_OK;
const LEVEL_DEFAULT = self::LEVEL_OK;
protected static $aLevelsPriority = array(
self::LEVEL_ERROR => 400,
@@ -617,29 +604,36 @@ abstract class LogAPI
public static function Log($sLevel, $sMessage, $sChannel = null, $aContext = array())
{
if (!static::$m_oFileLog) {
if (! static::$m_oFileLog)
{
return;
}
if (!isset(self::$aLevelsPriority[$sLevel])) {
if (! isset(self::$aLevelsPriority[$sLevel]))
{
IssueLog::Error("invalid log level '{$sLevel}'");
return;
}
if (is_null($sChannel)) {
if (is_null($sChannel))
{
$sChannel = static::CHANNEL_DEFAULT;
}
$sMinLogLevel = self::GetMinLogLevel($sChannel);
if ($sMinLogLevel === false || $sMinLogLevel === 'false') {
if ($sMinLogLevel === false || $sMinLogLevel === 'false')
{
return;
}
if (is_string($sMinLogLevel)) {
if (!isset(self::$aLevelsPriority[$sMinLogLevel])) {
if (is_string($sMinLogLevel))
{
if (! isset(self::$aLevelsPriority[$sMinLogLevel]))
{
throw new Exception("invalid configuration for log_level '{$sMinLogLevel}' is not within the list: ".implode(',', array_keys(self::$aLevelsPriority)));
} elseif (self::$aLevelsPriority[$sLevel] < self::$aLevelsPriority[$sMinLogLevel]) {
}
elseif (self::$aLevelsPriority[$sLevel] < self::$aLevelsPriority[$sMinLogLevel])
{
//priority too low regarding the conf, do not log this
return;
}
@@ -746,7 +740,7 @@ class DeadLockLog extends LogAPI
return self::CHANNEL_WAIT_TIMEOUT;
break;
case 1213:
return self::CHANNEL_DEADLOCK_FOUND;
return self::CHANNEL_DEADLOCK_FOUND;
break;
default:
return self::CHANNEL_DEFAULT;
@@ -755,21 +749,17 @@ class DeadLockLog extends LogAPI
}
/**
* @param string $sLevel
* @param int $iMySQLErrNo will be converted to channel using {@link GetChannelFromMysqlErrorNo}
* @param string $sMessage
* @param int $iMysqlErrorNumber will be converted to channel using {@link GetChannelFromMysqlErrorNo}
* @param null $iMysqlErroNo
* @param array $aContext
*
* @throws \Exception
* @noinspection PhpParameterNameChangedDuringInheritanceInspection
*
* @since 2.7.1 method creation
* @since 2.7.5 3.0.0 rename param names and fix phpdoc (thanks Hipska !)
*/
public static function Log($sLevel, $sMessage, $iMysqlErrorNumber = null, $aContext = array())
public static function Log($iMySQLErrNo, $sMessage, $iMysqlErroNo = null, $aContext = array())
{
$sChannel = self::GetChannelFromMysqlErrorNo($iMysqlErrorNumber);
parent::Log($sLevel, $sMessage, $sChannel, $aContext);
$sChannel = self::GetChannelFromMysqlErrorNo($iMysqlErroNo);
parent::Log($iMySQLErrNo, $sMessage, $sChannel, $aContext);
}
}

View File

@@ -5366,7 +5366,7 @@ abstract class MetaModel
$aSugFix[$sClass]['id'][] = "ALTER TABLE `$sTable` ADD $sKeyFieldDefinition";
if (!$bTableToCreate)
{
$aAlterTableItems[$sTable]['field'][$sKeyField] = "ADD $sKeyFieldDefinition";
$aAlterTableItems[$sTable][$sKeyField] = "ADD $sKeyFieldDefinition";
}
}
else
@@ -5379,7 +5379,7 @@ abstract class MetaModel
$aSugFix[$sClass]['id'][] = "ALTER TABLE `$sTable`, DROP PRIMARY KEY, ADD PRIMARY key(`$sKeyField`)";
if (!$bTableToCreate)
{
$aAlterTableItems[$sTable]['field'][$sKeyField] = "CHANGE `$sKeyField` $sKeyFieldDefinition";
$aAlterTableItems[$sTable][$sKeyField] = "CHANGE `$sKeyField` $sKeyFieldDefinition";
}
}
if (self::IsAutoIncrementKey($sClass) && !CMDBSource::IsAutoIncrement($sTable, $sKeyField))
@@ -5388,7 +5388,7 @@ abstract class MetaModel
$aSugFix[$sClass]['id'][] = "ALTER TABLE `$sTable` CHANGE `$sKeyField` $sKeyFieldDefinition";
if (!$bTableToCreate)
{
$aAlterTableItems[$sTable]['field'][$sKeyField] = "CHANGE `$sKeyField` $sKeyFieldDefinition";
$aAlterTableItems[$sTable][$sKeyField] = "CHANGE `$sKeyField` $sKeyFieldDefinition";
}
}
}
@@ -5451,7 +5451,7 @@ abstract class MetaModel
}
else
{
$aAlterTableItems[$sTable]['field'][$sField] = "ADD $sFieldDefinition";
$aAlterTableItems[$sTable][$sField] = "ADD $sFieldDefinition";
$aAdditionalRequests = self::GetAdditionalRequestAfterAlter($sClass, $sTable, $sField);
if (!empty($aAdditionalRequests))
{
@@ -5495,7 +5495,7 @@ abstract class MetaModel
}
else
{
$aAlterTableItems[$sTable]['index'][] = "ADD $sIndexType `$sIndexName` ($sColumns)";
$aAlterTableItems[$sTable][] = "ADD $sIndexType `$sIndexName` ($sColumns)";
}
}
@@ -5536,7 +5536,7 @@ abstract class MetaModel
if (CMDBSource::HasIndex($sTable, $sField))
{
$aSugFix[$sClass][$sAttCode][] = "ALTER TABLE `$sTable` DROP INDEX `$sIndexName`";
$aAlterTableItems[$sTable]['index'][] = "DROP INDEX `$sIndexName`";
$aAlterTableItems[$sTable][] = "DROP INDEX `$sIndexName`";
}
$sSugFixAfterChange = "ALTER TABLE `$sTable` ADD $sIndexType `$sIndexName` ($sColumns)";
$sAlterTableItemsAfterChange = "ADD $sIndexType `$sIndexName` ($sColumns)";
@@ -5550,7 +5550,7 @@ abstract class MetaModel
{
$aErrors[$sClass][$sAttCode][] = "field '$sField' in table '$sTable' has a wrong type: found <code>$sActualFieldSpec</code> while expecting <code>$sDBFieldSpec</code>";
$aSugFix[$sClass][$sAttCode][] = "ALTER TABLE `$sTable` CHANGE `$sField` $sFieldDefinition";
$aAlterTableItems[$sTable]['field'][$sField] = "CHANGE `$sField` $sFieldDefinition";
$aAlterTableItems[$sTable][$sField] = "CHANGE `$sField` $sFieldDefinition";
}
// Create indexes (external keys only... so far)
@@ -5565,7 +5565,7 @@ abstract class MetaModel
}
else
{
$aAlterTableItems[$sTable]['index'][] = $sAlterTableItemsAfterChange;
$aAlterTableItems[$sTable][] = $sAlterTableItemsAfterChange;
}
}
}
@@ -5625,12 +5625,9 @@ abstract class MetaModel
{
$aAlterTableItems[$sTable] = array();
}
if (isset($aAlterTableItems[$sTable]['index']))
{
array_unshift($aAlterTableItems[$sTable]['index'], "DROP INDEX `$sIndexId`");
}
array_unshift($aAlterTableItems[$sTable], "DROP INDEX `$sIndexId`");
}
$aAlterTableItems[$sTable]['index'][] = "ADD INDEX `$sIndexId` ($sColumns)";
$aAlterTableItems[$sTable][] = "ADD INDEX `$sIndexId` ($sColumns)";
}
}
}
@@ -5648,7 +5645,7 @@ abstract class MetaModel
// without specifying the value of this unknown column
$sFieldDefinition = "`$sField` ".CMDBSource::GetFieldType($sTable, $sField).' NULL';
$aSugFix[$sClass][$sAttCode][] = "ALTER TABLE `$sTable` CHANGE `$sField` $sFieldDefinition";
$aAlterTableItems[$sTable]['field'][$sField] = "CHANGE `$sField` $sFieldDefinition";
$aAlterTableItems[$sTable][$sField] = "CHANGE `$sField` $sFieldDefinition";
}
$aSugFix[$sClass][$sAttCode][] = "-- Recommended action: ALTER TABLE `$sTable` DROP `$sField`";
}
@@ -5667,10 +5664,7 @@ abstract class MetaModel
{
$aAlterTableItems[$sTable] = array();
}
if (isset($aAlterTableItems[$sTable]['index']))
{
array_unshift($aAlterTableItems[$sTable]['index'], "DROP INDEX `$sIndexId`");
}
array_unshift($aAlterTableItems[$sTable], "DROP INDEX `$sIndexId`");
}
}
@@ -5702,16 +5696,8 @@ abstract class MetaModel
}
foreach ($aAlterTableItems as $sTable => $aChangeList)
{
if (isset($aAlterTableItems[$sTable]['field']))
{
$sChangeList = implode(', ', $aChangeList['field']);
$aCondensedQueries[] = "ALTER TABLE `$sTable` $sChangeList";
}
if (isset($aAlterTableItems[$sTable]['index']))
{
$sChangeList = implode(', ', $aChangeList['index']);
$aCondensedQueries[] = "ALTER TABLE `$sTable` $sChangeList";
}
$sChangeList = implode(', ', $aChangeList);
$aCondensedQueries[] = "ALTER TABLE `$sTable` $sChangeList";
// Add request right after the ALTER TABLE
if (isset($aPostTableAlteration[$sTable]))
{

View File

@@ -242,8 +242,6 @@ class iTopMutex
*
* @throws \Exception
* @throws \MySQLException
*
* @since 2.7.5 3.0.0 N°3968 specify `wait_timeout` for the mutex dedicated connection
*/
public function InitMySQLSession()
{
@@ -256,36 +254,10 @@ class iTopMutex
$this->hDBLink = CMDBSource::GetMysqliInstance($sServer, $sUser, $sPwd, $sSource, $bTlsEnabled, $sTlsCA, false);
if (!$this->hDBLink) {
if (!$this->hDBLink)
{
throw new Exception("Could not connect to the DB server (host=$sServer, user=$sUser): ".mysqli_connect_error().' (mysql errno: '.mysqli_connect_errno().')');
}
// Make sure that the server variable `wait_timeout` is at least 86400 seconds for this connection,
// since the lock will be released if/when the connection times out.
// Source https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html :
// > A lock obtained with GET_LOCK() is released explicitly by executing RELEASE_LOCK() or implicitly when your session terminates
//
// BEWARE: If you want to check the value of this variable, when run from an interactive console `SHOW VARIABLES LIKE 'wait_timeout'`
// will actually returns the value of the variable `interactive_timeout` which may be quite different.
$sSql = "SHOW VARIABLES LIKE 'wait_timeout'";
$result = mysqli_query($this->hDBLink, $sSql);
if (!$result) {
throw new Exception("Failed to issue MySQL query '".$sSql."': ".mysqli_error($this->hDBLink).' (mysql errno: '.mysqli_errno($this->hDBLink).')');
}
if ($aRow = mysqli_fetch_array($result, MYSQLI_BOTH)) {
$iTimeout = (int)$aRow[1];
} else {
mysqli_free_result($result);
throw new Exception("No result for query '".$sSql."'");
}
mysqli_free_result($result);
if ($iTimeout < 86400) {
$result = mysqli_query($this->hDBLink, 'SET SESSION wait_timeout=86400');
if ($result === false) {
throw new Exception("Failed to issue MySQL query '".$sSql."': ".mysqli_error($this->hDBLink).' (mysql errno: '.mysqli_errno($this->hDBLink).')');
}
}
}

View File

@@ -597,7 +597,7 @@ static public $yy_action = array(
** defined, then do no error processing.
*/
const YYNOCODE = 119;
const YYSTACKDEPTH = 1000;
const YYSTACKDEPTH = 100;
const YYNSTATE = 175;
const YYNRULE = 125;
const YYERRORSYMBOL = 76;
@@ -1175,10 +1175,6 @@ static public $yy_action = array(
}
/* Here code is inserted which will execute if the parser
** stack ever overflows */
#line 30 "..\oql-parser.y"
throw new OQLParserStackOverFlowException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCol);
#line 1186 "..\oql-parser.php"
return;
}
$yytos = new OQLParser_yyStackEntry;
@@ -1478,116 +1474,116 @@ throw new OQLParserStackOverFlowException($this->m_sSourceQuery, $this->m_iLine,
** function yy_r0($yymsp){ ... } // User supplied code
** #line <lineno> <thisfile>
*/
#line 37 "..\oql-parser.y"
#line 29 "..\oql-parser.y"
function yy_r0(){ $this->my_result = $this->yystack[$this->yyidx + 0]->minor; }
#line 1488 "..\oql-parser.php"
#line 41 "..\oql-parser.y"
#line 1483 "..\oql-parser.php"
#line 33 "..\oql-parser.y"
function yy_r3(){
$this->_retvalue = new OqlUnionQuery($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor);
}
#line 1493 "..\oql-parser.php"
#line 48 "..\oql-parser.y"
#line 1488 "..\oql-parser.php"
#line 40 "..\oql-parser.y"
function yy_r5(){
$this->_retvalue = new OqlObjectQuery($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -1]->minor, array($this->yystack[$this->yyidx + -2]->minor));
}
#line 1498 "..\oql-parser.php"
#line 51 "..\oql-parser.y"
#line 1493 "..\oql-parser.php"
#line 43 "..\oql-parser.y"
function yy_r6(){
$this->_retvalue = new OqlObjectQuery($this->yystack[$this->yyidx + -4]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -1]->minor, array($this->yystack[$this->yyidx + -2]->minor));
}
#line 1503 "..\oql-parser.php"
#line 55 "..\oql-parser.y"
#line 1498 "..\oql-parser.php"
#line 47 "..\oql-parser.y"
function yy_r7(){
$this->_retvalue = new OqlObjectQuery($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + -4]->minor);
}
#line 1508 "..\oql-parser.php"
#line 58 "..\oql-parser.y"
#line 1503 "..\oql-parser.php"
#line 50 "..\oql-parser.y"
function yy_r8(){
$this->_retvalue = new OqlObjectQuery($this->yystack[$this->yyidx + -4]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + -6]->minor);
}
#line 1513 "..\oql-parser.php"
#line 63 "..\oql-parser.y"
#line 1508 "..\oql-parser.php"
#line 55 "..\oql-parser.y"
function yy_r9(){
$this->_retvalue = array($this->yystack[$this->yyidx + 0]->minor);
}
#line 1518 "..\oql-parser.php"
#line 66 "..\oql-parser.y"
#line 1513 "..\oql-parser.php"
#line 58 "..\oql-parser.y"
function yy_r10(){
array_push($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor);
$this->_retvalue = $this->yystack[$this->yyidx + -2]->minor;
}
#line 1524 "..\oql-parser.php"
#line 71 "..\oql-parser.y"
#line 1519 "..\oql-parser.php"
#line 63 "..\oql-parser.y"
function yy_r11(){ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor; }
#line 1527 "..\oql-parser.php"
#line 72 "..\oql-parser.y"
#line 1522 "..\oql-parser.php"
#line 64 "..\oql-parser.y"
function yy_r12(){ $this->_retvalue = null; }
#line 1530 "..\oql-parser.php"
#line 74 "..\oql-parser.y"
#line 1525 "..\oql-parser.php"
#line 66 "..\oql-parser.y"
function yy_r13(){
// insert the join statement on top of the existing list
array_unshift($this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -1]->minor);
// and return the updated array
$this->_retvalue = $this->yystack[$this->yyidx + 0]->minor;
}
#line 1538 "..\oql-parser.php"
#line 80 "..\oql-parser.y"
#line 1533 "..\oql-parser.php"
#line 72 "..\oql-parser.y"
function yy_r14(){
$this->_retvalue = Array($this->yystack[$this->yyidx + 0]->minor);
}
#line 1543 "..\oql-parser.php"
#line 86 "..\oql-parser.y"
#line 1538 "..\oql-parser.php"
#line 78 "..\oql-parser.y"
function yy_r16(){
// create an array with one single item
$this->_retvalue = new OqlJoinSpec($this->yystack[$this->yyidx + -4]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor);
}
#line 1549 "..\oql-parser.php"
#line 91 "..\oql-parser.y"
#line 1544 "..\oql-parser.php"
#line 83 "..\oql-parser.y"
function yy_r17(){
// create an array with one single item
$this->_retvalue = new OqlJoinSpec($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor);
}
#line 1555 "..\oql-parser.php"
#line 96 "..\oql-parser.y"
#line 1550 "..\oql-parser.php"
#line 88 "..\oql-parser.y"
function yy_r18(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, '=', $this->yystack[$this->yyidx + 0]->minor); }
#line 1558 "..\oql-parser.php"
#line 97 "..\oql-parser.y"
#line 1553 "..\oql-parser.php"
#line 89 "..\oql-parser.y"
function yy_r19(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'BELOW', $this->yystack[$this->yyidx + 0]->minor); }
#line 1561 "..\oql-parser.php"
#line 98 "..\oql-parser.y"
#line 1556 "..\oql-parser.php"
#line 90 "..\oql-parser.y"
function yy_r20(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'BELOW_STRICT', $this->yystack[$this->yyidx + 0]->minor); }
#line 1564 "..\oql-parser.php"
#line 99 "..\oql-parser.y"
#line 1559 "..\oql-parser.php"
#line 91 "..\oql-parser.y"
function yy_r21(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'NOT_BELOW', $this->yystack[$this->yyidx + 0]->minor); }
#line 1567 "..\oql-parser.php"
#line 100 "..\oql-parser.y"
#line 1562 "..\oql-parser.php"
#line 92 "..\oql-parser.y"
function yy_r22(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'NOT_BELOW_STRICT', $this->yystack[$this->yyidx + 0]->minor); }
#line 1570 "..\oql-parser.php"
#line 101 "..\oql-parser.y"
#line 1565 "..\oql-parser.php"
#line 93 "..\oql-parser.y"
function yy_r23(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'ABOVE', $this->yystack[$this->yyidx + 0]->minor); }
#line 1573 "..\oql-parser.php"
#line 102 "..\oql-parser.y"
#line 1568 "..\oql-parser.php"
#line 94 "..\oql-parser.y"
function yy_r24(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'ABOVE_STRICT', $this->yystack[$this->yyidx + 0]->minor); }
#line 1576 "..\oql-parser.php"
#line 103 "..\oql-parser.y"
#line 1571 "..\oql-parser.php"
#line 95 "..\oql-parser.y"
function yy_r25(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'NOT_ABOVE', $this->yystack[$this->yyidx + 0]->minor); }
#line 1579 "..\oql-parser.php"
#line 104 "..\oql-parser.y"
#line 1574 "..\oql-parser.php"
#line 96 "..\oql-parser.y"
function yy_r26(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'NOT_ABOVE_STRICT', $this->yystack[$this->yyidx + 0]->minor); }
#line 1582 "..\oql-parser.php"
#line 106 "..\oql-parser.y"
#line 1577 "..\oql-parser.php"
#line 98 "..\oql-parser.y"
function yy_r27(){ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor; }
#line 1585 "..\oql-parser.php"
#line 111 "..\oql-parser.y"
#line 1580 "..\oql-parser.php"
#line 103 "..\oql-parser.y"
function yy_r31(){ $this->_retvalue = new FunctionOqlExpression($this->yystack[$this->yyidx + -3]->minor, $this->yystack[$this->yyidx + -1]->minor); }
#line 1588 "..\oql-parser.php"
#line 112 "..\oql-parser.y"
#line 1583 "..\oql-parser.php"
#line 104 "..\oql-parser.y"
function yy_r32(){ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor; }
#line 1591 "..\oql-parser.php"
#line 113 "..\oql-parser.y"
#line 1586 "..\oql-parser.php"
#line 105 "..\oql-parser.y"
function yy_r33(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + 0]->minor); }
#line 1594 "..\oql-parser.php"
#line 119 "..\oql-parser.y"
#line 1589 "..\oql-parser.php"
#line 111 "..\oql-parser.y"
function yy_r37(){
if ($this->yystack[$this->yyidx + -1]->minor == 'MATCHES')
{
@@ -1598,44 +1594,44 @@ throw new OQLParserStackOverFlowException($this->m_sSourceQuery, $this->m_iLine,
$this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + 0]->minor);
}
}
#line 1606 "..\oql-parser.php"
#line 136 "..\oql-parser.y"
#line 1601 "..\oql-parser.php"
#line 128 "..\oql-parser.y"
function yy_r42(){
$this->_retvalue = new ListOqlExpression($this->yystack[$this->yyidx + -1]->minor);
}
#line 1611 "..\oql-parser.php"
#line 139 "..\oql-parser.y"
#line 1606 "..\oql-parser.php"
#line 131 "..\oql-parser.y"
function yy_r43(){
$this->_retvalue = new NestedQueryOqlExpression($this->yystack[$this->yyidx + -1]->minor);
}
#line 1616 "..\oql-parser.php"
#line 154 "..\oql-parser.y"
#line 1611 "..\oql-parser.php"
#line 146 "..\oql-parser.y"
function yy_r47(){
$this->_retvalue = array();
}
#line 1621 "..\oql-parser.php"
#line 165 "..\oql-parser.y"
#line 1616 "..\oql-parser.php"
#line 157 "..\oql-parser.y"
function yy_r51(){ $this->_retvalue = new IntervalOqlExpression($this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + 0]->minor); }
#line 1624 "..\oql-parser.php"
#line 178 "..\oql-parser.y"
#line 1619 "..\oql-parser.php"
#line 170 "..\oql-parser.y"
function yy_r61(){ $this->_retvalue = new ScalarOqlExpression($this->yystack[$this->yyidx + 0]->minor); }
#line 1627 "..\oql-parser.php"
#line 180 "..\oql-parser.y"
#line 1622 "..\oql-parser.php"
#line 172 "..\oql-parser.y"
function yy_r63(){ $this->_retvalue = new ScalarOqlExpression(null); }
#line 1630 "..\oql-parser.php"
#line 182 "..\oql-parser.y"
#line 1625 "..\oql-parser.php"
#line 174 "..\oql-parser.y"
function yy_r64(){ $this->_retvalue = new FieldOqlExpression($this->yystack[$this->yyidx + 0]->minor); }
#line 1633 "..\oql-parser.php"
#line 183 "..\oql-parser.y"
#line 1628 "..\oql-parser.php"
#line 175 "..\oql-parser.y"
function yy_r65(){ $this->_retvalue = new FieldOqlExpression($this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -2]->minor); }
#line 1636 "..\oql-parser.php"
#line 184 "..\oql-parser.y"
#line 1631 "..\oql-parser.php"
#line 176 "..\oql-parser.y"
function yy_r66(){ $this->_retvalue=$this->yystack[$this->yyidx + 0]->minor; }
#line 1639 "..\oql-parser.php"
#line 187 "..\oql-parser.y"
#line 1634 "..\oql-parser.php"
#line 179 "..\oql-parser.y"
function yy_r67(){ $this->_retvalue = new VariableOqlExpression(substr($this->yystack[$this->yyidx + 0]->minor, 1)); }
#line 1642 "..\oql-parser.php"
#line 189 "..\oql-parser.y"
#line 1637 "..\oql-parser.php"
#line 181 "..\oql-parser.y"
function yy_r68(){
if ($this->yystack[$this->yyidx + 0]->minor[0] == '`')
{
@@ -1647,22 +1643,22 @@ throw new OQLParserStackOverFlowException($this->m_sSourceQuery, $this->m_iLine,
}
$this->_retvalue = new OqlName($name, $this->m_iColPrev);
}
#line 1655 "..\oql-parser.php"
#line 200 "..\oql-parser.y"
#line 1650 "..\oql-parser.php"
#line 192 "..\oql-parser.y"
function yy_r69(){$this->_retvalue=(int)$this->yystack[$this->yyidx + 0]->minor; }
#line 1658 "..\oql-parser.php"
#line 201 "..\oql-parser.y"
#line 1653 "..\oql-parser.php"
#line 193 "..\oql-parser.y"
function yy_r70(){$this->_retvalue=(int)-$this->yystack[$this->yyidx + 0]->minor; }
#line 1661 "..\oql-parser.php"
#line 202 "..\oql-parser.y"
#line 1656 "..\oql-parser.php"
#line 194 "..\oql-parser.y"
function yy_r71(){$this->_retvalue=new OqlHexValue($this->yystack[$this->yyidx + 0]->minor); }
#line 1664 "..\oql-parser.php"
#line 203 "..\oql-parser.y"
#line 1659 "..\oql-parser.php"
#line 195 "..\oql-parser.y"
function yy_r72(){$this->_retvalue=stripslashes(substr($this->yystack[$this->yyidx + 0]->minor, 1, strlen($this->yystack[$this->yyidx + 0]->minor) - 2)); }
#line 1667 "..\oql-parser.php"
#line 206 "..\oql-parser.y"
#line 1662 "..\oql-parser.php"
#line 198 "..\oql-parser.y"
function yy_r73(){$this->_retvalue=$this->yystack[$this->yyidx + 0]->minor; }
#line 1670 "..\oql-parser.php"
#line 1665 "..\oql-parser.php"
/**
* placeholder for the left hand side in a reduce operation.
@@ -1763,10 +1759,6 @@ throw new OQLParserStackOverFlowException($this->m_sSourceQuery, $this->m_iLine,
}
/* Here code is inserted which will be executed whenever the
** parser fails */
#line 33 "..\oql-parser.y"
throw new OQLParserParseFailureException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCol);
#line 1775 "..\oql-parser.php"
}
/**
@@ -1780,8 +1772,8 @@ throw new OQLParserParseFailureException($this->m_sSourceQuery, $this->m_iLine,
{
#line 25 "..\oql-parser.y"
throw new OQLParserSyntaxErrorException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCol, $this->tokenName($yymajor), $TOKEN);
#line 1791 "..\oql-parser.php"
throw new OQLParserException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCol, $this->tokenName($yymajor), $TOKEN);
#line 1781 "..\oql-parser.php"
}
/**
@@ -1948,47 +1940,19 @@ throw new OQLParserSyntaxErrorException($this->m_sSourceQuery, $this->m_iLine, $
} while ($yymajor != self::YYNOCODE && $this->yyidx >= 0);
}
}
#line 271 "..\oql-parser.y"
#line 263 "..\oql-parser.y"
class OQLParserException extends OQLException
{
public function __construct($sIssue, $sInput, $iLine, $iCol, $sTokenValue)
{
parent::__construct($sIssue, $sInput, $iLine, $iCol, $sTokenValue);
}
}
class OQLParserSyntaxErrorException extends OQLParserException
{
public function __construct($sInput, $iLine, $iCol, $sTokenName, $sTokenValue)
{
$sIssue = "Unexpected token $sTokenName";
parent::__construct($sIssue, $sInput, $iLine, $iCol, $sTokenValue);
}
}
class OQLParserStackOverFlowException extends OQLParserException
{
public function __construct($sInput, $iLine, $iCol)
{
$sIssue = "Stack overflow";
parent::__construct($sIssue, $sInput, $iLine, $iCol, '');
}
}
class OQLParserParseFailureException extends OQLParserException
{
public function __construct($sInput, $iLine, $iCol)
{
$sIssue = "Unexpected token $sTokenName";
parent::__construct($sIssue, $sInput, $iLine, $iCol, '');
}
}
class OQLParser extends OQLParserRaw
{
// dirty, but working for us (no other mean to get the final result :-(
@@ -2041,4 +2005,4 @@ class OQLParser extends OQLParserRaw
}
}
#line 2052 "..\oql-parser.php"
#line 2014 "..\oql-parser.php"

View File

@@ -23,15 +23,7 @@ later : solve the 2 remaining shift-reduce conflicts (JOIN)
%name OQLParser_
%declare_class {class OQLParserRaw}
%syntax_error {
throw new OQLParserSyntaxErrorException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCol, $this->tokenName($yymajor), $TOKEN);
}
/* Bug N°4052 Parser stack size too small for huge OQL requests */
%stack_size 1000
%stack_overflow {
throw new OQLParserStackOverFlowException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCol);
}
%parse_failure {
throw new OQLParserParseFailureException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCol);
throw new OQLParserException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCol, $this->tokenName($yymajor), $TOKEN);
}
result ::= union(X). { $this->my_result = X; }
@@ -271,43 +263,15 @@ func_name(A) ::= F_INET_NTOA(X). { A=X; }
%code {
class OQLParserException extends OQLException
{
public function __construct($sIssue, $sInput, $iLine, $iCol, $sTokenValue)
{
parent::__construct($sIssue, $sInput, $iLine, $iCol, $sTokenValue);
}
}
class OQLParserSyntaxErrorException extends OQLParserException
{
public function __construct($sInput, $iLine, $iCol, $sTokenName, $sTokenValue)
{
$sIssue = "Unexpected token $sTokenName";
parent::__construct($sIssue, $sInput, $iLine, $iCol, $sTokenValue);
}
}
class OQLParserStackOverFlowException extends OQLParserException
{
public function __construct($sInput, $iLine, $iCol)
{
$sIssue = "Stack overflow";
parent::__construct($sIssue, $sInput, $iLine, $iCol, '');
}
}
class OQLParserParseFailureException extends OQLParserException
{
public function __construct($sInput, $iLine, $iCol)
{
$sIssue = "Unexpected token $sTokenName";
parent::__construct($sIssue, $sInput, $iLine, $iCol, '');
}
}
class OQLParser extends OQLParserRaw
{
// dirty, but working for us (no other mean to get the final result :-(

View File

@@ -1 +1 @@
2021-06-03
2020-09-29

View File

@@ -55,7 +55,7 @@ class OQLClassTreeOptimizer
$sJoinedClass = $oJoin->GetOOQLClassNode()->GetNodeClass();
$sExtKeyAttCode = $oJoin->GetLeftField();
$oExtKeyAttDef = MetaModel::GetAttributeDef($oCurrentClassNode->GetNodeClass(), $sExtKeyAttCode);
if (($oExtKeyAttDef instanceof AttributeExternalKey) && ($sJoinedClass == $oExtKeyAttDef->GetTargetClass())) {
if ($sJoinedClass == $oExtKeyAttDef->GetTargetClass()) {
// The join is not used, remove from tree
$oCurrentClassNode->RemoveJoin($sLeftKey, $index);
}

View File

@@ -17,7 +17,7 @@
*/
// Beware the version number MUST be enclosed with quotes otherwise v2.3.0 becomes v2 0.3 .0
$version: "v2.7.5";
$version: "v2.7.4";
$approot-relative: "../../../../../" !default; // relative to env-***/branding/themes/***/main.css
// Base colors

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-cas/2.7.5',
'authent-cas/2.7.4',
array(
// Identification
//

View File

@@ -27,7 +27,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-external/2.7.5',
'authent-external/2.7.4',
array(
// Identification
//

View File

@@ -9,7 +9,7 @@ if (function_exists('ldap_connect'))
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-ldap/2.7.5',
'authent-ldap/2.7.4',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-local/2.7.5',
'authent-local/2.7.4',
array(
// Identification
//

View File

@@ -222,11 +222,13 @@ class DatabaseAnalyzer
{
$oFixSearch->AddCondition($sAttCode, $sValue, '=');
}
$aFixit[] = $oFixSearch->MakeSelectQuery([], [], null, null, 0, 0, false, false).';';
$aFixit[] = $oFixSearch->MakeSelectQuery().';';
$aFixit[] = "";
}
$aErrorsAndFixes[$sClass][$sErrorDesc]['fixit'] = $aFixit;
}
return;
}
private function GetUniquenessRuleMessage($sUniquenessRuleId)
@@ -324,8 +326,13 @@ class DatabaseAnalyzer
{
$sField = MetaModel::DBGetClassField($sClass);
$sRootField = MetaModel::DBGetClassField($sRootClass);
$sSelWrongRecs = "SELECT `$sTable`.`$sKeyField` AS id FROM `$sTable` JOIN `$sRootTable` ON `$sRootTable`.`$sRootKey` = `$sTable`.`$sKeyField` WHERE `$sTable`.`$sField` != `$sRootTable`.`$sRootField`";
// Copy the final class of the root table
$sSelWrongRecs = <<<SQL
SELECT `$sTable`.`$sKeyField` AS id
FROM `$sTable`
JOIN `$sRootTable` ON `$sRootTable`.`$sRootKey` = `$sTable`.`$sKeyField`
WHERE `$sTable`.`$sField` != `$sRootTable`.`$sRootField`
SQL;
// Copy the finalclass of the root table
$sFixItRequest = "UPDATE `$sTable`,`$sRootTable` SET `$sTable`.`$sField` = `$sRootTable`.`$sRootField` WHERE `$sTable`.`$sKeyField` = `$sRootTable`.`$sRootKey`";
$this->ExecQuery($sSelWrongRecs, $sFixItRequest, Dict::Format('DBAnalyzer-Integrity-FinalClass', $sField, $sTable, $sRootTable), $sClass, $aErrorsAndFixes);
}
@@ -353,79 +360,65 @@ class DatabaseAnalyzer
// Note: a class/table may have an external key on itself
$sSelect = "SELECT DISTINCT `$sTable`.`$sKeyField` AS id, `$sTable`.`$sExtKeyField` AS value";
$sFrom = "FROM `$sTable`";
$sJoin = "LEFT JOIN `$sRemoteTable` AS `{$sRemoteTable}_1` ON `$sTable`.`$sExtKeyField` = `{$sRemoteTable}_1`.`$sRemoteKey`";
$sFilter = "FROM `$sTable` LEFT JOIN `$sRemoteTable` AS `{$sRemoteTable}_1` ON `$sTable`.`$sExtKeyField` = `{$sRemoteTable}_1`.`$sRemoteKey`";
$sFilter = "WHERE `{$sRemoteTable}_1`.`$sRemoteKey` IS NULL";
$sFilter = $sFilter." WHERE `{$sRemoteTable}_1`.`$sRemoteKey` IS NULL";
// Exclude the records pointing to 0/null from the errors (separate test below)
$sFilter .= " AND `$sTable`.`$sExtKeyField` IS NOT NULL";
$sFilter .= " AND `$sTable`.`$sExtKeyField` != 0";
$sSelWrongRecs = "$sSelect $sFrom $sJoin $sFilter";
$sSelWrongRecs = "$sSelect $sFilter";
$sErrorDesc = Dict::Format('DBAnalyzer-Integrity-InvalidExtKey', $sAttCode, $sTable, $sExtKeyField);
$this->ExecQuery($sSelWrongRecs, '', $sErrorDesc, $sClass, $aErrorsAndFixes);
$aFixIt = [];
// Fix it request needs the values of the enum to generate the requests
if (isset($aErrorsAndFixes[$sClass][$sErrorDesc]['values']))
{
if ($oAttDef->IsNullAllowed()) {
$aFixIt[] = "-- Fix inconsistant values: remove the external key";
foreach (array_keys($aErrorsAndFixes[$sClass][$sErrorDesc]['values']) as $sKey) {
$aFixIt[] = "UPDATE `$sTable` SET `$sTable`.`$sExtKeyField` = 0 WHERE `$sTable`.`$sExtKeyField` = '$sKey'";
}
} else {
$aAdditionalFixIt = $this->GetSpecificExternalKeysFixItForNull($sTable, $sExtKeyField, $sFilter, $sJoin);
foreach ($aAdditionalFixIt as $sFixIt)
{
$aFixIt[] = $sFixIt;
}
$aFixIt[] = "-- Alternate fix: remove inconsistant entries:";
$sIds = implode(', ', array_keys($aErrorsAndFixes[$sClass][$sErrorDesc]['values']));
$aFixIt[] = "DELETE `$sTable` FROM `$sTable` WHERE `$sTable`.`$sExtKeyField` IN ($sIds)";
$aFixIt[] = "-- Alternate fix: update inconsistant values: Replace XXX with the appropriate value";
foreach (array_keys($aErrorsAndFixes[$sClass][$sErrorDesc]['values']) as $sKey) {
$aFixIt[] = "UPDATE `$sTable` SET `$sTable`.`$sExtKeyField` = XXX WHERE `$sTable`.`$sExtKeyField` = '$sKey'";
}
$aFixIt = array();
$aFixIt[] = "-- Remove inconsistant entries:";
$sIds = implode(', ', array_keys($aErrorsAndFixes[$sClass][$sErrorDesc]['values']));
$aFixIt[] = "DELETE `$sTable` FROM `$sTable` WHERE `$sTable`.`$sExtKeyField` IN ($sIds)";
$aFixIt[] = "";
$aFixIt[] = "-- Or fix inconsistant values: Replace XXX with the appropriate value";
foreach (array_keys($aErrorsAndFixes[$sClass][$sErrorDesc]['values']) as $sKey)
{
$aFixIt[] = "UPDATE `$sTable` SET `$sTable`.`$sExtKeyField` = XXX WHERE `$sTable`.`$sExtKeyField` = '$sKey'";
}
$aErrorsAndFixes[$sClass][$sErrorDesc]['fixit'] = $aFixIt;
}
if (!$oAttDef->IsNullAllowed()) {
if (!$oAttDef->IsNullAllowed())
{
$sSelect = "SELECT DISTINCT `$sTable`.`$sKeyField` AS id";
$sDelete = "DELETE `$sTable`";
$sFrom = "FROM `$sTable`";
$sFilter = "WHERE `$sTable`.`$sExtKeyField` IS NULL OR `$sTable`.`$sExtKeyField` = 0";
$sSelWrongRecs = "$sSelect $sFrom $sFilter";
$sFixItRequest = "$sDelete $sFrom $sFilter";
$sFilter = "FROM `$sTable` WHERE `$sTable`.`$sExtKeyField` IS NULL OR `$sTable`.`$sExtKeyField` = 0";
$sSelWrongRecs = "$sSelect $sFilter";
$sFixItRequest = "$sDelete $sFilter";
$sErrorDesc = Dict::Format('DBAnalyzer-Integrity-MissingExtKey', $sAttCode, $sTable, $sExtKeyField);
$this->ExecQuery($sSelWrongRecs, '', $sErrorDesc, $sClass, $aErrorsAndFixes);
$aFixIt = [];
$this->ExecQuery($sSelWrongRecs, $sFixItRequest, $sErrorDesc, $sClass, $aErrorsAndFixes);
if (isset($aErrorsAndFixes[$sClass][$sErrorDesc]['count']) && ($aErrorsAndFixes[$sClass][$sErrorDesc]['count'] > 0))
{
$aAdditionalFixIt = $this->GetSpecificExternalKeysFixItForNull($sTable, $sExtKeyField, $sFilter);
$aFixIt = $aErrorsAndFixes[$sClass][$sErrorDesc]['fixit'];
$aFixIt[] = "-- Alternate fix";
$aFixIt[] = "-- Replace XXX with the appropriate value";
$aFixIt[] = "UPDATE `$sTable` SET `$sTable`.`$sExtKeyField` = XXX WHERE `$sTable`.`$sExtKeyField` IS NULL OR `$sTable`.`$sExtKeyField` = 0";
$aAdditionalFixIt = $this->GetSpecificExternalKeysFixItForNull($sTable, $sExtKeyField);
foreach ($aAdditionalFixIt as $sFixIt)
{
$aFixIt[] = $sFixIt;
}
$aFixIt[] = "-- Alternate fix: remove inconsistant entries:";
$aFixIt[] = $sFixItRequest;
$aFixIt[] = "-- Alternate fix: replace XXX with the appropriate value";
$aFixIt[] = "UPDATE `$sTable` SET `$sTable`.`$sExtKeyField` = XXX WHERE `$sTable`.`$sExtKeyField` IS NULL OR `$sTable`.`$sExtKeyField` = 0";
$aErrorsAndFixes[$sClass][$sErrorDesc]['fixit'] = $aFixIt;
}
}
}
private function GetSpecificExternalKeysFixItForNull($sTable, $sExtKeyField, $sFilter, $sJoin = '')
private function GetSpecificExternalKeysFixItForNull($sTable, $sExtKeyField)
{
$aFixIt = array();
if ($sTable == 'ticket' && $sExtKeyField == 'org_id')
{
$aFixIt[] = "-- Alternate fix: set the ticket org to the caller org";
$aFixIt[] = "UPDATE ticket JOIN contact AS c ON ticket.caller_id=c.id $sJoin SET ticket.org_id=c.org_id $sFilter";
$aFixIt[] = "UPDATE ticket AS t JOIN contact AS c ON t.caller_id=c.id SET t.org_id=c.org_id WHERE t.org_id IS NULL OR t.org_id = 0";
}
return $aFixIt;
}
@@ -448,8 +441,7 @@ class DatabaseAnalyzer
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode);
if (!is_null($aAllowedValues) && count($aAllowedValues) > 0)
{
$aAllowedValues = array_keys($aAllowedValues);
$sExpectedValues = implode(",", CMDBSource::Quote($aAllowedValues, true));
$sExpectedValues = implode(",", CMDBSource::Quote(array_keys($aAllowedValues), true));
$aCols = $oAttDef->GetSQLExpressions(); // Workaround a PHP bug: sometimes issuing a Notice if invoking current(somefunc())
$sMyAttributeField = current($aCols); // get the first column for the moment
@@ -466,18 +458,15 @@ class DatabaseAnalyzer
if (isset($aErrorsAndFixes[$sClass][$sErrorDesc]['fixit']))
{
$aFixIt = $aErrorsAndFixes[$sClass][$sErrorDesc]['fixit'];
$aFixIt[] = "-- Alternative: Replace enums with the appropriate value";
$aFixIt[] = "-- Alternative: Replace 'XXX' with the appropriate value";
}
else
{
$aFixIt = ["-- Replace enums with the appropriate value"];
$aFixIt = array("-- Replace 'XXX' with the appropriate value");
}
foreach (array_keys($aErrorsAndFixes[$sClass][$sErrorDesc]['values']) as $sKey)
{
foreach ($aAllowedValues as $sAllowedValue) {
$aFixIt[] = "-- Replace $sKey by $sAllowedValue";
$aFixIt[] = "UPDATE `$sTable` SET `$sTable`.`$sMyAttributeField` = '$sAllowedValue' WHERE `$sTable`.`$sMyAttributeField` = '$sKey'";
}
$aFixIt[] = "UPDATE `$sTable` SET `$sTable`.`$sMyAttributeField` = 'XXX' WHERE `$sTable`.`$sMyAttributeField` = '$sKey'";
}
$aErrorsAndFixes[$sClass][$sErrorDesc]['fixit'] = $aFixIt;
}

View File

@@ -31,16 +31,15 @@ const MAX_RESULTS = 10;
* @param ApplicationContext $oAppContext
*
* @return \iTopWebPage
* @throws \CoreException
* @throws \DictExceptionMissingString
* @throws \MySQLException
* @throws CoreException
* @throws DictExceptionMissingString
* @throws MySQLException
*/
function DisplayDBInconsistencies(iTopWebPage &$oP, ApplicationContext &$oAppContext)
{
$iShowId = intval(utils::ReadParam('show_id', '0'));
$sErrorLabelSelection = utils::ReadParam('error_selection', '');
$sClassSelection = utils::ReadParam('class_selection', '');
$bVerbose = utils::ReadParam('verbose', 0);
if (!empty($sClassSelection))
{
$aClassSelection = explode(",", $sClassSelection);
@@ -110,16 +109,11 @@ function DisplayDBInconsistencies(iTopWebPage &$oP, ApplicationContext &$oAppCon
if ($iShowId == 3)
{
DisplayInconsistenciesReport($aResults, $bVerbose);
DisplayInconsistenciesReport($aResults);
}
$oP->p(Dict::S('DBTools:ErrorsFound'));
if ($iShowId > 0) {
$oP->p(Dict::S('DBTools:Disclaimer'));
$oP->p(Dict::S('DBTools:Indication'));
}
$oP->add('<table class="listResults"><tr><th>'.Dict::S('DBTools:Class').'</th><th>'.Dict::S('DBTools:Count').'</th><th>'.Dict::S('DBTools:Error').'</th></tr>');
$bTable = true;
foreach($aResults as $sClass => $aErrorList)
@@ -154,7 +148,7 @@ function DisplayDBInconsistencies(iTopWebPage &$oP, ApplicationContext &$oAppCon
$oP->p(Dict::S('DBTools:SQLquery'));
$sQuery = $aError['query'];
$oP->add('<div style="padding: 15px; background: #f1f1f1;">');
$oP->add('<pre>'.$sQuery.'</pre>');
$oP->add('<code>'.$sQuery.'</code>');
$oP->add('</div>');
if (isset($aError['fixit']))
@@ -169,26 +163,27 @@ function DisplayDBInconsistencies(iTopWebPage &$oP, ApplicationContext &$oAppCon
$oP->add('<br></div>');
}
if ($bVerbose) {
$oP->p(Dict::S('DBTools:SQLresult'));
$sQueryResult = '';
$iCount = count($aError['res']);
$iMaxCount = MAX_RESULTS;
foreach ($aError['res'] as $aRes) {
$iMaxCount--;
if ($iMaxCount < 0) {
$sQueryResult .= 'Displayed '.MAX_RESULTS."/$iCount results.<br>";
break;
}
foreach ($aRes as $sKey => $sValue) {
$sQueryResult .= "'$sKey'='$sValue'&nbsp;";
}
$sQueryResult .= '<br>';
$oP->p(Dict::S('DBTools:SQLresult'));
$sQueryResult = '';
$iCount = count($aError['res']);
$iMaxCount = MAX_RESULTS;
foreach($aError['res'] as $aRes)
{
$iMaxCount--;
if ($iMaxCount < 0)
{
$sQueryResult .= 'Displayed '.MAX_RESULTS."/$iCount results.<br>";
break;
}
$oP->add('<div style="padding: 15px; background: #f1f1f1;">');
$oP->add('<pre>'.$sQueryResult.'</pre>');
$oP->add('</div>');
foreach($aRes as $sKey => $sValue)
{
$sQueryResult .= "'$sKey'='$sValue'&nbsp;";
}
$sQueryResult .= '<br>';
}
$oP->add('<div style="padding: 15px; background: #f1f1f1;">');
$oP->add('<code>'.$sQueryResult.'</code>');
$oP->add('</div>');
}
}
}
@@ -199,15 +194,14 @@ function DisplayDBInconsistencies(iTopWebPage &$oP, ApplicationContext &$oAppCon
/**
* @param $aResults
* @param bool $bVerbose
*
* @return mixed
* @throws \CoreException
* @throws \DictExceptionMissingString
* @throws CoreException
* @throws DictExceptionMissingString
*/
function DisplayInconsistenciesReport($aResults, $bVerbose = false)
function DisplayInconsistenciesReport($aResults)
{
$sReportFile = DBAnalyzerUtils::GenerateReport($aResults, $bVerbose);
$sReportFile = DBAnalyzerUtils::GenerateReport($aResults);
$sZipReport = "{$sReportFile}.zip";
$oArchive = new ZipArchive();

View File

@@ -28,8 +28,6 @@ Dict::Add('EN US', 'English', 'English', array(
'DBTools:Class' => 'Class',
'DBTools:Title' => 'Database Maintenance Tools',
'DBTools:ErrorsFound' => 'Errors Found',
'DBTools:Indication' => 'Important: after fixing errors in the database you\'ll have to run the analysis again as new inconsistencies will be generated',
'DBTools:Disclaimer' => 'DISCLAIMER: BACKUP YOUR DATABASE BEFORE RUNNING THE FIXES',
'DBTools:Error' => 'Error',
'DBTools:Count' => 'Count',
'DBTools:SQLquery' => 'SQL query',

View File

@@ -23,8 +23,6 @@ Dict::Add('FR FR', 'French', 'Français', array(
'DBTools:Class' => 'Classe',
'DBTools:Title' => 'Outils maintenance base de données',
'DBTools:ErrorsFound' => 'Erreurs trouvées',
'DBTools:Indication' => 'Important : après correction il est nécessaire de relancer l\'analyse car d\'autres inconsistances peuvent être générées par les modifications',
'DBTools:Disclaimer' => 'ATTENTION : EFFECTUEZ UNE SAUVEGARDE DE LA BASE AVANT D\'APPLIQUER LES CORRECTIONS',
'DBTools:Error' => 'Erreur',
'DBTools:Count' => 'Nombre',
'DBTools:SQLquery' => 'Requête SQL',
@@ -43,7 +41,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
'DBTools:Inconsistencies' => 'Incohérences de base de données',
'DBAnalyzer-Integrity-OrphanRecord' => 'Enregistrement orphelin dans `%1$s`, il devrait avoir son équivalent dans la table `%2$s`',
'DBAnalyzer-Integrity-OrphanRecord' => 'Enregistrement orphelin dans `%1$s`, il devrait avoir son équivalent dans la tableit `%2$s`',
'DBAnalyzer-Integrity-InvalidExtKey' => 'Clef externe invalide %1$s (colonne: `%2$s.%3$s`)',
'DBAnalyzer-Integrity-MissingExtKey' => 'Clef externe manquante %1$s (colonne: `%2$s.%3$s`)',
'DBAnalyzer-Integrity-InvalidValue' => 'Valeur invalide pour %1$s (colonne: `%2$s.%3$s`)',

View File

@@ -24,7 +24,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'combodo-db-tools/2.7.5',
'combodo-db-tools/2.7.4',
array(
// Identification
//

View File

@@ -8,7 +8,6 @@
namespace Combodo\iTop\DBTools\Service;
use CoreException;
use Dict;
use DictExceptionMissingString;
use MetaModel;
@@ -21,31 +20,29 @@ class DBAnalyzerUtils
* @throws CoreException
* @throws DictExceptionMissingString
*/
public static function GenerateReport($aResults, $bVerbose = false)
public static function GenerateReport($aResults)
{
$sDBToolsFolder = str_replace("\\", '/', APPROOT.'log/');
$sReportFile = 'dbtools-report';
$fReport = fopen($sDBToolsFolder.$sReportFile.'.log', 'w');
fwrite($fReport, '-- Database Maintenance tools: '.date('Y-m-d H:i:s')."\r\n");
fwrite($fReport, "-- ".Dict::S('DBTools:Disclaimer')."\r\n");
fwrite($fReport, "-- ".Dict::S('DBTools:Indication')."\r\n");
fwrite($fReport, 'Database Maintenance tools: '.date('Y-m-d H:i:s')."\r\n");
foreach ($aResults as $sClass => $aErrorList)
{
fwrite($fReport, '');
foreach ($aErrorList as $sErrorLabel => $aError)
{
fwrite($fReport, "\r\n-- \r\n");
fwrite($fReport, '-- Class: '.MetaModel::GetName($sClass).' ('.$sClass.")\r\n");
fwrite($fReport, "\r\n----------\r\n");
fwrite($fReport, 'Class: '.MetaModel::GetName($sClass).' ('.$sClass.")\r\n");
$iCount = $aError['count'];
fwrite($fReport, '-- Count: '.$iCount."\r\n");
fwrite($fReport, '-- Error: '.$sErrorLabel."\r\n");
fwrite($fReport, 'Count: '.$iCount."\r\n");
fwrite($fReport, 'Error: '.$sErrorLabel."\r\n");
$sQuery = $aError['query'];
fwrite($fReport, '-- Query: '.$sQuery."\r\n");
fwrite($fReport, 'Query: '.$sQuery."\r\n");
if (isset($aError['fixit']))
{
fwrite($fReport, "\r\n-- Fix it (indication):\r\n\r\n");
fwrite($fReport, "\r\nFix it (indication):\r\n\r\n");
$aFixitQueries = $aError['fixit'];
foreach ($aFixitQueries as $sFixitQuery)
{
@@ -54,26 +51,31 @@ class DBAnalyzerUtils
fwrite($fReport, "\r\n");
}
if ($bVerbose) {
$sQueryResult = '';
$aIdList = [];
foreach ($aError['res'] as $aRes) {
$sQueryResult .= " - ";
foreach ($aRes as $sKey => $sValue) {
$sQueryResult .= "'$sKey'='$sValue' ";
if ($sKey == 'id') {
$aIdList[] = $sValue;
}
$sQueryResult = '';
$aIdList = array();
foreach ($aError['res'] as $aRes)
{
foreach ($aRes as $sKey => $sValue)
{
$sQueryResult .= "'$sKey'='$sValue' ";
if ($sKey == 'id')
{
$aIdList[] = $sValue;
}
}
fwrite($fReport, "-- Result: ".$sQueryResult);
$sIdList = '('.implode(',', $aIdList).')';
fwrite($fReport, "\r\n-- Ids: ".$sIdList."\r\n");
$sQueryResult .= "\r\n";
}
fwrite($fReport, "Result: \r\n".$sQueryResult);
$sIdList = '('.implode(',', $aIdList).')';
fwrite($fReport, 'Ids: '.$sIdList."\r\n");
}
}
fclose($fReport);
return $sDBToolsFolder.$sReportFile;
$sReportFile = $sDBToolsFolder.$sReportFile;
return $sReportFile;
}
}

View File

@@ -64,26 +64,26 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
// Lost attachments
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'DBTools:LostAttachments' => '附件丢失',
'DBTools:LostAttachments:Disclaimer' => '您可以在数据库里搜索附件是否有丢失或误挪动. 这不是数据恢复工具, 无法恢复已删除的数据.',
'DBTools:LostAttachments' => 'Lost attachments~~',
'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~',
'DBTools:LostAttachments:Button:Analyze' => '分析',
'DBTools:LostAttachments:Button:Restore' => '还原',
'DBTools:LostAttachments:Button:Restore:Confirm' => '该操作无法回退, 请确认是否继续还原.',
'DBTools:LostAttachments:Button:Busy' => '请稍后...',
'DBTools:LostAttachments:Step:Analyze' => '首先, 通过分析数据库来搜索丢失或误挪动的附件.',
'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~',
'DBTools:LostAttachments:Step:AnalyzeResults' => '分析结果:',
'DBTools:LostAttachments:Step:AnalyzeResults:None' => '非常好! 所有附件都是正常的.',
'DBTools:LostAttachments:Step:AnalyzeResults:Some' => '某些附件 (%1$d) 看起来放错了位置. 请检查下面的列表并选择要挪动的文件.',
'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.~~',
'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.~~',
'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => '文件名',
'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => '当前位置',
'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => '移动到...',
'DBTools:LostAttachments:Step:RestoreResults' => '还原结果:',
'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d 的附件已还原.',
'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.~~',
'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image~~',
'DBTools:LostAttachments:History' => 'Attachment "附件 %1$s" 已被数据库工具恢复'
'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~'
));

View File

@@ -19,7 +19,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-attachments/2.7.5',
'itop-attachments/2.7.4',
array(
// Identification
//

View File

@@ -30,10 +30,10 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Attachment:Max_Ko' => '(最大文件尺寸: %1$s KB)',
'Attachments:NoAttachment' => '没有附件. ',
'Attachments:PreviewNotAvailable' => '该附件类型不支持预览.',
'Attachments:Error:FileTooLarge' => '上传的文件过大. %1$s',
'Attachments:Error:UploadedFileEmpty' => '收到的文件为空,无法添加.
可能是因为您上传了一个空文件,,
或者咨询iTop 管理员确认iTop 服务器磁盘空间是否已满.',
'Attachments:Error:FileTooLarge' => '上传的文件过大. %1$s~~',
'Attachments:Error:UploadedFileEmpty' => 'The received file is empty and cannot be attached.
Either you have pushed an empty file,
or ask your iTop administrator if the iTop server disk is full.~~',
'Attachments:Render:Icons' => '显示为图标',
'Attachments:Render:Table' => '显示为列表',
));
@@ -47,11 +47,11 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Class:Attachment+' => '',
'Class:Attachment/Attribute:expire' => '过期',
'Class:Attachment/Attribute:expire+' => '~~',
'Class:Attachment/Attribute:temp_id' => '临时id',
'Class:Attachment/Attribute:temp_id' => '临时 id',
'Class:Attachment/Attribute:temp_id+' => '~~',
'Class:Attachment/Attribute:item_class' => 'Item class~~',
'Class:Attachment/Attribute:item_class+' => '~~',
'Class:Attachment/Attribute:item_id' => '项目',
'Class:Attachment/Attribute:item_id' => 'Item~~',
'Class:Attachment/Attribute:item_id+' => '~~',
'Class:Attachment/Attribute:item_org_id' => 'Item organization~~',
'Class:Attachment/Attribute:item_org_id+' => '',

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-backup/2.7.5',
'itop-backup/2.7.4',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-bridge-virtualization-storage/2.7.5',
'itop-bridge-virtualization-storage/2.7.4',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-change-mgmt-itil/2.7.5',
'itop-change-mgmt-itil/2.7.4',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-change-mgmt/2.7.5',
'itop-change-mgmt/2.7.4',
array(
// Identification
//

View File

@@ -86,8 +86,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Class:Change/Attribute:category/Value:hardware+' => '硬件',
'Class:Change/Attribute:category/Value:network' => '网络',
'Class:Change/Attribute:category/Value:network+' => '网络',
'Class:Change/Attribute:category/Value:other' => '其',
'Class:Change/Attribute:category/Value:other+' => '其',
'Class:Change/Attribute:category/Value:other' => '其',
'Class:Change/Attribute:category/Value:other+' => '其',
'Class:Change/Attribute:category/Value:software' => '软件',
'Class:Change/Attribute:category/Value:software+' => '软件',
'Class:Change/Attribute:category/Value:system' => '系统',

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-config-mgmt/2.7.5',
'itop-config-mgmt/2.7.4',
array(
// Identification
//

View File

@@ -365,8 +365,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Class:PhysicalDevice/Attribute:status/Value:obsolete+' => '废弃',
'Class:PhysicalDevice/Attribute:status/Value:production' => '生产',
'Class:PhysicalDevice/Attribute:status/Value:production+' => '生产',
'Class:PhysicalDevice/Attribute:status/Value:stock' => '库存',
'Class:PhysicalDevice/Attribute:status/Value:stock+' => '库存',
'Class:PhysicalDevice/Attribute:status/Value:stock' => '闲置',
'Class:PhysicalDevice/Attribute:status/Value:stock+' => '闲置',
'Class:PhysicalDevice/Attribute:brand_id' => '品牌',
'Class:PhysicalDevice/Attribute:brand_id+' => '',
'Class:PhysicalDevice/Attribute:brand_name' => '品牌名称',
@@ -868,8 +868,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Class:VirtualDevice/Attribute:status/Value:obsolete+' => '废弃',
'Class:VirtualDevice/Attribute:status/Value:production' => '生产',
'Class:VirtualDevice/Attribute:status/Value:production+' => '生产',
'Class:VirtualDevice/Attribute:status/Value:stock' => '库存',
'Class:VirtualDevice/Attribute:status/Value:stock+' => '库存',
'Class:VirtualDevice/Attribute:status/Value:stock' => '闲置',
'Class:VirtualDevice/Attribute:status/Value:stock+' => '闲置',
'Class:VirtualDevice/Attribute:logicalvolumes_list' => '逻辑卷',
'Class:VirtualDevice/Attribute:logicalvolumes_list+' => '该设备使用的所有逻辑卷',
));

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-config/2.7.5',
'itop-config/2.7.4',
array(
// Identification
//

View File

@@ -24,7 +24,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-core-update/2.7.5',
'itop-core-update/2.7.4',
array(
// Identification
//

View File

@@ -24,33 +24,33 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'iTopUpdate:UI:PageTitle' => '应用升级',
'itop-core-update:UI:SelectUpdateFile' => '应用升级',
'itop-core-update:UI:ConfirmUpdate' => ' 升级',
'itop-core-update:UI:UpdateCoreFiles' => '应用升级',
'iTopUpdate:UI:MaintenanceModeActive' => '应用正处于维护状态, 用户无法登录系统. 您必须运行安装向导或从备份中还原才能恢复到正常状态.',
'itop-core-update:UI:UpdateDone' => '应用升级',
'itop-core-update:UI:UpdateCoreFiles' => 'Application Upgrade~~',
'iTopUpdate:UI:MaintenanceModeActive' => 'The application is currently under maintenance, no user can access the application. You have to run a setup or restore the application archive to return in normal mode.~~',
'itop-core-update:UI:UpdateDone' => 'Application Upgrade~~',
'itop-core-update/Operation:SelectUpdateFile/Title' => '应用升级',
'itop-core-update/Operation:ConfirmUpdate/Title' => '确认升级',
'itop-core-update/Operation:UpdateCoreFiles/Title' => '应用升级进行中',
'itop-core-update/Operation:UpdateDone/Title' => '升级完毕',
'itop-core-update/Operation:SelectUpdateFile/Title' => 'Application Upgrade~~',
'itop-core-update/Operation:ConfirmUpdate/Title' => 'Confirm Application Upgrade~~',
'itop-core-update/Operation:UpdateCoreFiles/Title' => 'Application Upgrading~~',
'itop-core-update/Operation:UpdateDone/Title' => 'Application Upgrade Done~~',
'iTopUpdate:UI:SelectUpdateFile' => '请选择要上传的升级文件',
'iTopUpdate:UI:CheckUpdate' => '校验升级文件',
'iTopUpdate:UI:ConfirmInstallFile' => '即将安装 %1$s',
'iTopUpdate:UI:DoUpdate' => '升级',
'iTopUpdate:UI:CurrentVersion' => '当前已安装的版本',
'iTopUpdate:UI:NewVersion' => '新安装的版本',
'iTopUpdate:UI:NewVersion' => 'Newly installed version~~',
'iTopUpdate:UI:Back' => '返回',
'iTopUpdate:UI:Cancel' => '取消',
'iTopUpdate:UI:Continue' => '继续',
'iTopUpdate:UI:RunSetup' => '运行安装向导',
'iTopUpdate:UI:RunSetup' => 'Run Setup~~',
'iTopUpdate:UI:WithDBBackup' => '数据库备份',
'iTopUpdate:UI:WithFilesBackup' => '应用文件备份',
'iTopUpdate:UI:WithoutBackup' => '暂时没有备份计划',
'iTopUpdate:UI:WithoutBackup' => 'No backup is planned~~',
'iTopUpdate:UI:Backup' => '升级之前执行备份',
'iTopUpdate:UI:DoFilesArchive' => '打包应用文件',
'iTopUpdate:UI:UploadArchive' => '请选择要上传的包',
'iTopUpdate:UI:ServerFile' => '软件包已在服务器上',
'iTopUpdate:UI:WarningReadOnlyDuringUpdate' => '在升级期间, 应用会变成只读状态.',
'iTopUpdate:UI:UploadArchive' => 'Select a package to upload~~',
'iTopUpdate:UI:ServerFile' => 'Path of a package already on the server~~',
'iTopUpdate:UI:WarningReadOnlyDuringUpdate' => 'During the upgrade, the application will be read-only.~~',
'iTopUpdate:UI:Status' => '状态',
'iTopUpdate:UI:Action' => '升级',
@@ -74,7 +74,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'iTopUpdate:UI:CanCoreUpdate:Failed' => '文件系统检查失败',
'iTopUpdate:UI:CanCoreUpdate:Yes' => '应用无法升级',
'iTopUpdate:UI:CanCoreUpdate:No' => '应用无法升级: %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => '警告: 应用升级可能会失败: %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Warning: application update can fail: %1$s~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => '准备开始',
@@ -82,9 +82,9 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'iTopUpdate:UI:SetupMessage:Backup' => '数据库备份',
'iTopUpdate:UI:SetupMessage:FilesArchive' => '打包应用文件',
'iTopUpdate:UI:SetupMessage:CopyFiles' => '复制新文件',
'iTopUpdate:UI:SetupMessage:CheckCompile' => '检查更新',
'iTopUpdate:UI:SetupMessage:CheckCompile' => 'Check application upgrade~~',
'iTopUpdate:UI:SetupMessage:Compile' => '升级应用程序和数据库',
'iTopUpdate:UI:SetupMessage:UpdateDatabase' => '升级数据库',
'iTopUpdate:UI:SetupMessage:UpdateDatabase' => 'Upgrade database~~',
'iTopUpdate:UI:SetupMessage:ExitMaintenance' => '正在退出维护模式',
'iTopUpdate:UI:SetupMessage:UpdateDone' => '升级完成',
@@ -109,7 +109,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Menu:iTopUpdate+' => '应用升级',
// Missing itop entries
'Class:ModuleInstallation/Attribute:installed' => '安装时间',
'Class:ModuleInstallation/Attribute:installed' => '安装',
'Class:ModuleInstallation/Attribute:name' => '名称',
'Class:ModuleInstallation/Attribute:version' => '版本',
'Class:ModuleInstallation/Attribute:comment' => '备注',

View File

@@ -18,7 +18,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-datacenter-mgmt/2.7.5',
'itop-datacenter-mgmt/2.7.4',
array(
// Identification
//

View File

@@ -25,7 +25,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-endusers-devices/2.7.5',
'itop-endusers-devices/2.7.4',
array(
// Identification
//

View File

@@ -24,7 +24,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-files-information/2.7.5',
'itop-files-information/2.7.4',
array(
// Identification
//

View File

@@ -6,7 +6,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-full-itil/2.7.5',
'itop-full-itil/2.7.4',
array(
// Identification
//

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-hub-connector/2.7.5',
'itop-hub-connector/2.7.4',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-incident-mgmt-itil/2.7.5',
'itop-incident-mgmt-itil/2.7.4',
array(
// Identification
//

View File

@@ -144,9 +144,9 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Class:Incident/Attribute:cumulatedpending' => 'Pendências acumuladas',
'Class:Incident/Attribute:cumulatedpending+' => '',
'Class:Incident/Attribute:tto' => 'TTO',
'Class:Incident/Attribute:tto+' => 'Tempo de atribuição',
'Class:Incident/Attribute:tto+' => '',
'Class:Incident/Attribute:ttr' => 'TTR',
'Class:Incident/Attribute:ttr+' => 'Tempo de resolução',
'Class:Incident/Attribute:ttr+' => '',
'Class:Incident/Attribute:tto_escalation_deadline' => 'Prazo determinado TTO',
'Class:Incident/Attribute:tto_escalation_deadline+' => '',
'Class:Incident/Attribute:sla_tto_passed' => 'SLA TTO passou',

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-knownerror-mgmt/2.7.5',
'itop-knownerror-mgmt/2.7.4',
array(
// Identification
//

View File

@@ -63,8 +63,6 @@ Dict::Add('EN US', 'English', 'English', array(
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Open</a> / <a href="%4$s" class="file_download_link">Download</a>',
'Portal:Calendar-FirstDayOfWeek' => 'en-us', //work with moment.js locales
'Portal:Form:Close:Warning' => 'Do you want to leave this form ? Data entered may be lost',
'Portal:Error:ObjectCannotBeCreated' => 'Error: object cannot be created. Check associated objects and attachments before submitting again this form.',
'Portal:Error:ObjectCannotBeUpdated' => 'Error: object cannot be updated. Check associated objects and attachments before submitting again this form.',
));
// UserProfile brick

View File

@@ -62,8 +62,6 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Portal:File:DisplayInfo+' => '%1$s (%2$s) <a href="%3$s" class="file_open_link" target="_blank">Ouvrir</a> / <a href="%4$s" class="file_download_link">Télécharger</a>',
'Portal:Calendar-FirstDayOfWeek' => 'fr', //work with moment.js locales
'Portal:Form:Close:Warning' => 'Voulez-vous quitter ce formulaire ? Les données saisies seront perdues',
'Portal:Error:ObjectCannotBeCreated' => 'Erreur: L\'objet n\'a pas été créé. Vérifiez les objets liés et les attachements avant de soumettre à nouveau le formulaire.',
'Portal:Error:ObjectCannotBeUpdated' => 'Erreur: L\'objet n\'a pas été modifié. Vérifiez les objets liés et les attachements avant de soumettre à nouveau le formulaire.',
));
// UserProfile brick

View File

@@ -20,7 +20,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-portal-base/2.7.5', array(
'itop-portal-base/2.7.4', array(
// Identification
'label' => 'Portal Development Library',
'category' => 'Portal',

View File

@@ -30,8 +30,6 @@ use DBObjectSearch;
use DBObjectSet;
use DBSearch;
use FieldExpression;
use IssueLog;
use LogChannels;
use MetaModel;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
@@ -67,8 +65,6 @@ class BrowseBrickController extends BrickController
*/
public function DisplayAction(Request $oRequest, $sBrickId, $sBrowseMode = null, $sDataLoading = null)
{
$sPortalId = $this->getParameter('combodo.portal.instance.id');
/** @var \Combodo\iTop\Portal\Helper\BrowseBrickHelper $oBrowseBrickHelper */
$oBrowseBrickHelper = $this->get('browse_brick');
/** @var \Combodo\iTop\Portal\Helper\RequestManipulatorHelper $oRequestManipulator */
@@ -270,7 +266,8 @@ class BrowseBrickController extends BrickController
// Note : This could be way more simpler if we had a SetInternalParam($sParam, $value) verb
$aQueryParams = $aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->GetInternalParams();
// Note : $iSearchloopMax was initialized on the previous loop
for ($j = 0; $j <= $iSearchLoopMax; $j++) {
for ($j = 0; $j <= $iSearchLoopMax; $j++)
{
$aQueryParams['search_value_'.$j] = '%'.$aSearchValues[$j].'%';
}
$aLevelsProperties[$aLevelsPropertiesKeys[$i]]['search']->SetInternalParams($aQueryParams);
@@ -280,11 +277,12 @@ class BrowseBrickController extends BrickController
$oQuery = $aLevelsProperties[$aLevelsPropertiesKeys[0]]['search'];
// Testing appropriate data loading mode if we are in auto
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_AUTO) {
if ($sDataLoading === AbstractBrick::ENUM_DATA_LOADING_AUTO)
{
// - Check how many records there is.
// - Update $sDataLoading with its new value regarding the number of record and the threshold
$oCountSet = new DBObjectSet($oQuery);
$fThreshold = (float)MetaModel::GetModuleSetting($sPortalId,
$fThreshold = (float)MetaModel::GetModuleSetting($this->getParameter('combodo.portal.instance.id'),
'lazy_loading_threshold');
$sDataLoading = ($oCountSet->Count() > $fThreshold) ? AbstractBrick::ENUM_DATA_LOADING_LAZY : AbstractBrick::ENUM_DATA_LOADING_FULL;
unset($oCountSet);
@@ -442,21 +440,17 @@ class BrowseBrickController extends BrickController
}
}
IssueLog::Debug('Portal BrowseBrick query', LogChannels::PORTAL, array(
'sPortalId' => $sPortalId,
'sBrickId' => $sBrickId,
'oql' => $oSet->GetFilter()->ToOQL(),
));
// Preparing response
if ($oRequest->isXmlHttpRequest()) {
if ($oRequest->isXmlHttpRequest())
{
$aData = $aData + array(
'data' => $aItems,
'levelsProperties' => $aLevelsProperties,
);
$oResponse = new JsonResponse($aData);
} else {
}
else
{
$aData = $aData + array(
'oBrick' => $oBrick,
'sBrickId' => $sBrickId,

View File

@@ -41,14 +41,13 @@ use Dict;
use Exception;
use FieldExpression;
use iPopupMenuExtension;
use IssueLog;
use JSButtonItem;
use LogChannels;
use MetaModel;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use UnaryExpression;
use URLButtonItem;
use VariableExpression;
/**
* Class ManageBrickController
@@ -90,10 +89,10 @@ class ManageBrickController extends BrickController
/** @var \Combodo\iTop\Portal\Brick\ManageBrick $oBrick */
$oBrick = $oBrickCollection->GetBrickById($sBrickId);
if (is_null($sDisplayMode)) {
if (is_null($sDisplayMode))
{
$sDisplayMode = $oBrick->GetDefaultDisplayMode();
}
$aData = $this->GetData($oRequest, $sBrickId, $sGroupingTab, $oBrick::AreDetailsNeededForDisplayMode($sDisplayMode));
$aExportFields = $oBrick->GetExportFields();
@@ -103,7 +102,8 @@ class ManageBrickController extends BrickController
'iDefaultListLength' => $oBrick->GetDefaultListLength(),
);
// Preparing response
if ($oRequest->isXmlHttpRequest()) {
if ($oRequest->isXmlHttpRequest())
{
$oResponse = new JsonResponse($aData);
}
else
@@ -814,31 +814,30 @@ class ManageBrickController extends BrickController
'aColumnsDefinition' => $aColumnsDefinition,
);
}
IssueLog::Debug('Portal ManageBrick query', LogChannels::PORTAL, array(
'sPortalId' => $sPortalId,
'sBrickId' => $sBrickId,
'sGroupingTab' => $sGroupingTab,
'oql' => $oSet->GetFilter()->ToOQL(),
'aGroupingTabs' => $aGroupingTabs,
));
} else {
}
else
{
$aGroupingAreasData = array();
$sGroupingArea = null;
}
// Preparing response
if ($oRequest->isXmlHttpRequest()) {
if ($oRequest->isXmlHttpRequest())
{
$aData = $aData + array(
'data' => $aGroupingAreasData[$sGroupingArea]['aItems'],
);
} else {
}
else
{
$aDisplayValues = array();
$aUrls = array();
$aColumns = array();
$aNames = array();
if ($bHasScope) {
foreach ($aGroupingTabsValues as $aValues) {
if ($bHasScope)
{
foreach ($aGroupingTabsValues as $aValues)
{
$aDisplayValues[] = array(
'value' => $aValues['count'],
'label' => $aValues['label'],

View File

@@ -639,7 +639,7 @@ class ObjectController extends BrickController
$oSet = new DBObjectSet($oSearch, array(), array('this' => $oHostObject, 'ac_query' => '%'.$sQuery.'%'));
$oSet->OptimizeColumnLoad(array($oSearch->GetClassAlias() => array('friendlyname')));
// Note : This limit is also used in the field renderer by typeahead to determine how many suggestions to display
$oSet->SetLimit(MetaModel::GetConfig()->GetMaxDisplayLimit());
$oSet->SetLimit(MetaModel::GetConfig()->Get('max_display_limit'));
// - Retrieving objects
while ($oItem = $oSet->Fetch())

View File

@@ -25,12 +25,14 @@ use AttributeDateTime;
use AttributeTagSet;
use CMDBChangeOpAttachmentAdded;
use CMDBChangeOpAttachmentRemoved;
use CMDBSource;
use Combodo\iTop\Form\Field\Field;
use Combodo\iTop\Form\Field\FileUploadField;
use Combodo\iTop\Form\Field\LabelField;
use Combodo\iTop\Form\Form;
use Combodo\iTop\Form\FormManager;
use Combodo\iTop\Portal\Helper\ApplicationHelper;
use CoreCannotSaveObjectException;
use DBObject;
use DBObjectSearch;
use DBObjectSet;
@@ -78,12 +80,6 @@ class ObjectFormManager extends FormManager
protected $aFormProperties;
/** @var array $aCallbackUrls */
protected $aCallbackUrls = array();
/**
* List of hidden fields, used for form update (eg. remove them from the form regarding they dependencies)
* @var array $aHiddenFieldsId
* @since 2.7.5
*/
protected $aHiddenFieldsId = array();
/**
* Creates an instance of \Combodo\iTop\Portal\Form\ObjectFormManager from JSON data that must contain at least :
@@ -947,8 +943,6 @@ class ObjectFormManager extends FormManager
if($oField->GetHidden() === false)
{
$oForm->AddField($oField);
} else {
$this->aHiddenFieldsId[]=$oField->GetId();
}
}
@@ -1114,28 +1108,30 @@ class ObjectFormManager extends FormManager
return $aData;
}
$sObjectClass = get_class($this->oObject);
// The try catch is essentially to start a MySQL transaction in order to ensure that all or none objects are persisted when creating an object with links
try
{
$sObjectClass = get_class($this->oObject);
try {
// Starting transaction
CMDBSource::Query('START TRANSACTION');
// Forcing allowed writing on the object if necessary. This is used in some particular cases.
$bAllowWrite = ($sObjectClass === 'Person' && $this->oObject->GetKey() == UserRights::GetContactId());
if ($bAllowWrite) {
if ($bAllowWrite)
{
$this->oObject->AllowWrite(true);
}
// Writing object to DB
$bIsNew = $this->oObject->IsNew();
$bActivateTriggers = (!$this->oObject->IsNew() && $this->oObject->IsModified());
$bWasModified = $this->oObject->IsModified();
$bActivateTriggers = (!$bIsNew && $bWasModified);
try
{
$this->oObject->DBWrite();
}
catch (Exception $e) {
if ($bIsNew) {
throw new Exception(Dict::S('Portal:Error:ObjectCannotBeCreated'));
}
throw new Exception(Dict::S('Portal:Error:ObjectCannotBeUpdated'));
catch (CoreCannotSaveObjectException $e)
{
throw new Exception($e->getHtmlMessage());
}
// Finalizing images link to object, otherwise it will be cleaned by the GC
InlineImage::FinalizeInlineImages($this->oObject);
@@ -1146,6 +1142,9 @@ class ObjectFormManager extends FormManager
$this->FinalizeAttachments($aArgs['attachmentIds']);
}
// Ending transaction with a commit as everything was fine
CMDBSource::Query('COMMIT');
// Checking if we have to apply a stimulus
if (isset($aArgs['applyStimulus']))
{
@@ -1193,11 +1192,14 @@ class ObjectFormManager extends FormManager
}
catch (Exception $e)
{
// End transaction with a rollback as something failed
CMDBSource::Query('ROLLBACK');
$aData['valid'] = false;
$aData['messages']['error'] += array('_main' => array($e->getMessage()));
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : '.$e->getMessage());
IssueLog::Error(__METHOD__.' at line '.__LINE__.' : Rollback during submit ('.$e->getMessage().')');
}
return $aData;
}
@@ -1480,22 +1482,4 @@ class ObjectFormManager extends FormManager
}
return $oChangeOp;
}
/**
* @return array
* @since 2.7.5
*/
public function GetHiddenFieldsId()
{
return $this->aHiddenFieldsId;
}
/**
* @param array $aHiddenFieldsId
* @since 2.7.5
*/
public function SetHiddenFieldsId($aHiddenFieldsId)
{
$this->aHiddenFieldsId = $aHiddenFieldsId;
}
}

View File

@@ -280,8 +280,8 @@ class ObjectFormHandlerHelper
->SetFormProperties($aFormProperties);
$oFormManager->Build();
$aFormData['hidden_fields'] = $oFormManager->GetHiddenFieldsId();
// Check the number of editable fields
// Check the number of editable fields
$aFormData['editable_fields_count'] = $oFormManager->GetForm()->GetEditableFieldCount();
}
else
@@ -388,7 +388,6 @@ class ObjectFormHandlerHelper
$aFormData['object_state'] = $oFormManager->GetObject()->GetState();
$aFormData['fieldset'] = $aFieldSetData;
$aFormData['display_mode'] = (isset($aFormProperties['properties'])) ? $aFormProperties['properties']['display_mode'] : ApplicationHelper::FORM_DEFAULT_DISPLAY_MODE;
$aFormData['hidden_fields'] = $oFormManager->GetHiddenFieldsId();
// - Set a text to be copied on title if the object is not in creation
if($sMode !== static::ENUM_MODE_CREATE && !empty($sObjectId))
{

View File

@@ -397,16 +397,15 @@
}
}
};
// N°3995: Loader is shown immediately, otherwise when we have a huge amount of items, we can have a bottleneck on the buildMosaic() function, blocking the display of the loader
showMosaicLoader();
$(document).ready(function(){
// Auto collapse item actions popup
$('body').click(function(){
$('#brick_content_mosaic .item-action-wrapper.collapse.in').collapse('hide');
});
// Build the mosaic (collapsed)
// Build the tree (collapsed)
showMosaicLoader();
buildMosaic(oRawDatas);
hideMosaicLoader();
registerFilterListeners();

View File

@@ -321,8 +321,6 @@
}
};
// N°3995: Loader is shown immediately, otherwise when we have a huge amount of items, we can have a bottleneck on the buildTree() function, blocking the display of the loader
showTreeLoader();
$(document).ready(function(){
// Init expand/collapse all buttons
$('#btn-collapse-all').on('click', function (oEvent) {
@@ -407,6 +405,7 @@
});
// Build the tree (collapsed)
showTreeLoader();
buildTree(oRawDatas);
hideTreeLoader();
registerFilterListeners();

View File

@@ -480,10 +480,6 @@
{
ShowErrorDialog('{{ 'UI:ObjectDoesNotExist'|dict_s|escape('js') }}', '{{ 'Error:HTTP:404'|dict_s|escape('js') }}');
}
else if(oXHR.status === 0 && oXHR.readyState === 0)
{
//DO NOTHING the ajax call has been aborted
}
else if(oXHR.responseText !== undefined && IsJSONString(oXHR.responseText) === true)
{
var oData = JSON.parse(oXHR.responseText);

View File

@@ -20,7 +20,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-portal/2.7.5', array(
'itop-portal/2.7.4', array(
// Identification
'label' => 'Enhanced Customer Portal',
'category' => 'Portal',

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-problem-mgmt/2.7.5',
'itop-problem-mgmt/2.7.4',
array(
// Identification
//

View File

@@ -19,7 +19,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-profiles-itil/2.7.5',
'itop-profiles-itil/2.7.4',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-request-mgmt-itil/2.7.5',
'itop-request-mgmt-itil/2.7.4',
array(
// Identification
//

View File

@@ -164,9 +164,9 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Class:UserRequest/Attribute:cumulatedpending' => 'Pendências acumuladas',
'Class:UserRequest/Attribute:cumulatedpending+' => '',
'Class:UserRequest/Attribute:tto' => 'TTO',
'Class:UserRequest/Attribute:tto+' => 'Tempo de atribuição',
'Class:UserRequest/Attribute:tto+' => '',
'Class:UserRequest/Attribute:ttr' => 'TTR',
'Class:UserRequest/Attribute:ttr+' => 'Tempo de resolução',
'Class:UserRequest/Attribute:ttr+' => '',
'Class:UserRequest/Attribute:tto_escalation_deadline' => 'Prazo determinado TTO',
'Class:UserRequest/Attribute:tto_escalation_deadline+' => '',
'Class:UserRequest/Attribute:sla_tto_passed' => 'SLA TTO passou',

View File

@@ -188,8 +188,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Class:UserRequest/Attribute:resolution_code/Value:bug fixed+' => 'bug修复',
'Class:UserRequest/Attribute:resolution_code/Value:hardware repair' => '硬件维修',
'Class:UserRequest/Attribute:resolution_code/Value:hardware repair+' => '硬件维修',
'Class:UserRequest/Attribute:resolution_code/Value:other' => '其',
'Class:UserRequest/Attribute:resolution_code/Value:other+' => '其',
'Class:UserRequest/Attribute:resolution_code/Value:other' => '其',
'Class:UserRequest/Attribute:resolution_code/Value:other+' => '其',
'Class:UserRequest/Attribute:resolution_code/Value:software patch' => '软件补丁',
'Class:UserRequest/Attribute:resolution_code/Value:software patch+' => '软件补丁',
'Class:UserRequest/Attribute:resolution_code/Value:system update' => '系统更新',
@@ -214,7 +214,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Class:UserRequest/Attribute:parent_change_id+' => '',
'Class:UserRequest/Attribute:parent_change_ref' => '变更编号',
'Class:UserRequest/Attribute:parent_change_ref+' => '',
'Class:UserRequest/Attribute:parent_incident_ref' => '父级事件编号',
'Class:UserRequest/Attribute:parent_incident_ref' => 'Parent incident ref~~',
'Class:UserRequest/Attribute:parent_incident_ref+' => '~~',
'Class:UserRequest/Attribute:related_request_list' => '子需求',
'Class:UserRequest/Attribute:related_request_list+' => '该父级需求相关的所有子需求',

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-request-mgmt/2.7.5',
'itop-request-mgmt/2.7.4',
array(
// Identification
//

View File

@@ -170,9 +170,9 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Class:UserRequest/Attribute:cumulatedpending' => 'Pendências acumuladas',
'Class:UserRequest/Attribute:cumulatedpending+' => '',
'Class:UserRequest/Attribute:tto' => 'TTO',
'Class:UserRequest/Attribute:tto+' => 'Tempo de atribuição',
'Class:UserRequest/Attribute:tto+' => '',
'Class:UserRequest/Attribute:ttr' => 'TTR',
'Class:UserRequest/Attribute:ttr+' => 'Tempo de resolução',
'Class:UserRequest/Attribute:ttr+' => '',
'Class:UserRequest/Attribute:tto_escalation_deadline' => 'Prazo determinado TTO',
'Class:UserRequest/Attribute:tto_escalation_deadline+' => '',
'Class:UserRequest/Attribute:sla_tto_passed' => 'SLA TTO passou',

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-service-mgmt-provider/2.7.5',
'itop-service-mgmt-provider/2.7.4',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-service-mgmt/2.7.5',
'itop-service-mgmt/2.7.4',
array(
// Identification
//

View File

@@ -18,7 +18,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-sla-computation/2.7.5',
'itop-sla-computation/2.7.4',
array(
// Identification
//

View File

@@ -25,7 +25,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-storage-mgmt/2.7.5',
'itop-storage-mgmt/2.7.4',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__,
'itop-tickets/2.7.5',
'itop-tickets/2.7.4',
array(
// Identification
//

View File

@@ -16,7 +16,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-virtualization-mgmt/2.7.5',
'itop-virtualization-mgmt/2.7.4',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-welcome-itil/2.7.5',
'itop-welcome-itil/2.7.4',
array(
// Identification
//

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<information>
<version>2.7.5</version>
<version>2.7.4</version>
</information>

View File

@@ -203,9 +203,9 @@ Operators:<br/>
'Core:AttributeTag' => '标签',
'Core:AttributeTag+' => '标签',
'Core:Context=REST/JSON' => 'REST',
'Core:Context=REST/JSON' => 'REST~~',
'Core:Context=Synchro' => 'Synchro~~',
'Core:Context=Setup' => '安装向导',
'Core:Context=Setup' => 'Setup~~',
'Core:Context=GUI:Console' => 'Console~~',
'Core:Context=CRON' => 'cron~~',
'Core:Context=GUI:Portal' => 'Portal~~',
@@ -536,12 +536,12 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Class:Trigger' => '触发器',
'Class:Trigger+' => 'Custom event handler',
'Class:Trigger/Attribute:description' => '描述',
'Class:Trigger/Attribute:description+' => '简短描述',
'Class:Trigger/Attribute:description+' => '一行描述',
'Class:Trigger/Attribute:action_list' => '触发的行为',
'Class:Trigger/Attribute:action_list+' => 'Actions performed when the trigger is activated',
'Class:Trigger/Attribute:finalclass' => '触发器子类别',
'Class:Trigger/Attribute:finalclass+' => 'Name of the final class',
'Class:Trigger/Attribute:context' => '上下文',
'Class:Trigger/Attribute:context' => 'Context~~',
'Class:Trigger/Attribute:context+' => 'Context to allow the trigger to start~~',
));
@@ -632,11 +632,11 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
//
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Class:TriggerOnThresholdReached' => '触发器 (基于值)',
'Class:TriggerOnThresholdReached+' => '当达到某个值时触发',
'Class:TriggerOnThresholdReached' => '触发器 (基于值)',
'Class:TriggerOnThresholdReached+' => '当达到某个值时触发',
'Class:TriggerOnThresholdReached/Attribute:stop_watch_code' => '秒表',
'Class:TriggerOnThresholdReached/Attribute:stop_watch_code+' => '',
'Class:TriggerOnThresholdReached/Attribute:threshold_index' => '值',
'Class:TriggerOnThresholdReached/Attribute:threshold_index' => '值',
'Class:TriggerOnThresholdReached/Attribute:threshold_index+' => '',
));
@@ -743,8 +743,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Class:SynchroDataSource/Error:DeleteRetentionDurationMustBeSpecified' => 'A delete retention period must be specified, since objects are to be deleted after being marked as obsolete',
'Class:SynchroDataSource/Error:DeletePolicyUpdateMustBeSpecified' => 'Obsolete objects are to be updated, but no update is specified.',
'Class:SynchroDataSource/Error:DataTableAlreadyExists' => 'The table %1$s already exists in the database. Please use another name for the synchro data table.',
'Core:SynchroReplica:PublicData' => '公共数据',
'Core:SynchroReplica:PrivateDetails' => '专属详情',
'Core:SynchroReplica:PublicData' => 'Public Data',
'Core:SynchroReplica:PrivateDetails' => 'Private Details',
'Core:SynchroReplica:BackToDataSource' => '返回同步数据源: %1$s',
'Core:SynchroReplica:ListOfReplicas' => 'List of Replica',
'Core:SynchroAttExtKey:ReconciliationById' => 'id (Primary Key)',
@@ -918,11 +918,11 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Core:BulkExport:OptionLinkSets' => '包含外链的对象',
'Core:BulkExport:OptionFormattedText' => '保持文本格式',
'Core:BulkExport:ScopeDefinition' => '定义要导出的对象',
'Core:BulkExportLabelOQLExpression' => 'OQL 查询:',
'Core:BulkExportLabelOQLExpression' => 'OQL Query:',
'Core:BulkExportLabelPhrasebookEntry' => 'Query Phrasebook Entry:',
'Core:BulkExportMessageEmptyOQL' => '请输入有效的OQL 查询.',
'Core:BulkExportMessageEmptyOQL' => 'Please enter a valid OQL query.',
'Core:BulkExportMessageEmptyPhrasebookEntry' => 'Please select a valid phrasebook entry.',
'Core:BulkExportQueryPlaceholder' => '请在这里输入OQL 查询...',
'Core:BulkExportQueryPlaceholder' => 'Type an OQL query here...',
'Core:BulkExportCanRunNonInteractive' => '点击这里运行非交互式导出.',
'Core:BulkExportLegacyExport' => '点击这里进入旧版导出.',
'Core:BulkExport:XLSXOptions' => 'Excel 选项',
@@ -959,7 +959,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Class:TagSetFieldData+' => '~~',
'Class:TagSetFieldData/Attribute:code' => '代码',
'Class:TagSetFieldData/Attribute:code+' => '内部代码. 必须至少包含3个数字或字母',
'Class:TagSetFieldData/Attribute:code+' => 'Internal code. Must contain at least 3 alphanumeric characters~~',
'Class:TagSetFieldData/Attribute:label' => '标签',
'Class:TagSetFieldData/Attribute:label+' => '显示的标签',
'Class:TagSetFieldData/Attribute:description' => '描述',

View File

@@ -418,15 +418,15 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'UI:Button:Insert' => '插入',
'UI:Button:More' => '更多',
'UI:Button:Less' => '更少',
'UI:Button:Wait' => '请稍候,正在更新字段',
'UI:Treeview:CollapseAll' => '全部折叠',
'UI:Treeview:ExpandAll' => '全部展开',
'UI:Button:Wait' => 'Please wait while updating fields~~',
'UI:Treeview:CollapseAll' => 'Collapse All~~',
'UI:Treeview:ExpandAll' => 'Expand All~~',
'UI:SearchToggle' => '搜索',
'UI:ClickToCreateNew' => '新建 %1$s',
'UI:SearchFor_Class' => '搜索 %1$s ',
'UI:NoObjectToDisplay' => '没有可显示的对象.',
'UI:Error:SaveFailed' => '对象无法被保存 :',
'UI:Error:SaveFailed' => 'The object cannot be saved :~~',
'UI:Error:MandatoryTemplateParameter_object_id' => '当link_attr 被指定时,参数 object_id 是必须的. 检查显示模板的定义.',
'UI:Error:MandatoryTemplateParameter_target_attr' => '当link_attr 被指定时, 参数 target_attr 是必须的. 检查显示模板的定义.',
'UI:Error:MandatoryTemplateParameter_group_by' => '参数 group_by 是必须的. 检查显示模板的定义.',
@@ -459,8 +459,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'UI:Error:Invalid_Stimulus_On_Object_In_State' => '错误: 在对象 %2$s 的 "%3$s" 状态上的无效刺激 "%1$s" .',
'UI:Error:InvalidDashboardFile' => 'Error: invalid dashboard file~~',
'UI:Error:InvalidDashboard' => 'Error: invalid dashboard~~',
'UI:Error:MaintenanceMode' => '应用正在维护中',
'UI:Error:MaintenanceTitle' => '维护',
'UI:Error:MaintenanceMode' => 'Application is currently in maintenance~~',
'UI:Error:MaintenanceTitle' => 'Maintenance~~',
'UI:GroupBy:Count' => '个数',
'UI:GroupBy:Count+' => '元素数量',
@@ -527,7 +527,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'UI:Login:ForgotPwdForm+' => 'iTop 将会给您发送一封密码重置邮件.',
'UI:Login:ResetPassword' => '立即发送!',
'UI:Login:ResetPwdFailed' => '邮件发送失败: %1$s',
'UI:Login:SeparatorOr' => '或者',
'UI:Login:SeparatorOr' => 'Or~~',
'UI:ResetPwd-Error-WrongLogin' => '\'%1$s\' 用户名无效',
'UI:ResetPwd-Error-NotPossible' => '外部账户不允许重置密码.',
@@ -786,7 +786,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'UI:Title:BulkDeletionOf_Count_ObjectsOf_Class' => '批量删除 %1$d 个 %2$s 类的对象',
'UI:Delete:NotAllowedToDelete' => '您无权删除该对象',
'UI:Delete:NotAllowedToUpdate_Fields' => '您无权更新以下栏目: %1$s',
'UI:Error:ActionNotAllowed' => '您无权进行操作',
'UI:Error:ActionNotAllowed' => 'You are not allowed to do this action~~',
'UI:Error:NotEnoughRightsToDelete' => '无法删除该对象, 因为当前用户没有足够的权限',
'UI:Error:CannotDeleteBecause' => '无法删除该对象,因为: %1$s',
'UI:Error:CannotDeleteBecauseOfDepencies' => '无法删除该对象, 因为必须事先完成一些手动操作',
@@ -901,7 +901,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Menu:AdminTools' => '管理工具', // Duplicated into itop-welcome-itil (will be removed from here...)
'Menu:AdminTools+' => '管理工具', // Duplicated into itop-welcome-itil (will be removed from here...)
'Menu:AdminTools?' => '具有管理员角色的用户才能获得的工具', // Duplicated into itop-welcome-itil (will be removed from here...)
'Menu:SystemTools' => '系统',
'Menu:SystemTools' => 'System~~',
'UI:ChangeManagementMenu' => '变更管理',
'UI:ChangeManagementMenu+' => '变更管理',
@@ -1039,9 +1039,9 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'UI:RelationGroups' => '组',
'UI:OperationCancelled' => '操作已取消',
'UI:ElementsDisplayed' => '过滤',
'UI:RelationGroupNumber_N' => '分组 #%1$d',
'UI:RelationGroupNumber_N' => 'Group #%1$d',
'UI:Relation:ExportAsPDF' => '导出PDF...',
'UI:RelationOption:GroupingThreshold' => '分组值',
'UI:RelationOption:GroupingThreshold' => '分组值',
'UI:Relation:AdditionalContextInfo' => '其他信息',
'UI:Relation:NoneSelected' => '无',
'UI:Relation:Zoom' => '放大',
@@ -1065,7 +1065,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'UI:PageOrientation_Landscape' => '横向',
'UI:RelationTooltip:Redundancy' => '冗余',
'UI:RelationTooltip:ImpactedItems_N_of_M' => '# 受影响的项目: %1$d / %2$d',
'UI:RelationTooltip:CriticalThreshold_N_of_M' => '值: %1$d / %2$d',
'UI:RelationTooltip:CriticalThreshold_N_of_M' => '值: %1$d / %2$d',
'Portal:Title' => 'iTop 用户门户',
'Portal:NoRequestMgmt' => '亲爱的 %1$s, 您被重定向到这个页面,因为您的账户已被设置成角色 \'Portal user\'. 并且, iTop 没有安装 \'需求管理\' 功能. 请联系管理员.',
'Portal:Refresh' => '刷新',
@@ -1111,7 +1111,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'UI:ModifiedObject' => '对象已修改',
'UI:BulkModifyStatus' => '操作',
'UI:BulkModifyStatus+' => '操作状态',
'UI:BulkModifyErrors' => '报错 (如果有)',
'UI:BulkModifyErrors' => 'Errors (if any)',
'UI:BulkModifyErrors+' => '阻止修改时报错',
'UI:BulkModifyStatusOk' => 'Ok',
'UI:BulkModifyStatusError' => '错误',
@@ -1161,8 +1161,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'UI:PrintResolution:FullSize' => '全尺寸',
'UI:PrintResolution:A4Portrait' => 'A4 纵向',
'UI:PrintResolution:A4Landscape' => 'A4 横向',
'UI:PrintResolution:LetterPortrait' => '纵向排版',
'UI:PrintResolution:LetterLandscape' => '横向排版',
'UI:PrintResolution:LetterPortrait' => 'Letter Portrait~~',
'UI:PrintResolution:LetterLandscape' => 'Letter Landscape~~',
'UI:Toggle:StandardDashboard' => '标准',
'UI:Toggle:CustomDashboard' => '自定义',
@@ -1444,7 +1444,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'UI:Button:RemoveImage' => '移除图片',
'UI:UploadNotSupportedInThisMode' => '本模式下不支持修改文件或图片.',
'UI:Button:RemoveDocument' => '移除文档',
'UI:Button:RemoveDocument' => 'Remove the document~~',
// Search form
'UI:Search:Toggle' => '折叠 / 展开',
@@ -1490,7 +1490,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'UI:Search:Criteria:Title:Enum:In:Many' => '%1$s: %2$s 和 %3$s others',
'UI:Search:Criteria:Title:Enum:In:All' => '%1$s: 任何',
// - TagSet widget
'UI:Search:Criteria:Title:TagSet:Matches' => '%1$s: %2$s',
'UI:Search:Criteria:Title:TagSet:Matches' => '%1$s: %2$s~~',
// - External key widget
'UI:Search:Criteria:Title:ExternalKey:Empty' => '%1$s 已定义',
'UI:Search:Criteria:Title:ExternalKey:NotEmpty' => '%1$s 未被定义',
@@ -1525,7 +1525,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'UI:Search:Criteria:Operator:Numeric:LessThanOrEquals' => '小于 / 等于', // > '<=',
'UI:Search:Criteria:Operator:Numeric:Different' => '不同', // => '≠',
// - Tag Set Widget
'UI:Search:Criteria:Operator:TagSet:Matches' => '匹配',
'UI:Search:Criteria:Operator:TagSet:Matches' => 'Matches~~',
// - Other translations
'UI:Search:Value:Filter:Placeholder' => '过滤器...',

View File

@@ -151,16 +151,9 @@ $(function()
// Intended for overloading in derived classes
_onUpdateSuccess: function(oData, sFormPath)
{
var me = this;
if(oData.form.hidden_fields !== undefined)
{
$.each(oData.form.hidden_fields, function( index, value ) {
me.element.find('[data-form-path="' + sFormPath + '"][data-field-id="'+value+'"][data-attribute-flag-hidden="false"]').children().remove();
});
}
if(oData.form.updated_fields !== undefined)
{
me.element.find('[data-form-path="' + sFormPath + '"]').trigger('update_form', {updated_fields: oData.form.updated_fields});
this.element.find('[data-form-path="' + sFormPath + '"]').trigger('update_form', {updated_fields: oData.form.updated_fields});
}
},
// Intended for overloading in derived classes

View File

@@ -42,8 +42,6 @@ namespace Composer\Autoload;
*/
class ClassLoader
{
private $vendorDir;
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
@@ -59,13 +57,6 @@ class ClassLoader
private $missingClasses = array();
private $apcuPrefix;
private static $registeredLoaders = array();
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
}
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
@@ -309,17 +300,6 @@ class ClassLoader
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
@@ -328,10 +308,6 @@ class ClassLoader
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
@@ -391,16 +367,6 @@ class ClassLoader
return $file;
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return self[]
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup

View File

@@ -1,705 +0,0 @@
<?php
namespace Composer;
use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
class InstalledVersions
{
private static $installed = array (
'root' =>
array (
'pretty_version' => 'dev-develop',
'version' => 'dev-develop',
'aliases' =>
array (
),
'reference' => '2d2a6857de55d005dbc4836e558e611ce7f52bb8',
'name' => '__root__',
),
'versions' =>
array (
'__root__' =>
array (
'pretty_version' => 'dev-develop',
'version' => 'dev-develop',
'aliases' =>
array (
),
'reference' => '2d2a6857de55d005dbc4836e558e611ce7f52bb8',
),
'combodo/tcpdf' =>
array (
'pretty_version' => '6.3.5',
'version' => '6.3.5.0',
'aliases' =>
array (
),
'reference' => 'aedd4b7b8cf7fcc24e617c405c9d3304150f4b94',
),
'nikic/php-parser' =>
array (
'pretty_version' => 'v3.1.5',
'version' => '3.1.5.0',
'aliases' =>
array (
),
'reference' => 'bb87e28e7d7b8d9a7fda231d37457c9210faf6ce',
),
'paragonie/random_compat' =>
array (
'pretty_version' => 'v2.0.18',
'version' => '2.0.18.0',
'aliases' =>
array (
),
'reference' => '0a58ef6e3146256cc3dc7cc393927bcc7d1b72db',
),
'pear/archive_tar' =>
array (
'pretty_version' => '1.4.13',
'version' => '1.4.13.0',
'aliases' =>
array (
),
'reference' => '2b87b41178cc6d4ad3cba678a46a1cae49786011',
),
'pear/console_getopt' =>
array (
'pretty_version' => 'v1.4.3',
'version' => '1.4.3.0',
'aliases' =>
array (
),
'reference' => 'a41f8d3e668987609178c7c4a9fe48fecac53fa0',
),
'pear/pear-core-minimal' =>
array (
'pretty_version' => 'v1.10.10',
'version' => '1.10.10.0',
'aliases' =>
array (
),
'reference' => '625a3c429d9b2c1546438679074cac1b089116a7',
),
'pear/pear_exception' =>
array (
'pretty_version' => 'v1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => 'dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7',
),
'pelago/emogrifier' =>
array (
'pretty_version' => 'v2.1.0',
'version' => '2.1.0.0',
'aliases' =>
array (
),
'reference' => '40c3d4f475d44ffc7265a760d1dd0e81f579f96f',
),
'psr/cache' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8',
),
'psr/cache-implementation' =>
array (
'provided' =>
array (
0 => '1.0',
),
),
'psr/container' =>
array (
'pretty_version' => '1.0.0',
'version' => '1.0.0.0',
'aliases' =>
array (
),
'reference' => 'b7ce3b176482dbbc1245ebf52b181af44c2cf55f',
),
'psr/container-implementation' =>
array (
'provided' =>
array (
0 => '1.0',
),
),
'psr/log' =>
array (
'pretty_version' => '1.1.2',
'version' => '1.1.2.0',
'aliases' =>
array (
),
'reference' => '446d54b4cb6bf489fc9d75f55843658e6f25d801',
),
'psr/log-implementation' =>
array (
'provided' =>
array (
0 => '1.0',
),
),
'psr/simple-cache' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
),
'psr/simple-cache-implementation' =>
array (
'provided' =>
array (
0 => '1.0',
),
),
'rsky/pear-core-min' =>
array (
'replaced' =>
array (
0 => 'v1.10.10',
),
),
'scssphp/scssphp' =>
array (
'pretty_version' => '1.0.6',
'version' => '1.0.6.0',
'aliases' =>
array (
),
'reference' => '5b3c9d704950d8f9637f5110c36c281ec47dc13c',
),
'swiftmailer/swiftmailer' =>
array (
'pretty_version' => 'v5.4.12',
'version' => '5.4.12.0',
'aliases' =>
array (
),
'reference' => '181b89f18a90f8925ef805f950d47a7190e9b950',
),
'symfony/cache' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '3d9f46a6960fd5cd7f030f86adc5b4b63bcfa4e3',
),
'symfony/class-loader' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'e212b06996819a2bce026a63da03b7182d05a690',
),
'symfony/config' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'a599a867d0e4a07c342b5f1e656b3915a540ddbe',
),
'symfony/console' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '1ee23b3b659b06c622f2bd2492a229e416eb4586',
),
'symfony/css-selector' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'f819f71ae3ba6f396b4c015bd5895de7d2f1f85f',
),
'symfony/debug' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'f72e33fdb1170b326e72c3157f0cd456351dd086',
),
'symfony/dependency-injection' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '0d201916bfb3af939fec3c0c8815ea16c60ac1a2',
),
'symfony/dotenv' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'c7e8e471fea74e868ae797970b383dea89ae548a',
),
'symfony/event-dispatcher' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'f9031c22ec127d4a2450760f81a8677fe8a10177',
),
'symfony/filesystem' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '00cdad0936d06fab136944bc2342b762b1c3a4a2',
),
'symfony/finder' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '290ae21279b37bfd287cdcce640d51204e84afdf',
),
'symfony/framework-bundle' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '0d61117c7a770da0bd8bbe7ccfa34d8063f272ea',
),
'symfony/http-foundation' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'd2d0cfe8e319d9df44c4cca570710fcf221d4593',
),
'symfony/http-kernel' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'c42c8339acb28cfff0fb1786948db4d23d609ff7',
),
'symfony/polyfill-apcu' =>
array (
'pretty_version' => 'v1.13.1',
'version' => '1.13.1.0',
'aliases' =>
array (
),
'reference' => 'a8e961c841b9ec52927a87914f8820a1ad8f8116',
),
'symfony/polyfill-ctype' =>
array (
'pretty_version' => 'v1.13.1',
'version' => '1.13.1.0',
'aliases' =>
array (
),
'reference' => 'f8f0b461be3385e56d6de3dbb5a0df24c0c275e3',
),
'symfony/polyfill-mbstring' =>
array (
'pretty_version' => 'v1.13.1',
'version' => '1.13.1.0',
'aliases' =>
array (
),
'reference' => '7b4aab9743c30be783b73de055d24a39cf4b954f',
),
'symfony/polyfill-php56' =>
array (
'pretty_version' => 'v1.13.1',
'version' => '1.13.1.0',
'aliases' =>
array (
),
'reference' => '53dd1cdf3cb986893ccf2b96665b25b3abb384f4',
),
'symfony/polyfill-php70' =>
array (
'pretty_version' => 'v1.13.1',
'version' => '1.13.1.0',
'aliases' =>
array (
),
'reference' => 'af23c7bb26a73b850840823662dda371484926c4',
),
'symfony/polyfill-util' =>
array (
'pretty_version' => 'v1.13.1',
'version' => '1.13.1.0',
'aliases' =>
array (
),
'reference' => '964a67f293b66b95883a5ed918a65354fcd2258f',
),
'symfony/routing' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'b689ccd48e234ea404806d94b07eeb45f9f6f06a',
),
'symfony/stopwatch' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'efe0af281ad336bc3b10375c88b117499f1d8494',
),
'symfony/twig-bridge' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '49b824ddc7f2d250a1f172349cd9a111d63287c0',
),
'symfony/twig-bundle' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'd39ed8f5df62aeeeb27a6f3bf7f58a6c02a58ea9',
),
'symfony/var-dumper' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '569e261461600810845a8305ca3f64abd3e712c0',
),
'symfony/web-profiler-bundle' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '3ae27cf1b2776cd68aa15fdb57089970f78bcf11',
),
'symfony/yaml' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'dab657db15207879217fc81df4f875947bf68804',
),
'tecnickcom/tcpdf' =>
array (
'replaced' =>
array (
0 => '6.3.5',
),
),
'twig/twig' =>
array (
'pretty_version' => 'v1.42.4',
'version' => '1.42.4.0',
'aliases' =>
array (
),
'reference' => 'e587180584c3d2d6cb864a0454e777bb6dcb6152',
),
),
);
private static $canGetVendors;
private static $installedByVendor = array();
public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
public static function isInstalled($packageName)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return true;
}
}
return false;
}
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints($constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
public static function getRawData()
{
return self::$installed;
}
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
}
}
}
$installed[] = self::$installed;
return $installed;
}
}

View File

@@ -330,10 +330,7 @@ return array(
'OQLMenuNode' => $baseDir . '/application/menunode.class.inc.php',
'OQLParser' => $baseDir . '/core/oql/oql-parser.php',
'OQLParserException' => $baseDir . '/core/oql/oql-parser.php',
'OQLParserParseFailureException' => $baseDir . '/core/oql/oql-parser.php',
'OQLParserRaw' => $baseDir . '/core/oql/oql-parser.php',
'OQLParserStackOverFlowException' => $baseDir . '/core/oql/oql-parser.php',
'OQLParserSyntaxErrorException' => $baseDir . '/core/oql/oql-parser.php',
'OQLParser_yyStackEntry' => $baseDir . '/core/oql/oql-parser.php',
'OQLParser_yyToken' => $baseDir . '/core/oql/oql-parser.php',
'OS_Guess' => $vendorDir . '/pear/pear-core-minimal/src/OS/Guess.php',

View File

@@ -25,7 +25,7 @@ class ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b', 'loadClassLoader'));
$includePaths = require __DIR__ . '/include_paths.php';

View File

@@ -560,10 +560,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
'OQLMenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php',
'OQLParser' => __DIR__ . '/../..' . '/core/oql/oql-parser.php',
'OQLParserException' => __DIR__ . '/../..' . '/core/oql/oql-parser.php',
'OQLParserParseFailureException' => __DIR__ . '/../..' . '/core/oql/oql-parser.php',
'OQLParserRaw' => __DIR__ . '/../..' . '/core/oql/oql-parser.php',
'OQLParserStackOverFlowException' => __DIR__ . '/../..' . '/core/oql/oql-parser.php',
'OQLParserSyntaxErrorException' => __DIR__ . '/../..' . '/core/oql/oql-parser.php',
'OQLParser_yyStackEntry' => __DIR__ . '/../..' . '/core/oql/oql-parser.php',
'OQLParser_yyToken' => __DIR__ . '/../..' . '/core/oql/oql-parser.php',
'OS_Guess' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/OS/Guess.php',

View File

@@ -6,8 +6,8 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
$vendorDir . '/pear/archive_tar',
$vendorDir . '/pear/console_getopt',
$vendorDir . '/pear/pear-core-minimal/src',
$vendorDir . '/pear/pear_exception',
$vendorDir . '/pear/archive_tar',
);

View File

@@ -171,17 +171,17 @@
},
{
"name": "pear/archive_tar",
"version": "1.4.13",
"version_normalized": "1.4.13.0",
"version": "1.4.10",
"version_normalized": "1.4.10.0",
"source": {
"type": "git",
"url": "https://github.com/pear/Archive_Tar.git",
"reference": "2b87b41178cc6d4ad3cba678a46a1cae49786011"
"reference": "bbb4f10f71a1da2715ec6d9a683f4f23c507a49b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pear/Archive_Tar/zipball/2b87b41178cc6d4ad3cba678a46a1cae49786011",
"reference": "2b87b41178cc6d4ad3cba678a46a1cae49786011",
"url": "https://api.github.com/repos/pear/Archive_Tar/zipball/bbb4f10f71a1da2715ec6d9a683f4f23c507a49b",
"reference": "bbb4f10f71a1da2715ec6d9a683f4f23c507a49b",
"shasum": ""
},
"require": {
@@ -196,7 +196,7 @@
"ext-xz": "Lzma2 compression support.",
"ext-zlib": "Gzip compression support."
},
"time": "2021-02-16T10:50:50+00:00",
"time": "2020-09-15T14:13:23+00:00",
"type": "library",
"extra": {
"branch-alias": {
@@ -236,20 +236,6 @@
"archive",
"tar"
],
"support": {
"issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Archive_Tar",
"source": "https://github.com/pear/Archive_Tar"
},
"funding": [
{
"url": "https://github.com/mrook",
"type": "github"
},
{
"url": "https://www.patreon.com/michielrook",
"type": "patreon"
}
],
"install-path": "../pear/archive_tar"
},
{

View File

@@ -1,444 +0,0 @@
<?php return array (
'root' =>
array (
'pretty_version' => 'dev-develop',
'version' => 'dev-develop',
'aliases' =>
array (
),
'reference' => '2d2a6857de55d005dbc4836e558e611ce7f52bb8',
'name' => '__root__',
),
'versions' =>
array (
'__root__' =>
array (
'pretty_version' => 'dev-develop',
'version' => 'dev-develop',
'aliases' =>
array (
),
'reference' => '2d2a6857de55d005dbc4836e558e611ce7f52bb8',
),
'combodo/tcpdf' =>
array (
'pretty_version' => '6.3.5',
'version' => '6.3.5.0',
'aliases' =>
array (
),
'reference' => 'aedd4b7b8cf7fcc24e617c405c9d3304150f4b94',
),
'nikic/php-parser' =>
array (
'pretty_version' => 'v3.1.5',
'version' => '3.1.5.0',
'aliases' =>
array (
),
'reference' => 'bb87e28e7d7b8d9a7fda231d37457c9210faf6ce',
),
'paragonie/random_compat' =>
array (
'pretty_version' => 'v2.0.18',
'version' => '2.0.18.0',
'aliases' =>
array (
),
'reference' => '0a58ef6e3146256cc3dc7cc393927bcc7d1b72db',
),
'pear/archive_tar' =>
array (
'pretty_version' => '1.4.13',
'version' => '1.4.13.0',
'aliases' =>
array (
),
'reference' => '2b87b41178cc6d4ad3cba678a46a1cae49786011',
),
'pear/console_getopt' =>
array (
'pretty_version' => 'v1.4.3',
'version' => '1.4.3.0',
'aliases' =>
array (
),
'reference' => 'a41f8d3e668987609178c7c4a9fe48fecac53fa0',
),
'pear/pear-core-minimal' =>
array (
'pretty_version' => 'v1.10.10',
'version' => '1.10.10.0',
'aliases' =>
array (
),
'reference' => '625a3c429d9b2c1546438679074cac1b089116a7',
),
'pear/pear_exception' =>
array (
'pretty_version' => 'v1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => 'dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7',
),
'pelago/emogrifier' =>
array (
'pretty_version' => 'v2.1.0',
'version' => '2.1.0.0',
'aliases' =>
array (
),
'reference' => '40c3d4f475d44ffc7265a760d1dd0e81f579f96f',
),
'psr/cache' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8',
),
'psr/cache-implementation' =>
array (
'provided' =>
array (
0 => '1.0',
),
),
'psr/container' =>
array (
'pretty_version' => '1.0.0',
'version' => '1.0.0.0',
'aliases' =>
array (
),
'reference' => 'b7ce3b176482dbbc1245ebf52b181af44c2cf55f',
),
'psr/container-implementation' =>
array (
'provided' =>
array (
0 => '1.0',
),
),
'psr/log' =>
array (
'pretty_version' => '1.1.2',
'version' => '1.1.2.0',
'aliases' =>
array (
),
'reference' => '446d54b4cb6bf489fc9d75f55843658e6f25d801',
),
'psr/log-implementation' =>
array (
'provided' =>
array (
0 => '1.0',
),
),
'psr/simple-cache' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
),
'psr/simple-cache-implementation' =>
array (
'provided' =>
array (
0 => '1.0',
),
),
'rsky/pear-core-min' =>
array (
'replaced' =>
array (
0 => 'v1.10.10',
),
),
'scssphp/scssphp' =>
array (
'pretty_version' => '1.0.6',
'version' => '1.0.6.0',
'aliases' =>
array (
),
'reference' => '5b3c9d704950d8f9637f5110c36c281ec47dc13c',
),
'swiftmailer/swiftmailer' =>
array (
'pretty_version' => 'v5.4.12',
'version' => '5.4.12.0',
'aliases' =>
array (
),
'reference' => '181b89f18a90f8925ef805f950d47a7190e9b950',
),
'symfony/cache' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '3d9f46a6960fd5cd7f030f86adc5b4b63bcfa4e3',
),
'symfony/class-loader' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'e212b06996819a2bce026a63da03b7182d05a690',
),
'symfony/config' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'a599a867d0e4a07c342b5f1e656b3915a540ddbe',
),
'symfony/console' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '1ee23b3b659b06c622f2bd2492a229e416eb4586',
),
'symfony/css-selector' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'f819f71ae3ba6f396b4c015bd5895de7d2f1f85f',
),
'symfony/debug' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'f72e33fdb1170b326e72c3157f0cd456351dd086',
),
'symfony/dependency-injection' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '0d201916bfb3af939fec3c0c8815ea16c60ac1a2',
),
'symfony/dotenv' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'c7e8e471fea74e868ae797970b383dea89ae548a',
),
'symfony/event-dispatcher' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'f9031c22ec127d4a2450760f81a8677fe8a10177',
),
'symfony/filesystem' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '00cdad0936d06fab136944bc2342b762b1c3a4a2',
),
'symfony/finder' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '290ae21279b37bfd287cdcce640d51204e84afdf',
),
'symfony/framework-bundle' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '0d61117c7a770da0bd8bbe7ccfa34d8063f272ea',
),
'symfony/http-foundation' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'd2d0cfe8e319d9df44c4cca570710fcf221d4593',
),
'symfony/http-kernel' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'c42c8339acb28cfff0fb1786948db4d23d609ff7',
),
'symfony/polyfill-apcu' =>
array (
'pretty_version' => 'v1.13.1',
'version' => '1.13.1.0',
'aliases' =>
array (
),
'reference' => 'a8e961c841b9ec52927a87914f8820a1ad8f8116',
),
'symfony/polyfill-ctype' =>
array (
'pretty_version' => 'v1.13.1',
'version' => '1.13.1.0',
'aliases' =>
array (
),
'reference' => 'f8f0b461be3385e56d6de3dbb5a0df24c0c275e3',
),
'symfony/polyfill-mbstring' =>
array (
'pretty_version' => 'v1.13.1',
'version' => '1.13.1.0',
'aliases' =>
array (
),
'reference' => '7b4aab9743c30be783b73de055d24a39cf4b954f',
),
'symfony/polyfill-php56' =>
array (
'pretty_version' => 'v1.13.1',
'version' => '1.13.1.0',
'aliases' =>
array (
),
'reference' => '53dd1cdf3cb986893ccf2b96665b25b3abb384f4',
),
'symfony/polyfill-php70' =>
array (
'pretty_version' => 'v1.13.1',
'version' => '1.13.1.0',
'aliases' =>
array (
),
'reference' => 'af23c7bb26a73b850840823662dda371484926c4',
),
'symfony/polyfill-util' =>
array (
'pretty_version' => 'v1.13.1',
'version' => '1.13.1.0',
'aliases' =>
array (
),
'reference' => '964a67f293b66b95883a5ed918a65354fcd2258f',
),
'symfony/routing' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'b689ccd48e234ea404806d94b07eeb45f9f6f06a',
),
'symfony/stopwatch' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'efe0af281ad336bc3b10375c88b117499f1d8494',
),
'symfony/twig-bridge' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '49b824ddc7f2d250a1f172349cd9a111d63287c0',
),
'symfony/twig-bundle' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'd39ed8f5df62aeeeb27a6f3bf7f58a6c02a58ea9',
),
'symfony/var-dumper' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '569e261461600810845a8305ca3f64abd3e712c0',
),
'symfony/web-profiler-bundle' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => '3ae27cf1b2776cd68aa15fdb57089970f78bcf11',
),
'symfony/yaml' =>
array (
'pretty_version' => 'v3.4.36',
'version' => '3.4.36.0',
'aliases' =>
array (
),
'reference' => 'dab657db15207879217fc81df4f875947bf68804',
),
'tecnickcom/tcpdf' =>
array (
'replaced' =>
array (
0 => '6.3.5',
),
),
'twig/twig' =>
array (
'pretty_version' => 'v1.42.4',
'version' => '1.42.4.0',
'aliases' =>
array (
),
'reference' => 'e587180584c3d2d6cb864a0454e777bb6dcb6152',
),
),
);

View File

@@ -1,26 +0,0 @@
<?php
// platform_check.php @generated by Composer
$issues = array();
if (!(PHP_VERSION_ID >= 50600)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 5.6.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
} elseif (!headers_sent()) {
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
}
}
trigger_error(
'Composer detected issues in your platform: ' . implode(' ', $issues),
E_USER_ERROR
);
}

View File

@@ -1,2 +0,0 @@
github: [mrook]
patreon: michielrook

View File

@@ -1,11 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "composer" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"

View File

@@ -1,40 +0,0 @@
on:
push:
branches:
- master
pull_request:
jobs:
test:
runs-on: ${{ matrix.operating-system }}
strategy:
fail-fast: false
matrix:
operating-system: [ ubuntu-latest ]
php: [ '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0' ]
dependencies: [ 'locked' ]
name: PHP ${{ matrix.php }} on ${{ matrix.operating-system }} with ${{ matrix.dependencies }} dependencies
steps:
- uses: actions/checkout@v2
name: Checkout repository
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
- uses: ramsey/composer-install@v1
with:
dependency-versions: ${{ matrix.dependencies }}
- name: Install PEAR
run: |
sudo apt-get install php-pear
- name: Run tests
run: |
sudo pear install -f package.xml
pear version
pear run-tests -qr tests/ || { cat run-tests.log; for i in `find tests/ -name '*.out'`; do echo "$i"; cat "$i"; done; exit 1; }

View File

@@ -257,7 +257,7 @@ class Archive_Tar extends PEAR
{
$this->_close();
// ----- Look for a local copy to delete
if ($this->_temp_tarname != '' && (bool) preg_match('/^tar[[:alnum:]]*\.tmp$/', $this->_temp_tarname)) {
if ($this->_temp_tarname != '') {
@unlink($this->_temp_tarname);
}
}
@@ -1397,20 +1397,16 @@ class Archive_Tar extends PEAR
$v_magic = 'ustar ';
$v_version = ' ';
$v_uname = '';
$v_gname = '';
if (function_exists('posix_getpwuid')) {
$userinfo = posix_getpwuid($v_info[4]);
$groupinfo = posix_getgrgid($v_info[5]);
if (isset($userinfo['name'])) {
$v_uname = $userinfo['name'];
}
if (isset($groupinfo['name'])) {
$v_gname = $groupinfo['name'];
}
$v_uname = $userinfo['name'];
$v_gname = $groupinfo['name'];
} else {
$v_uname = '';
$v_gname = '';
}
$v_devmajor = '';
@@ -1734,7 +1730,7 @@ class Archive_Tar extends PEAR
// ----- Extract the properties
$v_header['filename'] = rtrim($v_data['filename'], "\0");
if ($this->_isMaliciousFilename($v_header['filename'])) {
if ($this->_maliciousFilename($v_header['filename'])) {
$this->_error(
'Malicious .tar detected, file "' . $v_header['filename'] .
'" will not install in desired directory tree'
@@ -1804,9 +1800,9 @@ class Archive_Tar extends PEAR
*
* @return bool
*/
private function _isMaliciousFilename($file)
private function _maliciousFilename($file)
{
if (strpos($file, '://') !== false) {
if (strpos($file, 'phar://') === 0) {
return true;
}
if (strpos($file, '../') !== false || strpos($file, '..\\') !== false) {
@@ -1842,7 +1838,7 @@ class Archive_Tar extends PEAR
$v_filename = rtrim(substr($v_filename, 0, $v_filesize), "\0");
$v_header['filename'] = $v_filename;
if ($this->_isMaliciousFilename($v_filename)) {
if ($this->_maliciousFilename($v_filename)) {
$this->_error(
'Malicious .tar detected, file "' . $v_filename .
'" will not install in desired directory tree'
@@ -2124,32 +2120,6 @@ class Archive_Tar extends PEAR
}
}
} elseif ($v_header['typeflag'] == "2") {
$link_depth = 0;
foreach (explode("/", $v_header['filename']) as $dir) {
if ($dir === "..") {
$link_depth--;
} elseif ($dir !== "" && $dir !== "." ) {
$link_depth++;
}
}
foreach (explode("/", $v_header['link']) as $dir){
if ($link_depth <= 0) {
break;
}
if ($dir === "..") {
$link_depth--;
} elseif ($dir !== "" && $dir !== ".") {
$link_depth++;
}
}
if (strpos($v_header['link'], "/") === 0 or $link_depth <= 0) {
$this->_error(
'Out-of-path file extraction {'
. $v_header['filename'] . ' --> ' .
$v_header['link'] . '}'
);
return false;
}
if (!$p_symlinks) {
$this->_warning('Symbolic links are not allowed. '
. 'Unable to extract {'

View File

@@ -1,7 +1,7 @@
Archive_Tar
==========
![.github/workflows/build.yml](https://github.com/pear/Archive_Tar/workflows/.github/workflows/build.yml/badge.svg)
[![Build Status](https://secure.travis-ci.org/pear/Archive_Tar.png?branch=master)](https://travis-ci.org/pear/Archive_Tar)
This package provides handling of tar files in PHP.
It supports creating, listing, extracting and adding to tar files.

View File

@@ -32,10 +32,10 @@ Also Lzma2 compressed archives are supported with xz extension.</description>
<email>stig@php.net</email>
<active>no</active>
</helper>
<date>2021-02-16</date>
<time>10:49:28</time>
<date>2020-09-15</date>
<time>14:03:45</time>
<version>
<release>1.4.13</release>
<release>1.4.10</release>
<api>1.4.0</api>
</version>
<stability>
@@ -44,7 +44,8 @@ Also Lzma2 compressed archives are supported with xz extension.</description>
</stability>
<license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
<notes>
* Fix Bug #27010: Relative symlinks failing (out-of path file extraction) [mrook]
* Fix block padding when the file buffer length is a multiple of 512 and smaller than Archive_Tar buffer length
* Don't try to copy username/groupname in chroot jail
</notes>
<contents>
<dir name="/">
@@ -74,52 +75,6 @@ Also Lzma2 compressed archives are supported with xz extension.</description>
</dependencies>
<phprelease />
<changelog>
<release>
<version>
<release>1.4.12</release>
<api>1.4.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2021-01-18</date>
<license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
<notes>
* Fix Bug #27008: Symlink out-of-path write vulnerability (CVE-2020-36193) [mrook]
</notes>
</release>
<release>
<version>
<release>1.4.11</release>
<api>1.4.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2020-11-19</date>
<license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
<notes>
* Fix Bug #27002: Filename manipulation vulnerabilities (CVE-2020-28948 / CVE-2020-28949) [mrook]
</notes>
</release>
<release>
<version>
<release>1.4.10</release>
<api>1.4.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2020-09-15</date>
<license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
<notes>
* Fix block padding when the file buffer length is a multiple of 512 and smaller than Archive_Tar buffer length
* Don&apos;t try to copy username/groupname in chroot jail
</notes>
</release>
<release>
<version>
<release>1.4.9</release>

View File

@@ -132,79 +132,6 @@ try
$aClassAliases = utils::ReadParam('class_aliases', array());
$iListId = utils::ReadParam('list_id', 0);
foreach ($aColumns as $sClass => $aAttCodes) {
foreach ($aAttCodes as $sAttCode => $aAttProperties) {
if (!array_key_exists('checked', $aAttProperties)) {
/**
* For data passed in XHR queries with some volume, on some servers data can be cut off because of a php.ini's `max_input_vars` set too low
*
* Normal format is :
* ```
* array (
* 'UserRequest' =>
* array (
* '_key_' =>
* array (
* 'label' => 'User Request (Link)',
* 'checked' => 'true',
* 'disabled' => 'true',
* 'alias' => 'UserRequest',
* 'code' => '_key_',
* 'sort' => 'none',
* ),
* // ...
* 'parent_request_id_friendlyname' =>
* array (
* 'label' => 'parent_request_id_friendlyname (Friendly Name)',
* 'checked' => 'false',
* 'disabled' => 'false',
* 'alias' => 'UserRequest',
* 'code' => 'parent_request_id_friendlyname',
* 'sort' => 'none',
* ),
* )
* ```
*
* While with a low max_input_vars we can get :
* ```
* array (
* 'UserRequest' =>
* array (
* '_key_' =>
* array (
* 'label' => 'User Request (Link)',
* 'checked' => 'true',
* 'disabled' => 'true',
* 'alias' => 'UserRequest',
* 'code' => '_key_',
* 'sort' => 'none',
* ),
* // ...
* 'parent_request_id_friendlyname' =>
* array (
* 'label' => 'parent_request_id_friendlyname (Friendly Name)',
* ),
* )
* ```
*
* @link https://www.php.net/manual/fr/info.configuration.php#ini.max-input-vars PHP doc on `max_input_vars`
* @link https://www.itophub.io/wiki/page?id=latest%3Ainstall%3Aphp_and_mysql_configuration#php_mysql_mariadb_settings Combodo's recommended options
*/
$iMaxInputVarsValue = ini_get('max_input_vars');
IssueLog::Warning(
"ajax.render.php received an invalid array for columns : check max_input_vars value in php.ini !",
null,
array(
'operation' => $operation,
'max_input_vars' => $iMaxInputVarsValue,
'class.attcode with invalid format' => "$sClass.$sAttCode",
)
);
$aColumns[$sClass][$sAttCode]['checked'] = 'false';
}
}
}
// Filter the list to removed linked set since we are not able to display them here
$aOrderBy = array();
$iSortIndex = 0;
@@ -2133,9 +2060,7 @@ EOF
case 'xlsx_run':
$sMemoryLimit = MetaModel::GetConfig()->Get('xlsx_exporter_memory_limit');
if (utils::SetMinMemoryLimit($sMemoryLimit) === false) {
IssueLog::Warning("XSLX export : cannot set memory_limit to {$sMemoryLimit}");
}
ini_set('memory_limit', $sMemoryLimit);
ini_set('max_execution_time', max(300, ini_get('max_execution_time'))); // At least 5 minutes
$sToken = utils::ReadParam('token', '', false, 'raw_data');
@@ -2143,7 +2068,8 @@ EOF
$oExcelExporter = new ExcelExporter($sToken);
$aStatus = $oExcelExporter->Run();
$aResults = array('status' => $aStatus['code'], 'percentage' => $aStatus['percentage'], 'message' => $aStatus['message']);
if ($aStatus['code'] == 'done') {
if ($aStatus['code'] == 'done')
{
$aResults['statistics'] = $oExcelExporter->GetStatistics('html');
}
$oPage->add(json_encode($aResults));
@@ -2646,15 +2572,15 @@ EOF
$aResult['height'] = $aDimensions['height'];
}
IssueLog::Trace('InlineImage created', LogChannels::INLINE_IMAGE, array(
'$operation' => $operation,
'$aResult' => $aResult,
'secret' => $oAttachment->Get('secret'),
'temp_id' => $sTempId,
'item_class' => $sObjClass,
'user' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
IssueLog::Trace('InlineImage created', 'InlineImage', array(
'$operation' => $operation,
'$aResult' => $aResult,
'secret' => $oAttachment->Get('secret'),
'temp_id' => $sTempId,
'item_class' => $sObjClass,
'user' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
));
}
else
@@ -2697,15 +2623,15 @@ EOF
$oAttachment->Set('secret', sprintf('%06x', mt_rand(0, 0xFFFFFF))); // something not easy to guess
$iAttId = $oAttachment->DBInsert();
IssueLog::Trace('InlineImage created', LogChannels::INLINE_IMAGE, array(
'$operation' => $operation,
'secret' => $oAttachment->Get('secret'),
'temp_id' => $sTempId,
'item_class' => $sObjClass,
'user' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
));
IssueLog::Trace('InlineImage created', 'InlineImage', array(
'$operation' => $operation,
'secret' => $oAttachment->Get('secret'),
'temp_id' => $sTempId,
'item_class' => $sObjClass,
'user' => UserRights::GetUser(),
'HTTP_REFERER' => @$_SERVER['HTTP_REFERER'],
'REQUEST_URI' => @$_SERVER['REQUEST_URI'],
));
}
} catch (FileUploadException $e)

Some files were not shown because too many files have changed in this diff Show More