diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index f9a0cd7bc4..163794deb2 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -43,8 +43,20 @@ require_once(APPROOT.'sources/application/search/criterionconversionabstract.cla require_once(APPROOT.'sources/application/search/criterionconversion/criteriontooql.class.inc.php'); require_once(APPROOT.'sources/application/search/criterionconversion/criteriontosearchform.class.inc.php'); +/** + * Class cmdbAbstractObject + */ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay { + /** @var string ENUM_OBJECT_MODE_VIEW */ + const ENUM_OBJECT_MODE_VIEW = 'view'; + /** @var string ENUM_OBJECT_MODE_EDIT */ + const ENUM_OBJECT_MODE_EDIT = 'edit'; + /** @var string ENUM_OBJECT_MODE_CREATE */ + const ENUM_OBJECT_MODE_CREATE = 'create'; + /** @var string ENUM_OBJECT_MODE_STIMULUS */ + const ENUM_OBJECT_MODE_STIMULUS = 'stimulus'; + protected $m_iFormId; // The ID of the form used to edit the object (when in edition mode !) protected static $iGlobalFormId = 1; protected $aFieldsMap; @@ -819,6 +831,9 @@ EOF } foreach($aFields as $sAttCode) { + $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); + $sAttDefClass = get_class($oAttDef); + if ($bEditMode) { $sComments = isset($aFieldsComments[$sAttCode]) ? $aFieldsComments[$sAttCode] : ''; @@ -829,7 +844,6 @@ EOF // the caller may override some flags if needed $iFlags = $iFlags | $aExtraFlags[$sAttCode]; } - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); if ((!$oAttDef->IsLinkSet()) && (($iFlags & OPT_ATT_HIDDEN) == 0) && !($oAttDef instanceof AttributeDashboard)) { $sInputId = $this->m_iFormId.'_'.$sAttCode; @@ -844,7 +858,6 @@ EOF 'value' => $sHTMLValue, 'comments' => $sComments, 'infos' => $sInfos, - 'attcode' => $sAttCode, ); } else @@ -891,7 +904,6 @@ EOF 'value' => $sHTMLValue, 'comments' => $sComments, 'infos' => $sInfos, - 'attcode' => $sAttCode, ); } } @@ -902,29 +914,14 @@ EOF 'value' => "".$this->GetAsHTML($sAttCode)."", 'comments' => $sComments, 'infos' => $sInfos, - 'attcode' => $sAttCode, ); $aFieldsMap[$sAttCode] = $sInputId; } - - // Checking how the field should be rendered - // Note: For view mode, this is done in cmdbAbstractObject::GetFieldAsHtml() - // Note 2: Shouldn't this be a property of the AttDef instead an array that we have to maintain? - if (in_array($oAttDef->GetEditClass(), - array('Text', 'HTML', 'CaseLog', 'CustomFields', 'OQLExpression'))) - { - $val['layout'] = 'large'; - } - else - { - $val['layout'] = 'small'; - } } else { $val = null; // Skip this field } - } else { @@ -934,6 +931,26 @@ EOF if ($val != null) { + // Add extra data for markup generation + // - Attribute code and AttributeDef. class + $val['attcode'] = $sAttCode; + $val['atttype'] = $sAttDefClass; + + // - How the field should be rendered + $val['layout'] = (in_array($oAttDef->GetEditClass(), static::GetAttEditClassesToRenderAsLargeField())) ? 'large' : 'small'; + + // - For simple fields, we get the raw (stored) value as well + $bExcludeRawValue = false; + foreach (static::GetAttDefClassesToExcludeFromMarkupMetadataRawValue() as $sAttDefClassToExclude) + { + if (is_a($sAttDefClass, $sAttDefClassToExclude, true)) + { + $bExcludeRawValue = true; + break; + } + } + $val['value_raw'] = ($bExcludeRawValue === false) ? $this->Get($sAttCode) : ''; + // The field is visible, add it to the current column $aDetails[$sTab][$sColIndex][] = $val; $iInputId++; @@ -974,17 +991,21 @@ EOF */ public function DisplayDetails(WebPage $oPage, $bEditMode = false) { - $sTemplate = Utils::ReadFromFile(MetaModel::GetDisplayTemplate(get_class($this))); + $sClass = get_class($this); + $iKey = $this->GetKey(); + $sMode = static::ENUM_OBJECT_MODE_VIEW; + + $sTemplate = Utils::ReadFromFile(MetaModel::GetDisplayTemplate($sClass)); if (!empty($sTemplate)) { $oTemplate = new DisplayTemplate($sTemplate); // Note: to preserve backward compatibility with home-made templates, the placeholder '$pkey$' has been preserved // but the preferred method is to use '$id$' $oTemplate->Render($oPage, array( - 'class_name' => MetaModel::GetName(get_class($this)), - 'class' => get_class($this), - 'pkey' => $this->GetKey(), - 'id' => $this->GetKey(), + 'class_name' => MetaModel::GetName($sClass), + 'class' => $sClass, + 'pkey' => $iKey, + 'id' => $iKey, 'name' => $this->GetName(), )); } @@ -992,7 +1013,11 @@ EOF { // Object's details // template not found display the object using the *old style* - $oPage->add('
'); + $oPage->add(<< +
+HTML + ); $this->DisplayBareHeader($oPage, $bEditMode); /** @var \iTopWebPage $oPage */ $oPage->AddTabContainer(OBJECT_PROPERTIES_TAB); @@ -1003,8 +1028,11 @@ EOF //$oPage->SetCurrentTab(Dict::S('UI:HistoryTab')); //$this->DisplayBareHistory($oPage, $bEditMode); $oPage->AddAjaxTab(Dict::S('UI:HistoryTab'), - utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=history&class='.get_class($this).'&id='.$this->GetKey()); - $oPage->add('
'); + utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=history&class='.$sClass.'&id='.$iKey); + $oPage->add(<< +HTML + ); } } @@ -2399,15 +2427,31 @@ EOF $oPage->add_dict_entry('UI:ValueMustBeChanged'); $oPage->add_dict_entry('UI:ValueInvalidFormat'); + // Note: In 2.8, remove the data-attcode attribute (either because it's has been moved to .field_container in 2.7 or even better because the admin. console has been reworked) return "
{$sHTMLValue}
"; } + /** + * @param \WebPage $oPage + * @param array $aExtraParams + * + * @throws \ArchivedObjectException + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \DictExceptionMissingString + * @throws \MissingQueryArgument + * @throws \MySQLException + * @throws \MySQLHasGoneAwayException + * @throws \OQLException + */ public function DisplayModifyForm(WebPage $oPage, $aExtraParams = array()) { $sOwnershipToken = null; $iKey = $this->GetKey(); $sClass = get_class($this); - if ($iKey > 0) + $sMode = ($iKey > 0) ? static::ENUM_OBJECT_MODE_EDIT : static::ENUM_OBJECT_MODE_CREATE; + + if ($sMode === static::ENUM_OBJECT_MODE_EDIT) { // The concurrent access lock makes sense only for already existing objects $LockEnabled = MetaModel::GetConfig()->Get('concurrent_lock_enabled'); @@ -2442,13 +2486,22 @@ EOF if (isset($aExtraParams['wizard_container']) && $aExtraParams['wizard_container']) { $sClassLabel = MetaModel::GetName($sClass); + $sHeaderTitle = Dict::Format('UI:ModificationTitle_Class_Object', $sClassLabel, + $this->GetName()); + $oPage->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $this->GetRawName(), $sClassLabel)); // Set title will take care of the encoding - $oPage->add("
\n"); - $oPage->add("

