Merge remote-tracking branch 'origin/support/3.0' into develop

This commit is contained in:
Molkobain
2022-02-02 11:20:58 +01:00
24 changed files with 568 additions and 62 deletions

View File

@@ -2,6 +2,7 @@
namespace Combodo\iTop;
use AttributeDate;
use AttributeDateTime;
use Dict;
use Exception;
@@ -55,6 +56,10 @@ class TwigExtension
{
return AttributeDateTime::GetFormat()->Format($sDate);
}
if (preg_match('@^\d\d\d\d-\d\d-\d\d$@', trim($sDate)))
{
return AttributeDate::GetFormat()->Format($sDate);
}
}
catch (Exception $e)
{

View File

@@ -1218,7 +1218,7 @@ class DeprecatedCallsLog extends LogAPI
$sMessage .= ' : '.$sAdditionalMessage;
}
static::Warning($sMessage, self::ENUM_CHANNEL_P&HP_METHOD);
static::Warning($sMessage, self::ENUM_CHANNEL_PHP_METHOD);
}
/**

View File

@@ -37,6 +37,8 @@ $ibo-input--margin-x: $ibo-spacing-200 !default;
border: 1px solid $ibo-input--border-color;
border-radius: $ibo-input--border-radius;
@extend %ibo-font-ral-nor-150;
&:focus{
border: 1px solid $ibo-input--focus--border-color;
}

View File

@@ -161,7 +161,7 @@ body.ibo-has-fullscreen-descendant {
/* Preserve original text color in code blocks, except for the Highlight.js blocks which have their own colors */
& > code,
:not(pre.hljs) code {
code:not(.hljs) {
color: inherit;
}
}

View File

