From 3a990f46d3da23421569ce847a2b17c5a571911b Mon Sep 17 00:00:00 2001 From: Molkobain Date: Fri, 22 Mar 2024 09:46:31 +0100 Subject: [PATCH 01/21] =?UTF-8?q?N=C2=B07157=20-=20Add=20'subscription=5Fp?= =?UTF-8?q?olicy'=20to=20remaning=20Trigger=20zlists?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/trigger.class.inc.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/trigger.class.inc.php b/core/trigger.class.inc.php index ba193b773..ba760e9df 100644 --- a/core/trigger.class.inc.php +++ b/core/trigger.class.inc.php @@ -185,7 +185,7 @@ abstract class TriggerOnObject extends Trigger MetaModel::Init_AddAttribute(new AttributeOQL("filter", array("allowed_values" => null, "sql" => "filter", "default_value" => null, "is_null_allowed" => true, "depends_on" => array()))); // Display lists - MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'description')); // Attributes to be displayed for a list // Search criteria MetaModel::Init_SetZListItems('default_search', array('description', 'target_class')); // Default criteria of the search banner @@ -385,7 +385,7 @@ class TriggerOnPortalUpdate extends TriggerOnObject MetaModel::Init_InheritAttributes(); // Display lists - MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'description')); // Attributes to be displayed for a list // Search criteria } @@ -418,7 +418,7 @@ abstract class TriggerOnStateChange extends TriggerOnObject MetaModel::Init_AddAttribute(new AttributeClassState("state", array("class_field" => 'target_class', "allowed_values" => null, "sql" => "state", "default_value" => null, "is_null_allowed" => false, "depends_on" => array('target_class')))); // Display lists - MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'action_list')); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'state')); // Attributes to be displayed for a list // Search criteria MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class', 'state')); // Criteria of the std search form @@ -840,7 +840,7 @@ class TriggerOnThresholdReached extends TriggerOnObject MetaModel::Init_AddAttribute(new AttributeString("threshold_index", array("allowed_values" => null, "sql" => "threshold_index", "default_value" => null, "is_null_allowed" => false, "depends_on" => array()))); // Display lists - MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'stop_watch_code', 'threshold_index', 'filter', 'action_list')); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'stop_watch_code', 'threshold_index', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('list', array('target_class', 'threshold_index', 'threshold_index')); // Attributes to be displayed for a list // Search criteria MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form From 90458f604833fc97ea016460a4d38a089d8afe6f Mon Sep 17 00:00:00 2001 From: Eric Espie Date: Fri, 22 Mar 2024 10:11:25 +0100 Subject: [PATCH 02/21] =?UTF-8?q?N=C2=B06974=20-=20Flatten=20classes=20in?= =?UTF-8?q?=20datamodel=20-=20Allow=20=5Fdelta=3D"merge"=20in=20strict=20m?= =?UTF-8?q?ode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/designdocument.class.inc.php | 20 ++ setup/modelfactory.class.inc.php | 10 +- .../unitary-tests/setup/ModelFactoryTest.php | 223 ++++++++++++++---- 3 files changed, 201 insertions(+), 52 deletions(-) diff --git a/core/designdocument.class.inc.php b/core/designdocument.class.inc.php index e04c0fb54..6137f7fd1 100644 --- a/core/designdocument.class.inc.php +++ b/core/designdocument.class.inc.php @@ -339,6 +339,26 @@ class DesignElement extends \DOMElement return false; } + /** + * True if the node is contained in a _delta="merge" tree + * @return bool + */ + public function IsInSpecifiedMerge(): bool + { + // Iterate through the parents: reset the flag if any of them has a flag set + for ($oParent = $this; $oParent instanceof MFElement; $oParent = $oParent->parentNode) { + $sDeltaSpec = $oParent->getAttribute('_delta'); + if ($sDeltaSpec === 'merge') { + return true; + } + if (in_array($sDeltaSpec, ['define', 'define_if_not_exists', 'force', 'redefine'])) { + return false; + } + } + + return false; + } + /** * Find the child node matching the given node. * UNSAFE: may return nodes marked as _alteration="removed" diff --git a/setup/modelfactory.class.inc.php b/setup/modelfactory.class.inc.php index 573f19b26..945f3c703 100644 --- a/setup/modelfactory.class.inc.php +++ b/setup/modelfactory.class.inc.php @@ -832,6 +832,7 @@ class ModelFactory case '': $bMustExist = ($sDeltaSpec === 'must_exist'); $bIfExists = ($sDeltaSpec === 'if_exists'); + $bSpecifiedMerge = $oSourceNode->IsInSpecifiedMerge(); /** @var MFElement $oTargetNode */ $oTargetNode = $oTargetParentNode->_FindChildNode($oSourceNode, $sSearchId); @@ -847,7 +848,7 @@ class ModelFactory // Do not continue deeper $oTargetNode = null; } else { - if ($sMode === self::LOAD_DELTA_MODE_STRICT && ($sSearchId !== '' || is_null($oSourceNode->firstElementChild))) { + if (!$bSpecifiedMerge && $sMode === self::LOAD_DELTA_MODE_STRICT && ($sSearchId !== '' || is_null($oSourceNode->firstElementChild))) { $iLine = ModelFactory::GetXMLLineNumber($oSourceNode); $sItopNodePath = DesignDocument::GetItopNodePath($oSourceNode); throw new MFException($sItopNodePath.' at line '.$iLine.': could not be found or marked as removed (strict mode)', @@ -867,12 +868,15 @@ class ModelFactory // Do not continue deeper everything is already copied $oTargetNode = null; } else { - // copy the node with attributes and continue deeper + // copy the node with attributes (except _delta) and continue deeper $oTargetNode = $oTargetDocument->importNode($oSourceNode, false); foreach ($oSourceNode->attributes as $oAttributeNode) { $oTargetNode->setAttribute($oAttributeNode->name, $oAttributeNode->value); } - if ($sSearchId !== '') { + if ($oTargetNode->hasAttribute('_delta')) { + $oTargetNode->removeAttribute('_delta'); + } + if ($sSearchId !== '' || $bSpecifiedMerge) { // Add the node by default $oTargetParentNode->AddChildNode($oTargetNode); } else { diff --git a/tests/php-unit-tests/unitary-tests/setup/ModelFactoryTest.php b/tests/php-unit-tests/unitary-tests/setup/ModelFactoryTest.php index 7fd9f2a60..f213e06dd 100644 --- a/tests/php-unit-tests/unitary-tests/setup/ModelFactoryTest.php +++ b/tests/php-unit-tests/unitary-tests/setup/ModelFactoryTest.php @@ -75,10 +75,12 @@ class ModelFactoryTest extends ItopTestCase // Canonicalize the expected XML (to cope with indentation) $oExpectedDocument = new DOMDocument(); $oExpectedDocument->preserveWhiteSpace = false; - $oExpectedDocument->loadXML($sXML); $oExpectedDocument->formatOutput = true; + $oExpectedDocument->loadXML($sXML); - return $oExpectedDocument->C14N(false, true); + $sSavedXML = $oExpectedDocument->SaveXML(); + + return str_replace(' encoding="UTF-8"', '', $sSavedXML); } /** @@ -665,7 +667,7 @@ class ModelFactoryTest extends ItopTestCase $oFactory = $this->MakeVanillaModelFactory($sInitialXML); $oFactoryDocument = $this->GetNonPublicProperty($oFactory, 'oDOMDocument'); $sExpectedXML = null; - if (\utils::StartsWith($sExpectedXMLOrErrorMessage, '<')) { + if (\utils::StartsWith(trim($sExpectedXMLOrErrorMessage), '<')) { $sExpectedXML = $sExpectedXMLOrErrorMessage; } @@ -3026,14 +3028,16 @@ XML , ], 'Conditionally deleted class' => [ - 'sInitialXMLInternal' => ' + 'sInitialXMLInternal' => ' + ', - 'sExpectedXMLDelta' => ' + 'sExpectedXMLDelta' => ' + @@ -3411,15 +3415,21 @@ XML $oDocument->loadXML($sDeltaXML); /* @var MFElement $oDeltaRoot */ $oDeltaRoot = $oDocument->firstChild; + $sExpectedXML = null; + if (\utils::StartsWith(trim($sExpectedXMLInLaxMode), '<')) { + $sExpectedXML = $sExpectedXMLInLaxMode; + } try { $oFactory->LoadDelta($oDeltaRoot, $oFactoryDocument, ModelFactory::LOAD_DELTA_MODE_LAX); - $this->AssertEqualModels($sExpectedXMLInLaxMode, $oFactory, 'LoadDelta(lax) did not produce the expected result'); + $this->assertNotNull($sExpectedXML, "LoadDelta(lax) should have failed with exception: $sExpectedXMLInLaxMode"); + $this->AssertEqualModels($sExpectedXML, $oFactory, 'LoadDelta(lax) did not produce the expected result'); } catch (ExpectationFailedException $e) { throw $e; } catch (\Exception $e) { - $this->assertNull($sExpectedXMLInLaxMode, 'LoadDelta(lax) should not have failed with exception: '.$e->getMessage()); + $this->assertNull($sExpectedXML, 'LoadDelta(lax) should not have failed with exception: '.$e->getMessage()); + $this->assertEquals($sExpectedXMLInLaxMode, $e->getMessage()); } // Load in Strict mode @@ -3430,118 +3440,233 @@ XML $oDocument->loadXML($sDeltaXML); /* @var MFElement $oDeltaRoot */ $oDeltaRoot = $oDocument->firstChild; + $sExpectedXML = null; + if (\utils::StartsWith(trim($sExpectedXMLInStrictMode), '<')) { + $sExpectedXML = $sExpectedXMLInStrictMode; + } try { $oFactory->LoadDelta($oDeltaRoot, $oFactoryDocument, ModelFactory::LOAD_DELTA_MODE_STRICT); - $this->AssertEqualModels($sExpectedXMLInStrictMode, $oFactory, 'LoadDelta(strict) did not produce the expected result'); + $this->assertNotNull($sExpectedXML, "LoadDelta(lax) should have failed with exception: $sExpectedXMLInStrictMode"); + $this->AssertEqualModels($sExpectedXML, $oFactory, 'LoadDelta(strict) did not produce the expected result'); } catch (ExpectationFailedException $e) { throw $e; } catch (\Exception $e) { - $this->assertNull($sExpectedXMLInStrictMode, 'LoadDelta(strict) should not have failed with exception: '.$e->getMessage()); + $this->assertNull($sExpectedXML, 'LoadDelta(strict) should not have failed with exception: '.$e->getMessage()); + $this->assertEquals($sExpectedXMLInStrictMode, $e->getMessage()); } } - public function LoadDeltaModeProvider() { return [ - 'merge delta have different behavior depending on the mode' => [ + 'default no _delta have different behavior depending on the mode' => [ 'sInitialXML' => ' - - + ', - 'sDeltaXML' => ' + 'sDeltaXML' => ' + cmdbAbstractObject ', - 'sExpectedXMLInLaxMode' => ' + 'sExpectedXMLInLaxMode' => ' + cmdbAbstractObject ', - 'sExpectedXMLInStrictMode' => null, + 'sExpectedXMLInStrictMode' => '/itop_design/nodeA/nodeB[C_1] at line 4: could not be found or marked as removed (strict mode)', ], + 'mode specified in delta takes precedence' => [ 'sInitialXML' => ' - - + ', - 'sDeltaXML' => ' + 'sDeltaXML' => ' + cmdbAbstractObject ', - 'sExpectedXMLInLaxMode' => null, - 'sExpectedXMLInStrictMode' => null, + 'sExpectedXMLInLaxMode' => '/itop_design/nodeA/nodeB[C_1] at line 4: could not be found or marked as removed (strict mode)', + 'sExpectedXMLInStrictMode' => '/itop_design/nodeA/nodeB[C_1] at line 4: could not be found or marked as removed (strict mode)', ], - 'merge leaf nodes have different behavior depending on the mode' => [ + + 'default no _delta leaf nodes have different behavior depending on the mode' => [ 'sInitialXML' => ' - Test + Test ', - 'sDeltaXML' => ' + 'sDeltaXML' => ' + Taste ', - 'sExpectedXMLInLaxMode' => ' - Taste + 'sExpectedXMLInLaxMode' => ' + + Taste ', - 'sExpectedXMLInStrictMode' => null, + 'sExpectedXMLInStrictMode' => '/itop_design/nodeA at line 3: cannot be modified without _delta flag (strict mode)', ], - 'merge existing leaf nodes without text have same behavior' => [ + + 'default no _delta on existing leaf nodes without text have same behavior' => [ 'sInitialXML' => ' - -', - 'sDeltaXML' => ' ', - 'sExpectedXMLInLaxMode' => ' - -', - 'sExpectedXMLInStrictMode' => ' - -', - ], - 'merge non-existing leaf nodes without text have different behavior' => [ - 'sInitialXML' => ' + 'sDeltaXML' => ' -', - 'sDeltaXML' => ' ', - 'sExpectedXMLInLaxMode' => ' - + 'sExpectedXMLInLaxMode' => ' + + +', + 'sExpectedXMLInStrictMode' => ' + + ', - 'sExpectedXMLInStrictMode' => null, ], - 'merge non-existing nodes with sub-nodes defined' => [ + + 'default no _delta on non-existing leaf nodes without text have different behavior' => [ 'sInitialXML' => ' ', - 'sDeltaXML' => ' + 'sDeltaXML' => ' + + +', + 'sExpectedXMLInLaxMode' => ' + + +', + 'sExpectedXMLInStrictMode' => '/itop_design/nodeA at line 3: could not be found or marked as removed (strict mode)', + ], + + 'default no _delta on non-existing nodes with sub-nodes defined' => [ + 'sInitialXML' => ' + +', + 'sDeltaXML' => ' + ', - 'sExpectedXMLInLaxMode' => ' + 'sExpectedXMLInLaxMode' => ' + ', - 'sExpectedXMLInStrictMode' => ' + 'sExpectedXMLInStrictMode' => ' + +', + ], + + 'merge _delta on non-existing node must create node' => [ + 'sInitialXML' => ' + + + + +', + 'sDeltaXML' => ' + + + + + + Test + + + + +', + 'sExpectedXMLInLaxMode' => ' + + + + + + Test + + + + +', + 'sExpectedXMLInStrictMode' => ' + + + + + + Test + + + + +', + ], + + 'merge _delta on existing tree must merge...' => [ + 'sInitialXML' => ' + + + + + + + + +', + 'sDeltaXML' => ' + + + + + + Test + + + + +', + 'sExpectedXMLInLaxMode' => ' + + + + + + Test + + + + +', + 'sExpectedXMLInStrictMode' => ' + + + + + + Test + + + + ', ], ]; From e7a04e0e704ec52e84cd63ee93bc9f5a4436c809 Mon Sep 17 00:00:00 2001 From: Molkobain Date: Fri, 22 Mar 2024 11:38:02 +0100 Subject: [PATCH 03/21] =?UTF-8?q?N=C2=B07331=20-=20Fix=20cleanup=20script?= =?UTF-8?q?=20to=20remove=20all=20denied=20folders?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- node_modules/tippy.js/README.md | 2 +- .../tippy.js/dist/tippy-bundle.umd.js | 391 ++++++++++++++---- .../tippy.js/dist/tippy-bundle.umd.js.map | 2 +- .../tippy.js/dist/tippy-bundle.umd.min.js | 2 +- .../tippy.js/dist/tippy-bundle.umd.min.js.map | 2 +- node_modules/tippy.js/dist/tippy.cjs.js | 389 +++++++++++++---- node_modules/tippy.js/dist/tippy.cjs.js.map | 2 +- node_modules/tippy.js/dist/tippy.css | 2 +- node_modules/tippy.js/dist/tippy.esm.js | 391 ++++++++++++++---- node_modules/tippy.js/dist/tippy.esm.js.map | 2 +- node_modules/tippy.js/dist/tippy.umd.js | 389 +++++++++++++---- node_modules/tippy.js/dist/tippy.umd.js.map | 2 +- node_modules/tippy.js/dist/tippy.umd.min.js | 2 +- .../tippy.js/dist/tippy.umd.min.js.map | 2 +- .../headless/dist/tippy-headless.cjs.js | 389 +++++++++++++---- .../headless/dist/tippy-headless.cjs.js.map | 2 +- .../headless/dist/tippy-headless.esm.js | 391 ++++++++++++++---- .../headless/dist/tippy-headless.esm.js.map | 2 +- .../headless/dist/tippy-headless.umd.js | 385 +++++++++++++---- .../headless/dist/tippy-headless.umd.js.map | 2 +- .../headless/dist/tippy-headless.umd.min.js | 2 +- .../dist/tippy-headless.umd.min.js.map | 2 +- node_modules/tippy.js/index.d.ts | 3 + node_modules/tippy.js/package.json | 14 +- .../Dependencies/AbstractFolderAnalyzer.php | 4 +- sources/Dependencies/NPM/iTopNPM.php | 34 +- 26 files changed, 2216 insertions(+), 594 deletions(-) diff --git a/node_modules/tippy.js/README.md b/node_modules/tippy.js/README.md index ff449c80c..42cbc8d2c 100644 --- a/node_modules/tippy.js/README.md +++ b/node_modules/tippy.js/README.md @@ -52,7 +52,7 @@ The core CSS comes bundled with the default unpkg import. ## Usage For detailed usage information, -[visit the docs](https://atomiks.github.io/tippyjs/v6/creation/). +[visit the docs](https://atomiks.github.io/tippyjs/v6/getting-started/). ## Component Wrappers diff --git a/node_modules/tippy.js/dist/tippy-bundle.umd.js b/node_modules/tippy.js/dist/tippy-bundle.umd.js index 0653b228e..5f58c281f 100644 --- a/node_modules/tippy.js/dist/tippy-bundle.umd.js +++ b/node_modules/tippy.js/dist/tippy-bundle.umd.js @@ -1,6 +1,6 @@ /**! -* tippy.js v6.2.5 -* (c) 2017-2020 atomiks +* tippy.js v6.3.7 +* (c) 2017-2021 atomiks * MIT License */ (function (global, factory) { @@ -9,7 +9,7 @@ (global = global || self, global.tippy = factory(global.Popper)); }(this, (function (core) { 'use strict'; - var css = ".tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:\"\";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1}"; + var css = ".tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:\"\";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1}"; function injectCSS(css) { var style = document.createElement('style'); @@ -26,8 +26,8 @@ } var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined'; - var ua = isBrowser ? navigator.userAgent : ''; - var isIE = /MSIE |Trident\//.test(ua); + var isIE11 = isBrowser ? // @ts-ignore + !!window.msCrypto : false; var ROUND_ARROW = ''; var BOX_CLASS = "tippy-box"; @@ -39,6 +39,9 @@ passive: true, capture: true }; + var TIPPY_DEFAULT_APPEND_TO = function TIPPY_DEFAULT_APPEND_TO() { + return document.body; + }; function hasOwnProperty(obj, key) { return {}.hasOwnProperty.call(obj, key); @@ -158,10 +161,13 @@ }); } function getOwnerDocument(elementOrElements) { - var _normalizeToArray = normalizeToArray(elementOrElements), - element = _normalizeToArray[0]; + var _element$ownerDocumen; - return element ? element.ownerDocument || document : document; + var _normalizeToArray = normalizeToArray(elementOrElements), + element = _normalizeToArray[0]; // Elements created via a