".$this->GetIcon()." ".Dict::Format('UI:ModificationTitle_Class_Object', $sClassLabel, - $this->GetName())."

\n"); - $oPage->add("
\n"); - $oPage->add("
\n"); + + $oPage->add(<< +
+ + +
+HTML + ); } self::$iGlobalFormId++; $this->aFieldsMap = array(); @@ -2475,7 +2528,7 @@ EOF } else { - if ($iKey > 0) + if ($sMode === static::ENUM_OBJECT_MODE_EDIT) { $sApplyButton = Dict::S('UI:Button:Apply'); } @@ -2491,7 +2544,7 @@ EOF } else { - if ($iKey > 0) + if ($sMode === static::ENUM_OBJECT_MODE_EDIT) { $sOperation = 'apply_modify'; } @@ -2500,7 +2553,7 @@ EOF $sOperation = 'apply_new'; } } - if ($iKey > 0) + if ($sMode === static::ENUM_OBJECT_MODE_EDIT) { // The object already exists in the database, it's a modification $sButtons = "\n"; @@ -2597,7 +2650,7 @@ EOF { $aFieldsMap = array(); } - if ($iKey > 0) + if ($sMode === static::ENUM_OBJECT_MODE_EDIT) { $aFieldsMap['id'] = $sPrefix.'_id'; } @@ -2638,7 +2691,12 @@ EOF if (isset($aExtraParams['wizard_container']) && $aExtraParams['wizard_container']) { - $oPage->add("
\n"); + // Close wizContainer and object-details + $oPage->add(<< +
+HTML + ); } $iFieldsCount = count($aFieldsMap); @@ -2689,6 +2747,20 @@ EOF } } + /** + * @param \WebPage $oPage + * @param string $sClass + * @param null $oObjectToClone + * @param array $aArgs + * @param array $aExtraParams + * + * @return mixed + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \MissingQueryArgument + * @throws \MySQLException + * @throws \MySQLHasGoneAwayException + */ public static function DisplayCreationForm(WebPage $oPage, $sClass, $oObjectToClone = null, $aArgs = array(), $aExtraParams = array()) { $sClass = ($oObjectToClone == null) ? $sClass : get_class($oObjectToClone); @@ -2773,6 +2845,8 @@ EOF { $sClass = get_class($this); $iKey = $this->GetKey(); + $sMode = static::ENUM_OBJECT_MODE_STIMULUS; + $aTransitions = $this->EnumTransitions(); $aStimuli = MetaModel::EnumStimuli($sClass); if (!isset($aTransitions[$sStimulus])) @@ -2781,6 +2855,7 @@ EOF throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $this->GetName(), $this->GetStateLabel())); } + // Check for concurrent access lock $LockEnabled = MetaModel::GetConfig()->Get('concurrent_lock_enabled'); $sOwnershipToken = null; @@ -2803,12 +2878,22 @@ EOF } $sActionLabel = $aStimuli[$sStimulus]->GetLabel(); $sActionDetails = $aStimuli[$sStimulus]->GetDescription(); - $oPage->add("
\n"); - $oPage->add("