@@ -52,6 +52,10 @@ $ibo-vendors-ckeditor--autocomplete-item-title--text-color: #3A3A3A !default;
white-space: pre-line;
}
.ibo-hljs-container{
padding: 0 !important;
}
/* Mentions in caselogs */
/* Note: Mind the "ul", it allows us to have a more precise rule than the original plugin's CSS so we can override it */
ul.cke_autocomplete_panel{

File diff suppressed because one or more lines are too long

View File

@@ -206,7 +206,7 @@ abstract class AbstractAttachmentsRenderer
function RefreshAttachmentsDisplay(dataUpload)
{
var sContentNode = '#AttachmentsListContainer',
aAttachmentsDeletedHiddenInputs = $('table.attachmentsList>tbody>tr[id^="display_attachment_"]>td input[name="removed_attachments[]"]'),
aAttachmentsDeletedHiddenInputs = $('#AttachmentsListContainer table>tbody>tr[id^="display_attachment_"]>td input[name="removed_attachments[]"]'),
aAttachmentsDeletedIds = aAttachmentsDeletedHiddenInputs.map(function() { return $(this).val() }).toArray();
$(sContentNode).block();
$.post(GetAbsoluteUrlModulesRoot()+'itop-attachments/ajax.itop-attachment.php',
@@ -416,7 +416,6 @@ class TableDetailsAttachmentsRenderer extends AbstractAttachmentsRenderer
$sFileDate = Dict::S('Attachments:File:Date');
$sFileUploader = Dict::S('Attachments:File:Uploader');
$sFileType = Dict::S('Attachments:File:MimeType');
$sDeleteColumn = '';
if ($bWithDeleteButton)
{
@@ -488,17 +487,9 @@ JS
{
$iAttachmentId = $oAttachment->GetKey();
$sLineClass = '';
if ($bIsEven)
{
$sLineClass = 'class="even"';
}
$sLineStyle = '';
$bIsDeletedAttachment = false;
if (in_array($iAttachmentId, $aAttachmentsDeleted, true))
{
$sLineStyle = 'style="display: none;"';
$bIsDeletedAttachment = true;
}
@@ -513,7 +504,6 @@ JS
$sFileFormattedSize = $oDoc->GetFormattedSize();
$bIsTempAttachment = ($oAttachment->Get('item_id') === 0);
$sAttachmentDateFormatted = '';
$iAttachmentDateRaw = '';
if (!$bIsTempAttachment)
{
$sAttachmentDate = $oAttachment->Get('creation_date');
@@ -523,7 +513,6 @@ JS
}
$oAttachmentDate = DateTime::createFromFormat(AttributeDateTime::GetInternalFormat(), $sAttachmentDate);
$sAttachmentDateFormatted = AttributeDateTime::GetFormat()->Format($oAttachmentDate);
$iAttachmentDateRaw = AttributeDateTime::GetAsUnixSeconds($sAttachmentDate);
}
$sAttachmentUploader = $oAttachment->Get('contact_id_friendlyname');
@@ -560,7 +549,11 @@ JS
'type' => $sFileType,
'js' => '',
);
if ($bIsDeletedAttachment) {
$aAttachmentLine['@class'] = 'ibo-is-hidden';
}
if ($bWithDeleteButton)
{
$sDeleteButton = $this->GetDeleteAttachmentButton($iAttachmentId);

View File

@@ -19,6 +19,7 @@
namespace Combodo\iTop\Portal\Twig;
use AttributeDate;
use Twig\Extension\AbstractExtension;
use AttributeDateTime;
@@ -76,6 +77,10 @@ class AppExtension extends AbstractExtension
{
return AttributeDateTime::GetFormat()->Format($sDate);
}
if (preg_match('@^\d\d\d\d-\d\d-\d\d$@', trim($sDate)))
{
return AttributeDate::GetFormat()->Format($sDate);
}
}
catch (Exception $e)
{

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -141,25 +141,27 @@ const CombodoBackofficeToolbox = {
const sComplementarySelector = bForce ? '' : ':not(.hljs)';
// AttributeHTML and HTML AttributeText
let oCodeElements = oContainerElem.find('[data-attribute-type="AttributeHTML"], [data-attribute-type="AttributeText"], [data-attribute-type="AttributeTemplateHTML"]').find('.HTML pre'+sComplementarySelector+' > code');
let oCodeElements = oContainerElem.find('[data-attribute-type="AttributeHTML"], [data-attribute-type="AttributeText"], [data-attribute-type="AttributeTemplateHTML"]').find('.HTML pre > code'+sComplementarySelector);
if (oCodeElements.length > 0) {
if (typeof hljs === 'undefined') {
CombodoJSConsole.Error('Cannot format code snippets in HTML fields as the highlight.js lib is not loaded');
} else {
oCodeElements.parent().each(function (iIdx, oElem) {
oCodeElements.each(function (iIdx, oElem) {
hljs.highlightBlock(oElem);
$(oElem).parent().addClass('ibo-hljs-container');
});
}
}
// CaseLogs
oCodeElements = oContainerElem.find('[data-role="ibo-activity-entry--main-information-content"] pre'+sComplementarySelector+' > code');
oCodeElements = oContainerElem.find('[data-role="ibo-activity-entry--main-information-content"] pre > code'+sComplementarySelector);
if (oCodeElements.length > 0) {
if (typeof hljs === 'undefined') {
CombodoJSConsole.Error('Cannot format code snippets in log entries as the highlight.js lib is not loaded');
} else {
oCodeElements.parent().each(function (iIdx, oElem) {
oCodeElements.each(function (iIdx, oElem) {
hljs.highlightBlock(oElem);
$(oElem).parent().addClass('ibo-hljs-container');
});
}
}

View File

@@ -294,8 +294,6 @@ class iTopDesignFormat
return $this->bStatus;
}
/**
* Does the conversion, eventually in a recursive manner
*
@@ -861,7 +859,22 @@ class iTopDesignFormat
foreach ($oNodeList as $oNode) {
$oNode->setAttribute('id', 'ibo-page-banner--text-content');
}
$this->RemoveNodeFromXPath('/itop_design/branding/themes/theme[@id="test-red"]/stylesheets/stylesheet[@id="environment-banner"]');
// Add new stylesheets
$oStyleSheetsNode = $oXPath->query('/itop_design/branding/themes/theme[@id="test-red"]/stylesheets')->item(0);
if ($oStyleSheetsNode) {
$oStyleSheetNode = $oStyleSheetsNode->ownerDocument->createElement("stylesheet");
$oStyleSheetNode->setAttribute('id', 'environment-banner');
$oStyleSheetNode->appendChild(new DOMText('../css/backoffice/themes/page-banner.scss'));
$oStyleSheetsNode->appendChild($oStyleSheetNode);
$oStyleSheetNode = $oStyleSheetsNode->ownerDocument->createElement("stylesheet");
$oStyleSheetNode->setAttribute('id', 'fullmoon');
$oStyleSheetNode->appendChild(new DOMText('../css/backoffice/main.scss'));
$oStyleSheetsNode->appendChild($oStyleSheetNode);
}
// Add new attribute to theme import nodes
$oNodeList = $oXPath->query('/itop_design/branding/themes/theme/imports/import');
foreach ($oNodeList as $oNode) {
@@ -956,6 +969,9 @@ class iTopDesignFormat
$oNode->setAttribute('id', 'backoffice-environment-banner-text-content');
}
$this->RemoveNodeFromXPath('/itop_design/branding/themes/theme[@id="test-red"]/stylesheets/stylesheet[@id="environment-banner"]');
$this->RemoveNodeFromXPath('/itop_design/branding/themes/theme[@id="test-red"]/stylesheets/stylesheet[@id="fullmoon"]');
// Add new attribute to theme import nodes
$oNodeList = $oXPath->query('/itop_design/branding/themes/theme/imports/import');
@@ -1000,11 +1016,13 @@ class iTopDesignFormat
* @param string $sNodeMetaVersion
*
* @return void
* @throws \Exception
*/
private function RestorePreviousNodes($sNodeMetaVersion)
{
$oXPath = new DOMXPath($this->oDocument);
$oTrashedNodes = $oXPath->query("/itop_design/meta/previous_versions/previous_version[@id='$sNodeMetaVersion']/trashed_nodes/trashed_node");
$sVersion = str_replace('.', '_', $sNodeMetaVersion);
$oTrashedNodes = $oXPath->query("/itop_design/meta/previous_versions/previous_version_$sVersion/trashed_nodes/trashed_node");
foreach ($oTrashedNodes as $oTrashedNode) {
if ($oTrashedNode->nodeType == XML_ELEMENT_NODE) {
$oXPathNode = $oXPath->query('parent_xpath', $oTrashedNode)->item(0);
@@ -1017,6 +1035,15 @@ class iTopDesignFormat
while ($oNode) {
$oNextNode = $oNode->nextSibling;
if ($oNode->nodeType == XML_ELEMENT_NODE) {
// Check for collision
$sId = $oNode->getAttribute('id');
$sNodeXPath = ($sId != '') ? $oNode->nodeName.'[@id="'.$sId.'"]' : $oNode->nodeName;
$sNodeXPath = $sXPath.'/'.$sNodeXPath;
$oTarget = $oXPath->query($sNodeXPath)->item(0);
if ($oTarget) {
// Do not continue migration
throw new Exception("Trying to restore an existing node $sNodeXPath from version $sNodeMetaVersion");
}
// Restore the modification flags
$oModifiedNodeList = $oXPath->query('descendant-or-self::*[@_disabled_delta or @_disabled_rename_from]', $oNode);
foreach ($oModifiedNodeList as $oModifiedNode) {
@@ -1038,7 +1065,7 @@ class iTopDesignFormat
}
}
// Clean up the mess
$this->RemoveNodeFromXPath("/itop_design/meta/previous_versions/previous_version[@id='$sNodeMetaVersion']", false);
$this->RemoveNodeFromXPath("/itop_design/meta/previous_versions/previous_version_$sVersion", false);
$this->RemoveEmptyNodeFromXPath("/itop_design/meta/previous_versions");
$this->RemoveEmptyNodeFromXPath("/itop_design/meta");
}
@@ -1079,9 +1106,8 @@ class iTopDesignFormat
$oItopDesignNode = $this->GetOrCreateNode('/itop_design', 'itop_design', null);
$oMetaNode = $this->GetOrCreateNode('meta', 'meta', $oItopDesignNode);
$oPreviousVersionsNode = $this->GetOrCreateNode('previous_versions', 'previous_versions', $oMetaNode);
$oPreviousVersionNode = $this->GetOrCreateNode("previous_version[@id='$this->sKeepVersion']", 'previous_version', $oPreviousVersionsNode);
$oPreviousVersionNode->setAttribute('id', $this->sKeepVersion);
//$oPreviousVersionNode->setAttribute('_delta', 'define_if_not_exists');
$sVersion = str_replace('.', '_', $this->sKeepVersion);
$oPreviousVersionNode = $this->GetOrCreateNode("previous_version_$sVersion", "previous_version_$sVersion", $oPreviousVersionsNode);
$oTrashedNodeList = $this->GetOrCreateNode('trashed_nodes', 'trashed_nodes', $oPreviousVersionNode);
$iNextId = str_replace('.', '', uniqid('', true));

View File

@@ -7,6 +7,7 @@
namespace Combodo\iTop\Application\TwigBase\Twig;
use AttributeDate;
use AttributeDateTime;
use AttributeText;
use Combodo\iTop\Application\UI\Base\iUIBlock;
@@ -56,6 +57,10 @@ class Extension
{
return AttributeDateTime::GetFormat()->Format($sDate);
}
if (preg_match('@^\d\d\d\d-\d\d-\d\d$@', trim($sDate)))
{
return AttributeDate::GetFormat()->Format($sDate);
}
}
catch (Exception $e)
{

View File

@@ -15,7 +15,7 @@
data-attribute-flag-must-change="{{ oUIBlock.IsMustChange()|var_export }}"
data-attribute-flag-must-prompt="{{ oUIBlock.IsMustPrompt()|var_export }}"
data-attribute-flag-slave="{{ oUIBlock.IsSlave()|var_export }}"
data-value-raw="{{ aParams.value_raw }}"
data-value-raw="{{ oUIBlock.GetValueRaw() }}"
{% if oUIBlock.GetDataAttributes() %}
{% for sName, sValue in oUIBlock.GetDataAttributes() %}
data-{{ sName }}="{{ sValue }}"

View File

@@ -50,10 +50,10 @@ class iTopXmlVersionIntegrationTest extends ItopTestCase
public function testItopXmlVersion()
{
// Retrieve only first 2 parts of the version
$aCoreVersionParts = explode('.', ITOP_VERSION);
$aCoreVersionParts = explode('.', ITOP_CORE_VERSION);
$sCoreVersion = $aCoreVersionParts[0].'.'.$aCoreVersionParts[1];
$sXMLVersion = ITOP_DESIGN_LATEST_VERSION;
$this->assertSame($sXMLVersion, $sCoreVersion, "XML datamodel version (ITOP_DESIGN_LATEST_VERSION={$sXMLVersion}) is not aligned with the app. core version (ITOP_VERSION={$sCoreVersion})");
$this->assertSame($sXMLVersion, $sCoreVersion, "XML datamodel version (ITOP_DESIGN_LATEST_VERSION={$sXMLVersion}) is not aligned with the app. core version (ITOP_CORE_VERSION={$sCoreVersion})");
}
}

View File

@@ -16,7 +16,7 @@
</constants>
<meta>
<previous_versions>
<previous_version id="1.6">
<previous_version_1_6>
<trashed_nodes>
<trashed_node id="XXX" _delta="define">
<parent_xpath>/itop_design/constants</parent_xpath>
@@ -31,7 +31,7 @@
</node_tree>
</trashed_node>
</trashed_nodes>
</previous_version>
</previous_version_1_6>
</previous_versions>
</meta>
</itop_design>

View File

@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.6">
<branding _revision_id="180" _delta="define">
<main_logo _revision_id="53">
<branding _revision_id="180">
<main_logo _revision_id="53" _delta="define">
<fileref ref="smile_portal_logo_7417a491754f12f744ac6311525e4db3" _revision_id="116"/>
</main_logo>
<login_logo _revision_id="53">
<login_logo _revision_id="53" _delta="define">
<fileref ref="smile_portal_logo_7417a491754f12f744ac6311525e4db3" _revision_id="116"/>
</login_logo>
<portal_logo _revision_id="53">
<portal_logo _revision_id="53" _delta="define">
<fileref ref="smile_portal_logo_7417a491754f12f744ac6311525e4db3" _revision_id="116"/>
</portal_logo>
</branding>

View File

@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.7">
<branding>
<themes>
<theme id="test-red" _delta="define">
<variables>
<variable id="backoffice-environment-banner-background-color">#C53030</variable>
<variable id="var1">#C53030</variable>
</variables>
<imports>
<import id="scss-variables">../css/scss-variables.scss</import>
<import id="css-variables">../css/css-variables.scss</import>
</imports>
<stylesheets>
<stylesheet id="custom">../css/custom.scss</stylesheet>
<stylesheet id="jqueryui">../css/ui-lightness/jqueryui.scss</stylesheet>
<stylesheet id="main">../css/main.scss</stylesheet>
</stylesheets>
</theme>
<theme id="light-grey">
<variables/>
<imports>
<import id="css-variables">../css/css-variables.scss</import>
</imports>
<stylesheets>
<stylesheet id="jqueryui">../css/ui-lightness/jqueryui.scss</stylesheet>
<stylesheet id="main">../css/light-grey.scss</stylesheet>
</stylesheets>
</theme>
</themes>
</branding>
<classes>
<class id="ClassWithStateButNoLifecycle">
<properties>
<icon>images/class-with-lifecycle.png</icon>
</properties>
</class>
<class id="ClassWithStateAndLifecycle">
<properties>
<icon>images/class-with-lifecycle.png</icon>
</properties>
<lifecycle>
<attribute>foo</attribute>
</lifecycle>
</class>
<class id="ClassWithStateAndImage">
<properties>
<icon>images/class-with-lifecycle.png</icon>
</properties>
</class>
<class id="ClassWithImageOnly">
<properties>
<icon>images/class-with-lifecycle.png</icon>
</properties>
</class>
<class id="OtherClass">
<properties>
<icon revisionid="2" _delta="redefine">
<fileref ref="company_0faae3b9d86b7c382b2e4cdae570bc3c" revisionid="62"/>
</icon>
</properties>
<fields>
<field id="status" xsi:type="AttributeEnum">
<always_load_in_tables>true</always_load_in_tables>
<values>
<value id="new">new</value>
<value id="waiting_for_approval">waiting_for_approval</value>
</values>
</field>
<field id="operational_status" xsi:type="AttributeMetaEnum">
<values>
<value id="ongoing">ongoing</value>
<value id="resolved">resolved</value>
</values>
</field>
</fields>
</class>
</classes>
<menus>
<menu id="WelcomeMenuLink1" xsi:type="WebPageMenuNode" _delta="define">
<rank>100</rank>
<parent>WelcomeMenu</parent>
<url>$$http://fr.wikipedia.org/</url>
<in_new_window>true</in_new_window>
</menu>
<menu id="RequestManagement" xsi:type="MenuGroup" _delta="define">
<rank>30</rank>
<enable_stimulus/>
</menu>
</menus>
<branding>
<main_logo _delta="define">images/itop-logo.png</main_logo>
</branding>
</itop_design>

View File

@@ -16,7 +16,7 @@
</constants>
<meta>
<previous_versions>
<previous_version id="1.6" _delta="define">
<previous_version_1_6>
<trashed_nodes>
<trashed_node id="1">
<parent_xpath>/itop_design/constants</parent_xpath>
@@ -31,7 +31,7 @@
</node_tree>
</trashed_node>
</trashed_nodes>
</previous_version>
</previous_version_1_6>
</previous_versions>
</meta>
</itop_design>

View File

@@ -12,6 +12,8 @@
</imports>
<stylesheets>
<stylesheet id="custom">../css/custom.scss</stylesheet>
<stylesheet id="environment-banner">../css/backoffice/themes/page-banner.scss</stylesheet>
<stylesheet id="fullmoon">../css/backoffice/main.scss</stylesheet>
</stylesheets>
</theme>
</themes>
@@ -108,7 +110,7 @@
</classes>
<meta>
<previous_versions>
<previous_version id="1.7">
<previous_version_1_7>
<trashed_nodes>
<trashed_node id="XXX" _delta="define">
<parent_xpath>/itop_design/branding/themes</parent_xpath>
@@ -144,7 +146,7 @@
</node_tree>
</trashed_node>
</trashed_nodes>
</previous_version>
</previous_version_1_7>
</previous_versions>
</meta>
</itop_design>

View File

@@ -135,7 +135,7 @@
</branding>
<meta>
<previous_versions>
<previous_version id="1.7" _delta="define">
<previous_version_1_7>
<trashed_nodes>
<trashed_node id="1">
<parent_xpath>/itop_design/branding/themes</parent_xpath>
@@ -171,7 +171,7 @@
</node_tree>
</trashed_node>
</trashed_nodes>
</previous_version>
</previous_version_1_7>
</previous_versions>
</meta>
</itop_design>

View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
<branding>
<themes>
<theme id="test-red" _delta="define">
<variables>
<variable id="backoffice-environment-banner-background-color">#C53030</variable>
<variable id="var1">#C53030</variable>
</variables>
<imports>
<import id="scss-variables">../css/scss-variables.scss</import>
</imports>
<stylesheets>
<stylesheet id="custom">../css/custom.scss</stylesheet>
</stylesheets>
</theme>
<theme id="light-grey" _delta="define">
<totally_new_format>
bla bla bla
</totally_new_format>
</theme>
</themes>
</branding>
<classes>
<class id="ClassWithStateButNoLifecycle">
<properties>
<icon>images/class-with-lifecycle.png</icon>
</properties>
</class>
<class id="ClassWithStateAndLifecycle">
<properties>
<icon>images/class-with-lifecycle.png</icon>
</properties>
<lifecycle>
<attribute>foo</attribute>
</lifecycle>
</class>
<class id="ClassWithStateAndImage">
<properties>
<icon>images/class-with-lifecycle.png</icon>
</properties>
</class>
<class id="ClassWithImageOnly">
<properties>
<icon>images/class-with-lifecycle.png</icon>
</properties>
</class>
<class id="OtherClass">
<properties>
<icon revisionid="2" _delta="redefine">
<fileref ref="company_0faae3b9d86b7c382b2e4cdae570bc3c" revisionid="62"/>
</icon>
</properties>
<fields>
<field id="status" xsi:type="AttributeEnum">
<always_load_in_tables>true</always_load_in_tables>
<values>
<value id="new">new</value>
<value id="waiting_for_approval">waiting_for_approval</value>
</values>
</field>
<field id="operational_status" xsi:type="AttributeMetaEnum">
<values>
<value id="ongoing">ongoing</value>
<value id="resolved">resolved</value>
</values>
</field>
</fields>
</class>
</classes>
<menus>
<menu id="WelcomeMenuLink1" xsi:type="WebPageMenuNode" _delta="define">
<rank>100</rank>
<parent>WelcomeMenu</parent>
<url>$$http://fr.wikipedia.org/</url>
<in_new_window>true</in_new_window>
</menu>
<menu id="RequestManagement" xsi:type="MenuGroup" _delta="define">
<rank>30</rank>
<enable_stimulus/>
</menu>
</menus>
<branding>
<main_logo _delta="define">images/itop-logo.png</main_logo>
</branding>
<meta>
<previous_versions>
<previous_version_1_7>
<trashed_nodes>
<trashed_node id="XXX">
<parent_xpath>/itop_design/branding/themes</parent_xpath>
<node_tree>
<theme id="light-grey">
<variables/>
<imports>
<import id="css-variables">../css/css-variables.scss</import>
</imports>
<stylesheets>
<stylesheet id="jqueryui">../css/ui-lightness/jqueryui.scss</stylesheet>
<stylesheet id="main">../css/light-grey.scss</stylesheet>
</stylesheets>
</theme>
</node_tree>
</trashed_node>
<trashed_node id="XXX">
<parent_xpath>/itop_design/branding/themes/theme[@id="test-red"]/imports</parent_xpath>
<node_tree>
<import id="css-variables">../css/css-variables.scss</import>
</node_tree>
</trashed_node>
<trashed_node id="XXX">
<parent_xpath>/itop_design/branding/themes/theme[@id="test-red"]/stylesheets</parent_xpath>
<node_tree>
<stylesheet id="jqueryui">../css/ui-lightness/jqueryui.scss</stylesheet>
</node_tree>
</trashed_node>
<trashed_node id="XXX">
<parent_xpath>/itop_design/branding/themes/theme[@id="test-red"]/stylesheets</parent_xpath>
<node_tree>
<stylesheet id="main">../css/main.scss</stylesheet>
</node_tree>
</trashed_node>
</trashed_nodes>
</previous_version_1_7>
</previous_versions>
</meta>
</itop_design>

View File

@@ -0,0 +1,182 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
<branding>
<themes>
<theme id="test-red" _delta="define">
<variables>
<variable id="ibo-page-banner--background-color">#C53030</variable>
<variable id="var1">#C53030</variable>
</variables>
<imports>
<import id="scss-variables" xsi:type="utilities">../css/scss-variables.scss</import>
</imports>
<stylesheets>
<stylesheet id="custom">../css/custom.scss</stylesheet>
</stylesheets>
</theme>
<theme id="light-grey" _delta="define">
<totally_new_format>
bla bla bla
</totally_new_format>
</theme>
</themes>
</branding>
<classes>
<class id="ClassWithStateButNoLifecycle">
<properties>
<style>
<icon>images/class-with-lifecycle.png</icon>
</style>
<fields_semantic>
<state_attribute>foo</state_attribute>
</fields_semantic>
</properties>
</class>
<class id="ClassWithStateAndLifecycle">
<properties>
<style>
<icon>images/class-with-lifecycle.png</icon>
</style>
<fields_semantic>
<state_attribute>foo</state_attribute>
</fields_semantic>
</properties>
<lifecycle/>
</class>
<class id="ClassWithStateAndImage">
<properties>
<style>
<icon>images/class-with-lifecycle.png</icon>
</style>
<fields_semantic>
<state_attribute>foo</state_attribute>
<image_attribute>bar</image_attribute>
</fields_semantic>
</properties>
</class>
<class id="ClassWithImageOnly">
<properties>
<style>
<icon>images/class-with-lifecycle.png</icon>
</style>
<fields_semantic>
<image_attribute>bar</image_attribute>
</fields_semantic>
</properties>
</class>
<class id="OtherClass">
<properties>
<style>
<icon revisionid="2" _delta="redefine">
<fileref ref="company_0faae3b9d86b7c382b2e4cdae570bc3c" revisionid="62"/>
</icon>
<main_color>#4E79A5</main_color>
<complementary_color>white</complementary_color>
</style>
</properties>
<fields>
<field id="status" xsi:type="AttributeEnum">
<always_load_in_tables>true</always_load_in_tables>
<values>
<value id="new">
<code>new</code>
<style>
<main_color>#2C5382</main_color>
<complementary_color>#FFFFFF</complementary_color>
<decoration_classes/>
</style>
</value>
<value id="waiting_for_approval">
<code>waiting_for_approval</code>
</value>
</values>
<default_style>
<main_color>#2B6CB0</main_color>
<complementary_color>#FFFFFF</complementary_color>
<decoration_classes/>
</default_style>
</field>
<field id="operational_status" xsi:type="AttributeMetaEnum">
<values>
<value id="ongoing">
<code>ongoing</code>
<style>
<main_color>#2C5382</main_color>
<complementary_color>#FFFFFF</complementary_color>
<decoration_classes/>
</style>
</value>
<value id="resolved">
<code>resolved</code>
</value>
</values>
<default_style>
<main_color>#2B6CB0</main_color>
<complementary_color>#FFFFFF</complementary_color>
<decoration_classes/>
</default_style>
</field>
</fields>
</class>
</classes>
<menus>
<menu id="WelcomeMenuLink1" xsi:type="WebPageMenuNode" _delta="define">
<rank>100</rank>
<parent>WelcomeMenu</parent>
<url>$$http://fr.wikipedia.org/</url>
<in_new_window>true</in_new_window>
</menu>
<menu id="RequestManagement" xsi:type="MenuGroup" _delta="define">
<rank>30</rank>
<enable_stimulus/>
<style>
<decoration_classes>fas fa-comment-alt</decoration_classes>
</style>
</menu>
</menus>
<branding>
<main_logo _delta="define">images/itop-logo.png</main_logo>
<main_logo_compact _delta="define">images/itop-logo-square.png</main_logo_compact>
</branding>
<meta>
<previous_versions>
<previous_version_1_7>
<trashed_nodes>
<trashed_node id="1">
<parent_xpath>/itop_design/branding/themes</parent_xpath>
<node_tree>
<theme id="light-grey">
<variables/>
<imports>
<import id="css-variables">../css/css-variables.scss</import>
</imports>
<stylesheets>
<stylesheet id="jqueryui">../css/ui-lightness/jqueryui.scss</stylesheet>
<stylesheet id="main">../css/light-grey.scss</stylesheet>
</stylesheets>
</theme>
</node_tree>
</trashed_node>
<trashed_node id="2">
<parent_xpath>/itop_design/branding/themes/theme[@id="test-red"]/imports</parent_xpath>
<node_tree>
<import id="css-variables">../css/css-variables.scss</import>
</node_tree>
</trashed_node>
<trashed_node id="3">
<parent_xpath>/itop_design/branding/themes/theme[@id="test-red"]/stylesheets</parent_xpath>
<node_tree>
<stylesheet id="jqueryui">../css/ui-lightness/jqueryui.scss</stylesheet>
</node_tree>
</trashed_node>
<trashed_node id="4">
<parent_xpath>/itop_design/branding/themes/theme[@id="test-red"]/stylesheets</parent_xpath>
<node_tree>
<stylesheet id="main">../css/main.scss</stylesheet>
</node_tree>
</trashed_node>
</trashed_nodes>
</previous_version_1_7>
</previous_versions>
</meta>
</itop_design>

View File

@@ -35,11 +35,10 @@ class TestForITopDesignFormatClass extends ItopTestCase
*
* @throws \Exception
*/
public function testConvert($sTargetVersion, $sXmlFileName)
public function testConvert($sTargetVersion, $sXmlFileName, $iExpectedErrors = 0, $sFirstErrorMessage = '')
{
$sSamplesRelDirPath = 'Convert-samples/';
$sInputXml = $this->GetFileContent($sSamplesRelDirPath.$sXmlFileName.'.input');
$sExpectedXml = $this->GetFileContent($sSamplesRelDirPath.$sXmlFileName.'.expected');
$oInputDocument = new DOMDocument();
libxml_clear_errors();
@@ -47,24 +46,84 @@ class TestForITopDesignFormatClass extends ItopTestCase
$oInputDocument->loadXML($sInputXml);
$oInputDocument->formatOutput = true;
$oDesignFormat = new iTopDesignFormat($oInputDocument);
$oDesignFormat->Convert($sTargetVersion);
$sConvertedXml = $oInputDocument->saveXML();
$bResult = $oDesignFormat->Convert($sTargetVersion);
$aErrors = $oDesignFormat->GetErrors();
$this->assertCount($iExpectedErrors, $aErrors);
if ($iExpectedErrors > 0) {
$this->assertFalse($bResult);
$this->assertEquals($sFirstErrorMessage, $aErrors[0]);
}
$sConvertedXml = $oInputDocument->saveXML();
// Erase dynamic values
$sConvertedXml = preg_replace('@<trashed_node id="\w+"@', '<trashed_node id="XXX"', $sConvertedXml);
$sExpectedXml = $this->GetFileContent($sSamplesRelDirPath.$sXmlFileName.'.expected');
$this->assertEquals($sExpectedXml, $sConvertedXml);
}
public function ConvertProvider()
{
return [
'1.7 to 1.6' => ['1.6', '1.7_to_1.6'],
'1.6 to 1.7 2' => ['1.7', '1.6_to_1.7_2'],
'1.7 to 1.6 2' => ['1.6', '1.7_to_1.6_2'],
'1.7 to 3.0' => ['3.0', '1.7_to_3.0'],
'3.0 to 1.7' => ['1.7', '3.0_to_1.7'],
'3.0 to 1.7 no previous' => ['1.7', '3.0_to_1.7_no_previous'],
'3.0 to 1.7 collision' => ['1.7', '3.0_to_1.7_collision', 1, 'Trying to restore an existing node /itop_design/branding/themes/theme[@id="light-grey"] from version 1.7'],
];
}
/**
* @covers iTopDesignFormat::Convert
* @dataProvider ConvertBackAndForthProvider
*
* @param string $sTargetVersion
* @param string $sXmlFileName Example "1.7_to_1.6". Corresponding files should exist with the ".input" and ".Expected" suffix
*
* @throws \Exception
*/
public function testConvertBackAndForth($sTargetVersion, $sXmlFileName)
{
$sSamplesRelDirPath = 'Convert-samples/';
$sInputXml = $this->GetFileContent($sSamplesRelDirPath.$sXmlFileName.'.input');
$oInputDocument = new DOMDocument();
libxml_clear_errors();
$oInputDocument->preserveWhiteSpace = false;
$oInputDocument->loadXML($sInputXml);
$oXPath = new DOMXPath($oInputDocument);
$oItopDesignNode = $oXPath->query('/itop_design')->item(0);
if (!$oItopDesignNode) {
$this->fail('Bad XML format');
}
$sSourceVersion = $oItopDesignNode->getAttribute('version');
$oInputDocument->formatOutput = true;
$oDesignFormat = new iTopDesignFormat($oInputDocument);
$oDesignFormat->Convert($sTargetVersion);
$sConvertedXml = $oInputDocument->saveXML();
// Convert back
$oInputDocument = new DOMDocument();
libxml_clear_errors();
$oInputDocument->preserveWhiteSpace = false;
$oInputDocument->loadXML($sConvertedXml);
$oInputDocument->formatOutput = true;
$oDesignFormat = new iTopDesignFormat($oInputDocument);
$oDesignFormat->Convert($sSourceVersion);
$sConvertedXml = $oInputDocument->saveXML();
$this->assertEquals($sInputXml, $sConvertedXml);
}
public function ConvertBackAndForthProvider()
{
return array(
'1.7 to 1.6' => array('1.6', '1.7_to_1.6'),
'1.6 to 1.7 2' => array('1.7', '1.6_to_1.7_2'),
'1.7 to 1.6 2' => array('1.6', '1.7_to_1.6_2'),
'1.7 to 3.0' => array('3.0', '1.7_to_3.0'),
'3.0 to 1.7' => array('1.7', '3.0_to_1.7'),
'3.0 to 1.7 no previous' => array('1.7', '3.0_to_1.7_no_previous'),
'1.6 to 1.7' => array('1.7', '1.6_to_1.7_2'),
'1.6 to 3.0' => array('3.0', '1.6_to_1.7_2'),
'1.7 to 3.0' => array('3.0', '1.7'),
);
}