mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
Merge remote-tracking branch 'origin/support/3.0' into develop
This commit is contained in:
@@ -3929,7 +3929,7 @@ HTML;
|
||||
}
|
||||
elseif ($iFlags & OPT_ATT_SLAVE)
|
||||
{
|
||||
$aErrors[$sAttCode] = Dict::Format('UI:AttemptingToSetASlaveAttribute_Name', $oAttDef->GetLabel());
|
||||
$aErrors[$sAttCode] = Dict::Format('UI:AttemptingToSetASlaveAttribute_Name', $oAttDef->GetLabel(), $sAttCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -262,7 +262,7 @@ abstract class Dashlet
|
||||
}
|
||||
} catch (OqlException $e) {
|
||||
$oDashletContainer->AddCSSClass("dashlet-content");
|
||||
$oDashletContainer->AddHtml('<p>'.$e->GetUserFriendlyDescription().'</p>');
|
||||
$oDashletContainer->AddHtml('<p>'.utils::HtmlEntities($e->GetUserFriendlyDescription()).'</p>');
|
||||
} catch (Exception $e) {
|
||||
$oDashletContainer->AddCSSClass("dashlet-content");
|
||||
$oDashletContainer->AddHtml('<p>'.$e->getMessage().'</p>');
|
||||
|
||||
@@ -454,6 +454,11 @@ class utils
|
||||
$retValue = preg_replace('/[^a-zA-Z0-9_]/', '', $value);
|
||||
break;
|
||||
|
||||
// For URL
|
||||
case 'url':
|
||||
$retValue = filter_var($value, FILTER_SANITIZE_URL);
|
||||
break;
|
||||
|
||||
default:
|
||||
case static::ENUM_SANITIZATION_FILTER_RAW_DATA:
|
||||
$retValue = $value;
|
||||
@@ -2815,6 +2820,7 @@ HTML;
|
||||
|
||||
/**
|
||||
* Helper around the native strlen() PHP method to keep allowing usage of null value when computing the length of a string as null value is no longer allowed with PHP 8.1+
|
||||
* @link https://www.php.net/releases/8.1/en.php#deprecations_and_bc_breaks "Passing null to non-nullable internal function parameters is deprecated"
|
||||
*
|
||||
* @param string|null $sString
|
||||
*
|
||||
|
||||
@@ -277,7 +277,7 @@ class ActionEmail extends ActionNotification
|
||||
protected function FindRecipients($sRecipAttCode, $aArgs)
|
||||
{
|
||||
$sOQL = $this->Get($sRecipAttCode);
|
||||
if (strlen($sOQL) == '') return '';
|
||||
if (strlen($sOQL) === 0) return '';
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -2026,9 +2026,9 @@ abstract class DBObject implements iDisplay
|
||||
/**
|
||||
* check attributes together
|
||||
*
|
||||
* @overwritable-hook You can extend this method in order to provide your own logic.
|
||||
*
|
||||
* @return bool
|
||||
* @overwritable-hook You can extend this method in order to provide your own logic.
|
||||
*
|
||||
* @return true|string true if successful, the error description otherwise
|
||||
*/
|
||||
public function CheckConsistency()
|
||||
{
|
||||
@@ -2249,8 +2249,9 @@ abstract class DBObject implements iDisplay
|
||||
foreach($aChanges as $sAttCode => $value) {
|
||||
$res = $this->CheckValue($sAttCode);
|
||||
if ($res !== true) {
|
||||
$sAttLabel = $this->GetLabel($sAttCode);
|
||||
// $res contains the error description
|
||||
$this->m_aCheckIssues[] = "Unexpected value for attribute '$sAttCode': $res";
|
||||
$this->m_aCheckIssues[] = Dict::Format('Core:CheckValueError', $sAttLabel, $sAttCode, $res);
|
||||
}
|
||||
|
||||
$this->DoCheckLinkedSetDuplicates($sAttCode, $value);
|
||||
@@ -2265,7 +2266,7 @@ abstract class DBObject implements iDisplay
|
||||
if ($res !== true)
|
||||
{
|
||||
// $res contains the error description
|
||||
$this->m_aCheckIssues[] = "Consistency rules not followed: $res";
|
||||
$this->m_aCheckIssues[] = Dict::Format('Core:CheckConsistencyError', $res);
|
||||
}
|
||||
|
||||
// Synchronization: are we attempting to modify an attribute for which an external source is master?
|
||||
@@ -2278,12 +2279,10 @@ abstract class DBObject implements iDisplay
|
||||
if ($iFlags & OPT_ATT_SLAVE)
|
||||
{
|
||||
// Note: $aReasonInfo['name'] could be reported (the task owning the attribute)
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
||||
$sAttLabel = $oAttDef->GetLabel();
|
||||
if (!empty($aReasons))
|
||||
{
|
||||
// Todo: associate the attribute code with the error
|
||||
$this->m_aCheckIssues[] = Dict::Format('UI:AttemptingToSetASlaveAttribute_Name', $sAttLabel);
|
||||
$sAttLabel = $this->GetLabel($sAttCode);
|
||||
$this->m_aCheckIssues[] = Dict::Format('UI:AttemptingToSetASlaveAttribute_Name', $sAttLabel, $sAttCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1195,8 +1195,10 @@ class DisplayableGraph extends SimpleGraph
|
||||
* @param float $xMax Right coordinate of the bounding box to display the graph
|
||||
* @param float $yMin Top coordinate of the bounding box to display the graph
|
||||
* @param float $yMax Bottom coordinate of the bounding box to display the graph
|
||||
*
|
||||
* @since 2.7.7 3.0.2 3.1.0 N°4985 $sComments param is no longer optional
|
||||
*/
|
||||
function RenderAsPDF(PDFPage $oPage, $sComments = '', $sContextKey, $xMin = -1, $xMax = -1, $yMin = -1, $yMax = -1)
|
||||
function RenderAsPDF(PDFPage $oPage, $sComments, $sContextKey, $xMin = -1, $xMax = -1, $yMin = -1, $yMax = -1)
|
||||
{
|
||||
$aContextDefs = static::GetContextDefinitions($sContextKey, false); // No need to develop the parameters
|
||||
$oPdf = $oPage->get_tcpdf();
|
||||
|
||||
@@ -162,12 +162,20 @@ class BrickCollection
|
||||
// - Home
|
||||
$this->aHomeOrdering = $this->aAllowedBricks;
|
||||
usort($this->aHomeOrdering, function (PortalBrick $a, PortalBrick $b) {
|
||||
return $a->GetRankHome() > $b->GetRankHome();
|
||||
if ($a->GetRankHome() === $b->GetRankHome()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $a->GetRankHome() > $b->GetRankHome() ? 1 : -1;
|
||||
});
|
||||
// - Navigation menu
|
||||
$this->aNavigationMenuOrdering = $this->aAllowedBricks;
|
||||
usort($this->aNavigationMenuOrdering, function (PortalBrick $a, PortalBrick $b) {
|
||||
return $a->GetRankNavigationMenu() > $b->GetRankNavigationMenu();
|
||||
if ($a->GetRankNavigationMenu() === $b->GetRankNavigationMenu()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $a->GetRankNavigationMenu() > $b->GetRankNavigationMenu() ? 1 : -1;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -485,7 +485,11 @@ class ManageBrick extends PortalBrick
|
||||
if (!$this->IsGroupingByDistinctValues($sName))
|
||||
{
|
||||
usort($this->aGrouping[$sName]['groups'], function ($a, $b) {
|
||||
return $a['rank'] > $b['rank'];
|
||||
if ($a['rank'] === $b['rank']) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $a['rank'] > $b['rank'] ? 1 : -1;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,10 @@ class Lists extends AbstractConfiguration
|
||||
}
|
||||
// - Sorting list items by rank
|
||||
usort($aListItems, function ($a, $b) {
|
||||
return $a['rank'] > $b['rank'];
|
||||
if ($a['rank'] == $b['rank']) {
|
||||
return 0;
|
||||
}
|
||||
return $a['rank'] > $b['rank'] ? 1 : -1;
|
||||
});
|
||||
$aClassLists[$sListId] = $aListItems;
|
||||
}
|
||||
|
||||
@@ -703,7 +703,7 @@ class ObjectFormManager extends FormManager
|
||||
|
||||
/** @var Field $oField */
|
||||
$oField = null;
|
||||
if (is_callable(get_class($oAttDef).'::MakeFormField'))
|
||||
if (is_callable([$oAttDef, 'MakeFormField']))
|
||||
{
|
||||
$oField = $oAttDef->MakeFormField($this->oObject);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2022 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* This file is part of iTop.
|
||||
@@ -29,6 +29,8 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Core:UnknownObjectTip' => 'The object could not be found. It may have been deleted some time ago and the log has been purged since.',
|
||||
|
||||
'Core:UniquenessDefaultError' => 'Uniqueness rule \'%1$s\' in error',
|
||||
'Core:CheckConsistencyError' => 'Consistency rules not followed: %1$s',
|
||||
'Core:CheckValueError' => 'Unexpected value for attribute \'%1$s\' (%2$s) : %3$s',
|
||||
|
||||
'Core:AttributeLinkedSet' => 'Array of objects',
|
||||
'Core:AttributeLinkedSet+' => 'Any kind of objects of the same class or subclass',
|
||||
|
||||
@@ -1168,7 +1168,7 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
'UI:CaseLogTypeYourTextHere' => 'Type your text here...',
|
||||
'UI:CaseLog:Header_Date_UserName' => '%1$s - %2$s:',
|
||||
'UI:CaseLog:InitialValue' => 'Initial value:',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'The field %1$s is not writable because it is mastered by the data synchronization. Value not set.',
|
||||
'UI:AttemptingToSetASlaveAttribute_Name' => 'The field %1$s (%2$s) is not writable because it is mastered by the data synchronization. Value not set.',
|
||||
'UI:ActionNotAllowed' => 'You are not allowed to perform this action on these objects.',
|
||||
'UI:BulkAction:NoObjectSelected' => 'Please select at least one object to perform this operation',
|
||||
'UI:AttemptingToChangeASlaveAttribute_Name' => 'The field %1$s is not writable because it is mastered by the data synchronization. Value remains unchanged.',
|
||||
|
||||
@@ -21,3 +21,24 @@ if ((CKEDITOR !== undefined) && (CKEDITOR.plugins.registered['disabler'] === und
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// Rewrite the CKEditor Mentions plugin regexp to make it suitable for all Unicode alphabets.
|
||||
if (CKEDITOR !== undefined && CKEDITOR.plugins.registered['mentions']) {
|
||||
// from https://github.com/ckeditor/ckeditor4/blob/a3786007fb979d7d7bff3d10c34a2d422935baed/plugins/mentions/plugin.js#L147
|
||||
function createPattern(marker, minChars) {
|
||||
let pattern = marker + '[\\p{L}\\p{N}_-]';
|
||||
if ( minChars ) {
|
||||
pattern += '{' + minChars + ',}';
|
||||
} else {
|
||||
pattern += '*';
|
||||
}
|
||||
pattern += '$';
|
||||
return new RegExp(pattern, 'u');
|
||||
}
|
||||
|
||||
CKEDITOR.on('instanceLoaded', event => {
|
||||
event.editor.config.mentions.forEach(config => {
|
||||
config.pattern = createPattern(config.marker, config.minChars);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1461,7 +1461,7 @@ EOF
|
||||
if ( ($iFlags & OPT_ATT_SLAVE) && ($paramValue != $oObj->Get($sAttCode)) )
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
$aErrors[] = Dict::Format('UI:AttemptingToSetASlaveAttribute_Name', $oAttDef->GetLabel());
|
||||
$aErrors[] = Dict::Format('UI:AttemptingToSetASlaveAttribute_Name', $oAttDef->GetLabel(), $sAttCode);
|
||||
unset($aExpectedAttributes[$sAttCode]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -932,7 +932,7 @@ try
|
||||
|
||||
$aExtraParams = utils::ReadParam('extra_params', array(), false, 'raw_data');
|
||||
$sDashboardFile = utils::ReadParam('file', '', false, 'raw_data');
|
||||
$sReloadURL = utils::ReadParam('reload_url', '', false, 'raw_data');
|
||||
$sReloadURL = utils::ReadParam('reload_url', '', false, 'url');
|
||||
$oDashboard = RuntimeDashboard::GetDashboard($sDashboardFile, $sDashboardId);
|
||||
$aResult = array('error' => '');
|
||||
if (!is_null($oDashboard))
|
||||
@@ -950,7 +950,7 @@ try
|
||||
$sDashboardId = utils::ReadParam('dashboard_id', '', false, 'raw_data');
|
||||
$aExtraParams = utils::ReadParam('extra_params', array(), false, 'raw_data');
|
||||
$sDashboardFile = utils::ReadParam('file', '', false, 'raw_data');
|
||||
$sReloadURL = utils::ReadParam('reload_url', '', false, 'raw_data');
|
||||
$sReloadURL = utils::ReadParam('reload_url', '', false, 'url');
|
||||
$oDashboard = RuntimeDashboard::GetDashboard($sDashboardFile, $sDashboardId);
|
||||
$aResult = array('error' => '');
|
||||
if (!is_null($oDashboard))
|
||||
@@ -967,7 +967,7 @@ try
|
||||
$sDashboardId = utils::ReadParam('dashboard_id', '', false, 'context_param');
|
||||
|
||||
$aExtraParams = utils::ReadParam('extra_params', array(), false, 'raw_data');
|
||||
$sReloadURL = utils::ReadParam('reload_url', '', false, 'raw_data');
|
||||
$sReloadURL = utils::ReadParam('reload_url', '', false, 'url');
|
||||
appUserPreferences::SetPref('display_original_dashboard_'.$sDashboardId, false);
|
||||
$sJSExtraParams = json_encode($aExtraParams);
|
||||
$aParams = array();
|
||||
@@ -1009,7 +1009,7 @@ JS
|
||||
|
||||
case 'revert_dashboard':
|
||||
$sDashboardId = utils::ReadParam('dashboard_id', '', false, 'raw_data');
|
||||
$sReloadURL = utils::ReadParam('reload_url', '', false, 'raw_data');
|
||||
$sReloadURL = utils::ReadParam('reload_url', '', false, 'url');
|
||||
appUserPreferences::UnsetPref('display_original_dashboard_'.$sDashboardId);
|
||||
$oDashboard = new RuntimeDashboard($sDashboardId);
|
||||
$oDashboard->Revert();
|
||||
@@ -1039,7 +1039,7 @@ EOF
|
||||
$aParams['cells'] = utils::ReadParam('cells', array(), false, 'raw_data');
|
||||
$aParams['auto_reload'] = utils::ReadParam('auto_reload', false);
|
||||
$aParams['auto_reload_sec'] = utils::ReadParam('auto_reload_sec', 300);
|
||||
$sReloadURL = utils::ReadParam('reload_url', '', false, 'raw_data');
|
||||
$sReloadURL = utils::ReadParam('reload_url', '', false, 'url');
|
||||
$oDashboard = new RuntimeDashboard($sDashboardId);
|
||||
$oDashboard->FromParams($aParams);
|
||||
$oDashboard->SetReloadURL($sReloadURL);
|
||||
@@ -1051,7 +1051,7 @@ EOF
|
||||
$aExtraParams = utils::ReadParam('extra_params', array(), false, 'raw_data');
|
||||
$aExtraParams['dashboard_div_id'] = utils::Sanitize($sId, '', 'element_identifier');
|
||||
$sDashboardFile = utils::ReadParam('file', '', false, 'string');
|
||||
$sReloadURL = utils::ReadParam('reload_url', '', false, 'raw_data');
|
||||
$sReloadURL = utils::ReadParam('reload_url', '', false, 'url');
|
||||
$oDashboard = RuntimeDashboard::GetDashboardToEdit($sDashboardFile, $sId);
|
||||
if (!is_null($oDashboard)) {
|
||||
if (!empty($sReloadURL)) {
|
||||
|
||||
@@ -236,6 +236,11 @@ try {
|
||||
throw new CoreException(Dict::S('UI:ActionNotAllowed'));
|
||||
}
|
||||
|
||||
// CSRF transaction id verification
|
||||
if(!$bSimulate && !utils::IsTransactionValid(utils::ReadPostedParam('transaction_id', '', 'raw_data'))){
|
||||
throw new CoreException(Dict::S('UI:Error:InvalidToken'));
|
||||
}
|
||||
|
||||
$aResult = array();
|
||||
$sCSVData = utils::ReadParam('csvdata', '', false, 'raw_data');
|
||||
$sCSVDataTruncated = utils::ReadParam('csvdata_truncated', '', false, 'raw_data');
|
||||
@@ -522,6 +527,7 @@ try {
|
||||
$oForm = FormUIBlockFactory::MakeStandard('wizForm');
|
||||
$oContainer->AddSubBlock($oForm);
|
||||
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("transaction_id", utils::GetNewTransactionId()));
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("step", ($iCurrentStep + 1)));
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("separator", htmlentities($sSeparator, ENT_QUOTES, 'UTF-8')));
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden("text_qualifier", htmlentities($sTextQualifier, ENT_QUOTES, 'UTF-8')));
|
||||
@@ -681,7 +687,7 @@ EOF
|
||||
// Add graphs dependencies
|
||||
WebResourcesHelper::EnableC3JSToWebPage($oPage);
|
||||
|
||||
$oPage->add_script(
|
||||
$oPage->add_script(
|
||||
<<< EOF
|
||||
function CSVGoBack()
|
||||
{
|
||||
@@ -1178,7 +1184,7 @@ EOF
|
||||
}
|
||||
|
||||
$aGuesses = GuessParameters($sUTF8Data); // Try to predict the parameters, based on the input data
|
||||
|
||||
|
||||
$iSkippedLines = utils::ReadParam('nb_skipped_lines', '');
|
||||
$bBoxSkipLines = utils::ReadParam('box_skiplines', 0);
|
||||
$sTextQualifier = utils::ReadParam('text_qualifier', '', false, 'raw_data');
|
||||
|
||||
@@ -44,12 +44,8 @@
|
||||
<testsuite name="Application">
|
||||
<directory>application</directory>
|
||||
</testsuite>
|
||||
<!-- OQL : taking too long (20min+)... we should move this to nightlies ! See N°4655 -->
|
||||
<!--testsuite name="OQL">
|
||||
<directory>OQL</directory>
|
||||
</testsuite-->
|
||||
<testsuite name="Sources">
|
||||
<directory>sources</directory>
|
||||
<testsuite name="Setup">
|
||||
<directory>setup</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Status">
|
||||
<directory>status</directory>
|
||||
|
||||
42
test/phpunit_nightly.xml.dist
Normal file
42
test/phpunit_nightly.xml.dist
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.5/phpunit.xsd"
|
||||
bootstrap="unittestautoload.php"
|
||||
backupGlobals="true"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnError="false"
|
||||
stopOnFailure="false"
|
||||
stopOnIncomplete="false"
|
||||
stopOnRisky="false"
|
||||
stopOnSkipped="false"
|
||||
verbose="true"
|
||||
>
|
||||
|
||||
<php>
|
||||
<ini name="error_reporting" value="E_ALL"/>
|
||||
<ini name="display_errors" value="On"/>
|
||||
<ini name="log_errors" value="On"/>
|
||||
<ini name="html_errors" value="On"/>
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="OQL">
|
||||
<directory>OQL</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<!-- Code coverage white list -->
|
||||
<filter>
|
||||
<whitelist>
|
||||
<file>../core/apc-emulation.php</file>
|
||||
<file>../core/ormlinkset.class.inc.php</file>
|
||||
<file>../datamodels/2.x/itop-tickets/main.itop-tickets.php</file>
|
||||
</whitelist>
|
||||
</filter>
|
||||
|
||||
</phpunit>
|
||||
Reference in New Issue
Block a user