$sActionLabel - {$this->GetName()}

\n"); - $oPage->set_title($sActionLabel); - $oPage->add("
\n"); - $oPage->add("

$sActionDetails

\n"); + + // Get info on current state + $sCurrentState = $this->GetState(); $sTargetState = $aTransitions[$sStimulus]['target_state']; + + $oPage->set_title($sActionLabel); + $oPage->add(<< +
+ +

$sActionDetails

+HTML + ); + $aExpectedAttributes = $this->GetTransitionAttributes($sStimulus /*, current state*/); if ($aPrefillFormParam != null) { @@ -2923,7 +3008,11 @@ EOF $oPage->add("    \n"); $oPage->add("\n"); $oPage->add("\n"); - $oPage->add("
\n"); + $oPage->add(<< +
+HTML + ); if ($sButtonsPosition != 'top') { // bottom or both: Displays the ticket details AFTER the actions @@ -3081,20 +3170,7 @@ EOF 'label' => ''.MetaModel::GetLabel($sClass, $sAttCode).'', 'value' => $sDisplayValue, - 'attcode' => $sAttCode, ); - - // Checking how the field should be rendered - // Note: For edit mode, this is done in self::GetBareProperties() - // Note 2: Shouldn't this be a AttDef property instead of an array to maintain? - if (in_array($oAttDef->GetEditClass(), array('Text', 'HTML', 'CaseLog', 'CustomFields', 'OQLExpression'))) - { - $retVal['layout'] = 'large'; - } - else - { - $retVal['layout'] = 'small'; - } } return $retVal; @@ -4994,4 +5070,40 @@ EOF EOF ); } + + /** + * Return an array of AttributeDefinition EditClass that should be rendered as large field in the UI + * + * @return array + * @since 2.7.0 + */ + protected static function GetAttEditClassesToRenderAsLargeField(){ + return array( + 'CaseLog', + 'CustomFields', + 'HTML', + 'OQLExpression', + 'Text', + ); + } + + /** + * Return an array of AttributeDefinition classes that should be excluded from the markup metadata when priting raw value (typically large values) + * This markup is mostly aimed at CSS/JS hooks for extensions and Behat tests + * + * @return array + * @since 2.7.0 + */ + protected static function GetAttDefClassesToExcludeFromMarkupMetadataRawValue(){ + return array( + 'AttributeBlob', + 'AttributeCustomFields', + 'AttributeDashboard', + 'AttributeLinkedSet', + 'AttributeStopWatch', + 'AttributeSubItem', + 'AttributeTable', + 'AttributeText' + ); + } } diff --git a/application/itopwebpage.class.inc.php b/application/itopwebpage.class.inc.php index 628291d147..c4a39a4a84 100644 --- a/application/itopwebpage.class.inc.php +++ b/application/itopwebpage.class.inc.php @@ -1130,7 +1130,7 @@ EOF { $sBodyClass = 'printable-version'; } - $sHtml .= "\n"; + $sHtml .= "\n"; if ($this->IsPrintableVersion()) { $sHtml .= "
"; diff --git a/application/menunode.class.inc.php b/application/menunode.class.inc.php index 0c13142211..efeacf87fe 100644 --- a/application/menunode.class.inc.php +++ b/application/menunode.class.inc.php @@ -1,27 +1,20 @@ - - /** - * Construction and display of the application's main menu + * Copyright (C) 2013-2019 Combodo SARL * - * @copyright Copyright (C) 2010-2016 Combodo SARL - * @license http://opensource.org/licenses/AGPL-3.0 + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License */ require_once(APPROOT.'/application/utils.inc.php'); @@ -217,7 +210,7 @@ class ApplicationMenu { if (!self::CanDisplayMenu($aMenu)) { continue; } $oMenuNode = self::GetMenuNode($aMenu['index']); - $oPage->AddToMenu('

'.$oMenuNode->GetTitle().'

'); + $oPage->AddToMenu(''); $oPage->AddToMenu('
'); $oPage->AddToMenu('
    '); $aChildren = self::GetChildren($aMenu['index']); @@ -289,9 +282,13 @@ EOF if ($oMenu->IsEnabled()) { $aChildren = self::GetChildren($index); - $sCSSClass = (count($aChildren) > 0) ? ' class="submenu"' : ''; + $aCSSClasses = array('navigation-menu-item'); + if (count($aChildren) > 0) + { + $aCSSClasses[] = 'submenu'; + } $sHyperlink = $oMenu->GetHyperlink($aExtraParams); - $sItemHtml = '
  • '; + $sItemHtml = '
  • '; if ($sHyperlink != '') { $sLinkTarget = ''; diff --git a/application/webpage.class.inc.php b/application/webpage.class.inc.php index a2730b227c..82f7a2455c 100644 --- a/application/webpage.class.inc.php +++ b/application/webpage.class.inc.php @@ -504,12 +504,15 @@ class WebPage implements Page */ public function GetDetails($aFields) { - $sHtml = "
    \n"; + $sHtml = "
    \n"; foreach ($aFields as $aAttrib) { - $sDataAttCode = isset($aAttrib['attcode']) ? "data-attcode=\"{$aAttrib['attcode']}\"" : ''; $sLayout = isset($aAttrib['layout']) ? $aAttrib['layout'] : 'small'; - $sHtml .= "
    \n"; + $sDataAttributeCode = isset($aAttrib['attcode']) ? 'data-attribute-code="'.$aAttrib['attcode'].'"' : ''; + $sDataAttributeType = isset($aAttrib['atttype']) ? 'data-attribute-type="'.$aAttrib['atttype'].'"' : ''; + $sDataValueRaw = isset($aAttrib['value_raw']) ? 'data-value-raw="'.$aAttrib['value_raw'].'"' : ''; + + $sHtml .= "
    \n"; $sHtml .= "
    {$aAttrib['label']}
    \n"; $sHtml .= "
    \n"; @@ -943,8 +946,9 @@ class WebPage implements Page $sHtml = ''; if (!$this->IsPrintableVersion()) { - foreach ($aActions as $aAction) + foreach ($aActions as $sActionId => $aAction) { + $sDataActionId = 'data-action-id="'.$sActionId.'"'; $sClass = isset($aAction['css_classes']) ? 'class="'.implode(' ', $aAction['css_classes']).'"' : ''; $sOnClick = isset($aAction['onclick']) ? 'onclick="'.htmlspecialchars($aAction['onclick'], ENT_QUOTES, "UTF-8").'"' : ''; @@ -953,21 +957,21 @@ class WebPage implements Page { if ($sPrevUrl != '') // Don't output consecutively two separators... { - $sHtml .= "
  • {$aAction['label']}
  • "; + $sHtml .= "
  • {$aAction['label']}
  • "; } $sPrevUrl = ''; } else { - $sHtml .= "
  • {$aAction['label']}
  • "; + $sHtml .= "
  • {$aAction['label']}
  • "; $sPrevUrl = $aAction['url']; } } $sHtml .= "
"; - foreach (array_reverse($aFavoriteActions) as $aAction) + foreach (array_reverse($aFavoriteActions) as $sActionId => $aAction) { $sTarget = isset($aAction['target']) ? " target=\"{$aAction['target']}\"" : ""; - $sHtml .= ""; + $sHtml .= ""; } } diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 9e6017e77b..c1460feaa8 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -1022,6 +1022,14 @@ abstract class AttributeDefinition $oFormField->AddValidator(new \Combodo\iTop\Form\Validator\Validator($this->GetValidationPattern())); } + // Metadata + $oFormField->AddMetadata('attribute-code', $this->GetCode()); + $oFormField->AddMetadata('attribute-type', get_class($this)); + if($this::IsScalar()) + { + $oFormField->AddMetadata('value-raw', $oObject->Get($this->GetCode())); + } + return $oFormField; } diff --git a/datamodels/2.x/itop-portal-base/portal/templates/layout.html.twig b/datamodels/2.x/itop-portal-base/portal/templates/layout.html.twig index d6d768a1ab..ee92e23756 100644 --- a/datamodels/2.x/itop-portal-base/portal/templates/layout.html.twig +++ b/datamodels/2.x/itop-portal-base/portal/templates/layout.html.twig @@ -158,7 +158,7 @@ {% endblock %} - + {% block pPageBodyWrapper %} {% block pEnvBannerWrapper %} {% if app['combodo.current_environment'] != 'production' %} diff --git a/js/field_set.js b/js/field_set.js index cbc436aa69..dcad9a573b 100644 --- a/js/field_set.js +++ b/js/field_set.js @@ -276,6 +276,14 @@ $(function() { oFieldContainer.html(oField.html); } + // HTML metadata + if( (oField.html_metadata !== undefined) && (Object.keys(oField.html_metadata).length > 0) ) + { + for(var i in oField.html_metadata) + { + oFieldContainer.attr('data-' + i, oField.html_metadata[i]); + } + } // JS files if( (oField.js_files !== undefined) && (oField.js_files.length > 0) ) { diff --git a/sources/autoload.php b/sources/autoload.php index 612f727c53..518eb985ca 100644 --- a/sources/autoload.php +++ b/sources/autoload.php @@ -1,21 +1,22 @@ +/** + * Copyright (C) 2013-2019 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ /** * This is a "manual autoloader" for now that is meant to evolve into a real autoloader. @@ -56,6 +57,7 @@ require_once APPROOT . 'sources/renderer/formrenderer.class.inc.php'; require_once APPROOT . 'sources/renderer/fieldrenderer.class.inc.php'; require_once APPROOT . 'sources/renderer/renderingoutput.class.inc.php'; require_once APPROOT . 'sources/renderer/bootstrap/bsformrenderer.class.inc.php'; +require_once APPROOT . 'sources/renderer/bootstrap/fieldrenderer/bsfieldrenderer.class.inc.php'; require_once APPROOT . 'sources/renderer/bootstrap/fieldrenderer/bssimplefieldrenderer.class.inc.php'; require_once APPROOT . 'sources/renderer/bootstrap/fieldrenderer/bsselectobjectfieldrenderer.class.inc.php'; require_once APPROOT . 'sources/renderer/bootstrap/fieldrenderer/bssetfieldrenderer.class.inc.php'; diff --git a/sources/form/field/field.class.inc.php b/sources/form/field/field.class.inc.php index 5eea0240cd..9bae98e1f8 100644 --- a/sources/form/field/field.class.inc.php +++ b/sources/form/field/field.class.inc.php @@ -1,21 +1,22 @@ +/** + * Copyright (C) 2013-2019 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ namespace Combodo\iTop\Form\Field; @@ -36,6 +37,7 @@ abstract class Field const ENUM_DISPLAY_MODE_DENSE = 'dense'; // Label and value side by side, closely const DEFAULT_LABEL = ''; + const DEFAULT_METADATA = array(); const DEFAULT_HIDDEN = false; const DEFAULT_READ_ONLY = false; const DEFAULT_MANDATORY = false; @@ -46,6 +48,7 @@ abstract class Field protected $sGlobalId; protected $sFormPath; protected $sLabel; + protected $aMetadata; protected $bHidden; protected $bReadOnly; protected $bMandatory; @@ -68,6 +71,7 @@ abstract class Field // No space in such an id, that could be used as a DOM node id $this->sGlobalId = 'field_' . str_replace(' ', '_', $sId) . '_' . uniqid(); $this->sLabel = static::DEFAULT_LABEL; + $this->aMetadata = static::DEFAULT_METADATA; $this->bHidden = static::DEFAULT_HIDDEN; $this->bReadOnly = static::DEFAULT_READ_ONLY; $this->bMandatory = static::DEFAULT_MANDATORY; @@ -117,6 +121,17 @@ abstract class Field return $this->sLabel; } + /** + * Return an array of $sName => $sValue metadata. + * + * @return array + * @since 2.7.0 + */ + public function GetMetadata() + { + return $this->aMetadata; + } + /** * * @return boolean @@ -233,6 +248,20 @@ abstract class Field return $this; } + /** + * Must be an array of $sName => $sValue metadata. + * + * @param array $aMetadata + * + * @return $this + * @since 2.7.0 + */ + public function SetMetadata($aMetadata) + { + $this->aMetadata = $aMetadata; + return $this; + } + /** * * @param boolean $bHidden @@ -367,6 +396,21 @@ abstract class Field return $this; } + /** + * Add a metadata to the field. If the metadata $sName already exists, it will be overwritten. + * + * @param string $sName + * @param string $sValue + * + * @return $this; + * @since 2.7.0 + */ + public function AddMetadata($sName, $sValue) + { + $this->aMetadata[$sName] = $sValue; + return $this; + } + /** * * @param \Combodo\iTop\Form\Validator\Validator $oValidator diff --git a/sources/renderer/bootstrap/fieldrenderer/bsfieldrenderer.class.inc.php b/sources/renderer/bootstrap/fieldrenderer/bsfieldrenderer.class.inc.php new file mode 100644 index 0000000000..71c2fa574c --- /dev/null +++ b/sources/renderer/bootstrap/fieldrenderer/bsfieldrenderer.class.inc.php @@ -0,0 +1,46 @@ + + * @since 2.7.0 + */ +class BsFieldRenderer extends FieldRenderer +{ + + /** + * @inheritDoc + */ + public function Render() + { + $oOutput = parent::Render(); + $oOutput->AddCssClass('form_field_'.$this->oField->GetDisplayMode()); + + return $oOutput; + } +} diff --git a/sources/renderer/bootstrap/fieldrenderer/bsfileuploadfieldrenderer.class.inc.php b/sources/renderer/bootstrap/fieldrenderer/bsfileuploadfieldrenderer.class.inc.php index 423f5b94ac..5bc617d5c5 100644 --- a/sources/renderer/bootstrap/fieldrenderer/bsfileuploadfieldrenderer.class.inc.php +++ b/sources/renderer/bootstrap/fieldrenderer/bsfileuploadfieldrenderer.class.inc.php @@ -1,52 +1,46 @@ +/** + * Copyright (C) 2013-2019 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ namespace Combodo\iTop\Renderer\Bootstrap\FieldRenderer; -use utils; +use AttachmentPlugIn; +use Combodo\iTop\Renderer\RenderingOutput; +use DBObjectSearch; +use DBObjectSet; use Dict; use InlineImage; -use DBObjectSet; -use DBObjectSearch; -use AttachmentPlugIn; -use Combodo\iTop\Renderer\FieldRenderer; -use Combodo\iTop\Renderer\RenderingOutput; +use utils; /** * Description of BsFileUploadFieldRenderer * * @author Guillaume Lajarige */ -class BsFileUploadFieldRenderer extends FieldRenderer +class BsFileUploadFieldRenderer extends BsFieldRenderer { /** - * Returns a RenderingOutput for the FieldRenderer's Field - * - * @return \Combodo\iTop\Renderer\RenderingOutput - * - * @throws \CoreException - * @throws \OQLException + * @inheritDoc */ public function Render() { - $oOutput = new RenderingOutput(); - $oOutput->AddCssClass('form_field_' . $this->oField->GetDisplayMode()); + $oOutput = parent::Render(); $sObjectClass = get_class($this->oField->GetObject()); $sIsDeleteAllowed = ($this->oField->GetAllowDelete() && !$this->oField->GetReadOnly()) ? 'true' : 'false'; diff --git a/sources/renderer/bootstrap/fieldrenderer/bslinkedsetfieldrenderer.class.inc.php b/sources/renderer/bootstrap/fieldrenderer/bslinkedsetfieldrenderer.class.inc.php index e701cd1938..54b469c9f7 100644 --- a/sources/renderer/bootstrap/fieldrenderer/bslinkedsetfieldrenderer.class.inc.php +++ b/sources/renderer/bootstrap/fieldrenderer/bslinkedsetfieldrenderer.class.inc.php @@ -22,8 +22,6 @@ namespace Combodo\iTop\Renderer\Bootstrap\FieldRenderer; use ApplicationContext; use AttributeFriendlyName; -use Combodo\iTop\Renderer\FieldRenderer; -use Combodo\iTop\Renderer\RenderingOutput; use Dict; use Exception; use IssueLog; @@ -37,19 +35,14 @@ use MetaModel; * @property \Combodo\iTop\Form\Field\LinkedSetField $oField * */ -class BsLinkedSetFieldRenderer extends FieldRenderer +class BsLinkedSetFieldRenderer extends BsFieldRenderer { /** - * Returns a RenderingOutput for the FieldRenderer's Field - * - * @return \Combodo\iTop\Renderer\RenderingOutput - * - * @throws \CoreException + * @inheritDoc */ public function Render() { - $oOutput = new RenderingOutput(); - $oOutput->AddCssClass('form_field_' . $this->oField->GetDisplayMode()); + $oOutput = parent::Render(); $sFieldMandatoryClass = ($this->oField->GetMandatory()) ? 'form_mandatory' : ''; // Vars to build the table diff --git a/sources/renderer/bootstrap/fieldrenderer/bsselectobjectfieldrenderer.class.inc.php b/sources/renderer/bootstrap/fieldrenderer/bsselectobjectfieldrenderer.class.inc.php index 2cb692500a..2263e1340e 100644 --- a/sources/renderer/bootstrap/fieldrenderer/bsselectobjectfieldrenderer.class.inc.php +++ b/sources/renderer/bootstrap/fieldrenderer/bsselectobjectfieldrenderer.class.inc.php @@ -21,7 +21,6 @@ namespace Combodo\iTop\Renderer\Bootstrap\FieldRenderer; use ApplicationContext; -use Combodo\iTop\Renderer\FieldRenderer; use Combodo\iTop\Renderer\RenderingOutput; use ContextTag; use CoreException; @@ -38,22 +37,15 @@ use MetaModel; * * @property \Combodo\iTop\Form\Field\SelectObjectField $oField */ -class BsSelectObjectFieldRenderer extends FieldRenderer +class BsSelectObjectFieldRenderer extends BsFieldRenderer { /** - * Returns a RenderingOutput for the FieldRenderer's Field - * - * @return \Combodo\iTop\Renderer\RenderingOutput - * - * @throws \Exception - * @throws \CoreException - * @throws \ArchivedObjectException + * @inheritDoc */ public function Render() { - $oOutput = new RenderingOutput(); - $oOutput->AddCssClass('form_field_' . $this->oField->GetDisplayMode()); + $oOutput = parent::Render(); $sFieldValueClass = $this->oField->GetSearch()->GetClass(); $sFieldMandatoryClass = ($this->oField->GetMandatory()) ? 'form_mandatory' : ''; diff --git a/sources/renderer/bootstrap/fieldrenderer/bssetfieldrenderer.class.inc.php b/sources/renderer/bootstrap/fieldrenderer/bssetfieldrenderer.class.inc.php index 2a68a5a101..59d6269dbe 100644 --- a/sources/renderer/bootstrap/fieldrenderer/bssetfieldrenderer.class.inc.php +++ b/sources/renderer/bootstrap/fieldrenderer/bssetfieldrenderer.class.inc.php @@ -1,42 +1,40 @@ +/** + * Copyright (C) 2013-2019 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ namespace Combodo\iTop\Renderer\Bootstrap\FieldRenderer; use MetaModel; -use Combodo\iTop\Renderer\FieldRenderer; -use Combodo\iTop\Renderer\RenderingOutput; /** * Description of BsSetFieldRenderer * * @author Guillaume Lajarige */ -class BsSetFieldRenderer extends FieldRenderer +class BsSetFieldRenderer extends BsFieldRenderer { /** * @inheritdoc */ public function Render() { - $oOutput = new RenderingOutput(); - $oOutput->AddCssClass('form_field_' . $this->oField->GetDisplayMode()); + $oOutput = parent::Render(); $sFieldMandatoryClass = ($this->oField->GetMandatory()) ? 'form_mandatory' : ''; // Vars to build the table diff --git a/sources/renderer/bootstrap/fieldrenderer/bssimplefieldrenderer.class.inc.php b/sources/renderer/bootstrap/fieldrenderer/bssimplefieldrenderer.class.inc.php index d9b4657493..cda101550b 100644 --- a/sources/renderer/bootstrap/fieldrenderer/bssimplefieldrenderer.class.inc.php +++ b/sources/renderer/bootstrap/fieldrenderer/bssimplefieldrenderer.class.inc.php @@ -1,21 +1,22 @@ +/** + * Copyright (C) 2013-2019 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ namespace Combodo\iTop\Renderer\Bootstrap\FieldRenderer; @@ -25,7 +26,6 @@ use UserRights; use AttributeDateTime; use AttributeText; use InlineImage; -use Combodo\iTop\Renderer\FieldRenderer; use Combodo\iTop\Renderer\RenderingOutput; use Combodo\iTop\Form\Field\TextAreaField; use Combodo\iTop\Form\Field\MultipleChoicesField; @@ -35,20 +35,15 @@ use Combodo\iTop\Form\Field\MultipleChoicesField; * * @author Guillaume Lajarige */ -class BsSimpleFieldRenderer extends FieldRenderer +class BsSimpleFieldRenderer extends BsFieldRenderer { /** - * Returns a RenderingOutput for the FieldRenderer's Field - * - * @return \Combodo\iTop\Renderer\RenderingOutput - * - * @throws \Exception + * @inheritDoc */ public function Render() { - $oOutput = new RenderingOutput(); - $oOutput->AddCssClass('form_field_' . $this->oField->GetDisplayMode()); + $oOutput = parent::Render(); $sFieldClass = get_class($this->oField); $sFieldMandatoryClass = ($this->oField->GetMandatory()) ? 'form_mandatory' : ''; diff --git a/sources/renderer/bootstrap/fieldrenderer/bssubformfieldrenderer.class.inc.php b/sources/renderer/bootstrap/fieldrenderer/bssubformfieldrenderer.class.inc.php index 7dcdf5b318..556d3970df 100644 --- a/sources/renderer/bootstrap/fieldrenderer/bssubformfieldrenderer.class.inc.php +++ b/sources/renderer/bootstrap/fieldrenderer/bssubformfieldrenderer.class.inc.php @@ -1,33 +1,36 @@ +/** + * Copyright (C) 2013-2019 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ namespace Combodo\iTop\Renderer\Bootstrap\FieldRenderer; use Combodo\iTop\Renderer\Bootstrap\BsFormRenderer; -use Combodo\iTop\Renderer\FieldRenderer; use Combodo\iTop\Renderer\RenderingOutput; -class BsSubFormFieldRenderer extends FieldRenderer +/** + * Class BsSubFormFieldRenderer + * + * @author Guillaume Lajarige + */ +class BsSubFormFieldRenderer extends BsFieldRenderer { /** - * @return \Combodo\iTop\Renderer\RenderingOutput - * - * @throws \Exception + * @inheritDoc */ public function Render() { diff --git a/sources/renderer/console/fieldrenderer/consoleselectobjectfieldrenderer.class.inc.php b/sources/renderer/console/fieldrenderer/consoleselectobjectfieldrenderer.class.inc.php index e1ca29ca3d..3012832e69 100644 --- a/sources/renderer/console/fieldrenderer/consoleselectobjectfieldrenderer.class.inc.php +++ b/sources/renderer/console/fieldrenderer/consoleselectobjectfieldrenderer.class.inc.php @@ -1,20 +1,21 @@ +/** + * Copyright (C) 2013-2019 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ namespace Combodo\iTop\Renderer\Console\FieldRenderer; @@ -22,25 +23,21 @@ use Combodo\iTop\Form\Validator\MandatoryValidator; use \Dict; use \DBObjectSet; use Combodo\iTop\Renderer\FieldRenderer; -use Combodo\iTop\Renderer\RenderingOutput; use Combodo\iTop\Form\Field\SelectObjectField; - +/** + * Class ConsoleSelectObjectFieldRenderer + * + * @author Romain Quetiez + */ class ConsoleSelectObjectFieldRenderer extends FieldRenderer { /** - * @return RenderingOutput - * - * @throws \Exception - * @throws \CoreException - * @throws \CoreUnexpectedValue - * @throws \MissingQueryArgument - * @throws \MySQLException - * @throws \MySQLHasGoneAwayException + * @inheritDoc */ public function Render() { - $oOutput = new RenderingOutput(); + $oOutput = parent::Render(); $oOutput->AddHtml(''); $oOutput->AddHtml(''); diff --git a/sources/renderer/console/fieldrenderer/consolesimplefieldrenderer.class.inc.php b/sources/renderer/console/fieldrenderer/consolesimplefieldrenderer.class.inc.php index 52a4d9ce7e..3478fd4399 100644 --- a/sources/renderer/console/fieldrenderer/consolesimplefieldrenderer.class.inc.php +++ b/sources/renderer/console/fieldrenderer/consolesimplefieldrenderer.class.inc.php @@ -1,20 +1,21 @@ +/** + * Copyright (C) 2013-2019 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ namespace Combodo\iTop\Renderer\Console\FieldRenderer; @@ -28,13 +29,17 @@ use UserRights; use utils; use Combodo\iTop\Form\Field\TextAreaField; use Combodo\iTop\Renderer\FieldRenderer; -use Combodo\iTop\Renderer\RenderingOutput; +/** + * Class ConsoleSimpleFieldRenderer + * + * @author Romain Quetiez + */ class ConsoleSimpleFieldRenderer extends FieldRenderer { public function Render() { - $oOutput = new RenderingOutput(); + $oOutput = parent::Render(); $sFieldClass = get_class($this->oField); if ($sFieldClass == 'Combodo\\iTop\\Form\\Field\\HiddenField') diff --git a/sources/renderer/console/fieldrenderer/consolesubformfieldrenderer.class.inc.php b/sources/renderer/console/fieldrenderer/consolesubformfieldrenderer.class.inc.php index 53753d3715..76abe4b594 100644 --- a/sources/renderer/console/fieldrenderer/consolesubformfieldrenderer.class.inc.php +++ b/sources/renderer/console/fieldrenderer/consolesubformfieldrenderer.class.inc.php @@ -1,37 +1,41 @@ +/** + * Copyright (C) 2013-2019 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ namespace Combodo\iTop\Renderer\Console\FieldRenderer; use Combodo\iTop\Renderer\Console\ConsoleFormRenderer; use Combodo\iTop\Renderer\FieldRenderer; -use Combodo\iTop\Renderer\RenderingOutput; +/** + * Class ConsoleSubFormFieldRenderer + * + * @author Romain Quetiez + */ class ConsoleSubFormFieldRenderer extends FieldRenderer { - /** - * @return RenderingOutput - * - * @throws \Exception - */ + /** + * @inheritDoc + * @throws \Exception + */ public function Render() { - $oOutput = new RenderingOutput(); + $oOutput = parent::Render(); $oOutput->AddHtml('
'); $oOutput->AddHtml('
'); diff --git a/sources/renderer/fieldrenderer.class.inc.php b/sources/renderer/fieldrenderer.class.inc.php index 6655004fb5..159aae4e00 100644 --- a/sources/renderer/fieldrenderer.class.inc.php +++ b/sources/renderer/fieldrenderer.class.inc.php @@ -1,26 +1,28 @@ +/** + * Copyright (C) 2013-2019 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ namespace Combodo\iTop\Renderer; use Combodo\iTop\Form\Field\Field; use Dict; +use utils; /** * Description of FieldRenderer @@ -96,5 +98,16 @@ abstract class FieldRenderer * * @return \Combodo\iTop\Renderer\RenderingOutput */ - abstract public function Render(); + public function Render() + { + $oOutput = new RenderingOutput(); + + // Field metadata + foreach ($this->oField->GetMetadata() as $sMetadataName => $sMetadataValue) + { + $oOutput->AddMetadata($sMetadataName, utils::HtmlEntities($sMetadataValue)); + } + + return $oOutput; + } } diff --git a/sources/renderer/formrenderer.class.inc.php b/sources/renderer/formrenderer.class.inc.php index e63345bf87..d4ecde37c9 100644 --- a/sources/renderer/formrenderer.class.inc.php +++ b/sources/renderer/formrenderer.class.inc.php @@ -1,21 +1,22 @@ +/** + * Copyright (C) 2013-2019 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ namespace Combodo\iTop\Renderer; @@ -233,6 +234,7 @@ abstract class FormRenderer $output = array( 'id' => $oField->GetId(), 'html' => '', + 'html_metadata' => array(), 'js_inline' => '', 'css_inline' => '', 'js_files' => array(), @@ -260,6 +262,18 @@ abstract class FormRenderer $output['html'] .= $oRenderingOutput->GetHtml(); } } + // HTML metadata + foreach ($oRenderingOutput->GetMetadata() as $sMetadataName => $sMetadataValue) + { + // Warning: Do not work with ENUM_RENDER_MODE_JOINED mode + if ($sMode === static::ENUM_RENDER_MODE_EXPLODED) + { + if (!in_array($sMetadataName, $output['html_metadata'])) + { + $output['html_metadata'][$sMetadataName] = $sMetadataValue; + } + } + } // JS files foreach ($oRenderingOutput->GetJsFiles() as $sJsFile) diff --git a/sources/renderer/renderingoutput.class.inc.php b/sources/renderer/renderingoutput.class.inc.php index d777686d50..44ffa13d41 100644 --- a/sources/renderer/renderingoutput.class.inc.php +++ b/sources/renderer/renderingoutput.class.inc.php @@ -1,21 +1,22 @@ +/** + * Copyright (C) 2013-2019 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ namespace Combodo\iTop\Renderer; @@ -27,6 +28,7 @@ namespace Combodo\iTop\Renderer; class RenderingOutput { protected $sHtml; + protected $aMetadata; protected $sJsInline; protected $aJsFiles; protected $sCssInline; @@ -36,6 +38,7 @@ class RenderingOutput public function __construct() { $this->sHtml = ''; + $this->aMetadata = array(); $this->sJsInline = ''; $this->aJsFiles = array(); $this->sCssInline = ''; @@ -52,6 +55,15 @@ class RenderingOutput return $this->sHtml; } + /** + * @return array + * @since 2.7.0 + */ + public function GetMetadata() + { + return $this->aMetadata; + } + /** * * @return string @@ -110,6 +122,38 @@ class RenderingOutput return $this; } + /** + * Add a metadata identified by $sName. + * + * @param string $sName + * @param string $sValue + * + * @return $this + * @since 2.7.0 + */ + public function AddMetadata($sName, $sValue) + { + $this->aMetadata[$sName] = $sValue; + return $this; + } + + /** + * Remove the metadata identified by $sName + * + * @param string $sName + * + * @return $this + * @since 2.7.0 + */ + public function RemoveMetadata($sName) + { + if (in_array($sName, $this->aMetadata)) + { + unset($this->aJsFiles[$sName]); + } + return $this; + } + /** * * @param string $sJs