diff --git a/application/itopwebpage.class.inc.php b/application/itopwebpage.class.inc.php
index 9c13d3742..bc24b877f 100644
--- a/application/itopwebpage.class.inc.php
+++ b/application/itopwebpage.class.inc.php
@@ -51,7 +51,7 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
{
parent::__construct($sTitle, $bPrintable);
$this->m_oTabs = new TabManager();
- $this->oCtx = new ContextTag('GUI:Console');
+ $this->oCtx = new ContextTag(ContextTag::TAG_CONSOLE);
ApplicationContext::SetUrlMakerClass('iTopStandardURLMaker');
diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php
index fabf1d13d..200f349c9 100644
--- a/core/attributedef.class.inc.php
+++ b/core/attributedef.class.inc.php
@@ -17,6 +17,10 @@
* You should have received a copy of the GNU Affero General Public License
*/
+use Combodo\iTop\Form\Field\LabelField;
+use Combodo\iTop\Form\Validator\NotEmptyExtKeyValidator;
+use Combodo\iTop\Form\Validator\Validator;
+
require_once('MyHelpers.class.inc.php');
require_once('ormdocument.class.inc.php');
require_once('ormstopwatch.class.inc.php');
@@ -1022,7 +1026,7 @@ abstract class AttributeDefinition
// Validation pattern
if ($this->GetValidationPattern() !== '')
{
- $oFormField->AddValidator(new \Combodo\iTop\Form\Validator\Validator($this->GetValidationPattern()));
+ $oFormField->AddValidator(new Validator($this->GetValidationPattern()));
}
// Metadata
@@ -6730,7 +6734,7 @@ class AttributeExternalKey extends AttributeDBFieldVoid
// If ExtKey is mandatory, we add a validator to ensure that the value 0 is not selected
if ($oObject->GetAttributeFlags($this->GetCode()) & OPT_ATT_MANDATORY)
{
- $oFormField->AddValidator(new \Combodo\iTop\Form\Validator\NotEmptyExtKeyValidator());
+ $oFormField->AddValidator(new NotEmptyExtKeyValidator());
}
parent::MakeFormField($oObject, $oFormField);
@@ -9812,10 +9816,19 @@ abstract class AttributeSet extends AttributeDBFieldVoid
$aValues = array();
if (!empty($proposedValue))
{
- foreach(explode(',', $proposedValue) as $sCode)
+ $sSepItem = MetaModel::GetConfig()->Get('tag_set_item_separator');
+ // convert also , separated strings
+ if ($sSepItem !== ',')
+ {
+ $proposedValue = str_replace(',', $sSepItem, $proposedValue);
+ }
+ foreach(explode($sSepItem, $proposedValue) as $sCode)
{
$sValue = trim($sCode);
- $aValues[] = $sValue;
+ if ($sValue !== '')
+ {
+ $aValues[] = $sValue;
+ }
}
}
return $aValues;
@@ -9835,20 +9848,6 @@ abstract class AttributeSet extends AttributeDBFieldVoid
return $this->MakeRealValue($sValue, null, true);
}
- /**
- * @param $aCols
- * @param string $sPrefix
- *
- * @return mixed
- * @throws \Exception
- */
- public function FromImportToValue($aCols, $sPrefix = '')
- {
- $sValue = $aCols["$sPrefix"];
-
- return $this->MakeRealValue($sValue, null);
- }
-
/**
* force an allowed value (type conversion and possibly forces a value as mySQL would do upon writing!
*
@@ -9951,7 +9950,7 @@ abstract class AttributeSet extends AttributeDBFieldVoid
}
/**
- * @param $value
+ * @param string $value
*
* @return string
*/
@@ -9967,7 +9966,16 @@ abstract class AttributeSet extends AttributeDBFieldVoid
}
if (is_array($value))
{
- return implode(', ', $value);
+ $sSepItem = MetaModel::GetConfig()->Get('tag_set_item_separator');
+ $sRes = implode($sSepItem, $value);
+ if (!empty($sRes))
+ {
+ $value = "{$sSepItem}{$sRes}{$sSepItem}";
+ }
+ else
+ {
+ $value = '';
+ }
}
return $value;
}
@@ -9994,6 +10002,43 @@ abstract class AttributeSet extends AttributeDBFieldVoid
return $value;
}
+ /**
+ * @param $value
+ * @param string $sSeparator
+ * @param string $sTextQualifier
+ * @param \DBObject $oHostObject
+ * @param bool $bLocalize
+ * @param bool $bConvertToPlainText
+ *
+ * @return mixed|string
+ */
+ public function GetAsCSV($value, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, $bConvertToPlainText = false)
+ {
+ $sSepItem = MetaModel::GetConfig()->Get('tag_set_item_separator');
+ if (is_object($value) && ($value instanceof ormSet))
+ {
+ if ($bLocalize)
+ {
+ $aValues = $value->GetLabels();
+ }
+ else
+ {
+ $aValues = $value->GetValues();
+ }
+ $sRes = implode($sSepItem, $aValues);
+ if (!empty($sRes))
+ {
+ $sRes = "{$sSepItem}{$sRes}{$sSepItem}";
+ }
+ }
+ else
+ {
+ $sRes = '';
+ }
+
+ return "{$sTextQualifier}{$sRes}{$sTextQualifier}";
+ }
+
public function GetMaxItems()
{
return $this->Get('max_items');
@@ -10005,6 +10050,111 @@ abstract class AttributeSet extends AttributeDBFieldVoid
}
}
+class AttributeEnumSet extends AttributeSet
+{
+ const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_STRING;
+
+ public function GetAllowedValues($aArgs = array(), $sContains = '')
+ {
+ $aRawValues = parent::GetAllowedValues($aArgs, $sContains);
+ if (is_null($aRawValues))
+ {
+ return null;
+ }
+ $aLocalizedValues = array();
+ foreach($aRawValues as $sKey => $sValue)
+ {
+ $aLocalizedValues[$sKey] = $this->GetValueLabel($sKey);
+ }
+
+ return $aLocalizedValues;
+ }
+
+ public function GetValueLabel($sValue)
+ {
+ if (is_null($sValue))
+ {
+ // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label
+ $sLabel = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue,
+ Dict::S('Enum:Undefined'));
+ }
+ else
+ {
+ $sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'/Value:'.$sValue, null, true /*user lang*/);
+ if (is_null($sLabel))
+ {
+ $sDefault = str_replace('_', ' ', $sValue);
+ // Browse the hierarchy again, accepting default (english) translations
+ $sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'/Value:'.$sValue, $sDefault, false);
+ }
+ }
+
+ return $sLabel;
+ }
+
+ public function GetValueDescription($sValue)
+ {
+ if (is_null($sValue))
+ {
+ // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label
+ $sDescription = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue.'+',
+ Dict::S('Enum:Undefined'));
+ }
+ else
+ {
+ $sDescription = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue.'+',
+ '', true /* user language only */);
+ if (strlen($sDescription) == 0)
+ {
+ $sParentClass = MetaModel::GetParentClass($this->m_sHostClass);
+ if ($sParentClass)
+ {
+ if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode))
+ {
+ $oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode);
+ $sDescription = $oAttDef->GetValueDescription($sValue);
+ }
+ }
+ }
+ }
+
+ return $sDescription;
+ }
+
+ public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true)
+ {
+ if ($bLocalize)
+ {
+ if ($sValue instanceof ormSet)
+ {
+ /** @var ormSet $oOrmSet */
+ $oOrmSet = $sValue;
+ $aRes = array();
+ foreach ($oOrmSet->GetValues() as $sValue)
+ {
+ $sLabel = $this->GetValueLabel($sValue);
+ $sDescription = $this->GetValueDescription($sValue);
+ $aRes[] = "".parent::GetAsHtml($sLabel)."";
+ }
+ $sRes = implode(', ', $aRes);
+ }
+ else
+ {
+ $sLabel = $this->GetValueLabel($sValue);
+ $sDescription = $this->GetValueDescription($sValue);
+ $sRes = "".parent::GetAsHtml($sLabel)."";
+ }
+ }
+ else
+ {
+ $sRes = parent::GetAsHtml($sValue, $oHostObject, $bLocalize);
+ }
+
+ return $sRes;
+ }
+
+}
+
class AttributeClassAttCodeSet extends AttributeSet
{
const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_STRING;
@@ -11018,41 +11168,6 @@ class AttributeTagSet extends AttributeSet
return $sRes;
}
- /**
- * @param $value
- * @param string $sSeparator
- * @param string $sTextQualifier
- * @param \DBObject $oHostObject
- * @param bool $bLocalize
- * @param bool $bConvertToPlainText
- *
- * @return mixed|string
- */
- public function GetAsCSV(
- $value, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true,
- $bConvertToPlainText = false
- ) {
- $sSepItem = MetaModel::GetConfig()->Get('tag_set_item_separator');
- if (is_object($value) && ($value instanceof ormTagSet))
- {
- if ($bLocalize)
- {
- $aValues = $value->GetLabels();
- }
- else
- {
- $aValues = $value->GetValues();
- }
- $sRes = implode($sSepItem, $aValues);
- }
- else
- {
- $sRes = '';
- }
-
- return "{$sTextQualifier}{$sRes}{$sTextQualifier}";
- }
-
/**
* List the available verbs for 'GetForTemplate'
*/
@@ -12031,7 +12146,7 @@ class AttributeCustomFields extends AttributeDefinition
} catch (Exception $e)
{
$oForm = new \Combodo\iTop\Form\Form('');
- $oField = new \Combodo\iTop\Form\Field\LabelField('');
+ $oField = new LabelField('');
$oField->SetLabel('Custom field error: '.$e->getMessage());
$oForm->AddField($oField);
$oForm->Finalize();
diff --git a/core/contexttag.class.inc.php b/core/contexttag.class.inc.php
index f32ebdcf1..e3725de13 100644
--- a/core/contexttag.class.inc.php
+++ b/core/contexttag.class.inc.php
@@ -19,14 +19,14 @@
/**
* Simple helper class for keeping track of the context inside the call stack
- *
+ *
* To check (anywhere in the code) if a particular context tag is present
* in the call stack simply do:
- *
+ *
* if (ContextTag::Check()) ...
- *
+ *
* For example to know if the code is being executed in the context of a portal do:
- *
+ *
* if (ContextTag::Check('GUI:Portal'))
*
* @copyright Copyright (C) 2016-2017 Combodo SARL
@@ -35,8 +35,15 @@
class ContextTag
{
+ const TAG_PORTAL = 'GUI:Portal';
+ const TAG_CRON = 'CRON';
+ const TAG_CONSOLE = 'GUI:Console';
+ const TAG_SETUP = 'Setup';
+ const TAG_SYNCHRO = 'Synchro';
+ const TAG_REST = 'REST/JSON';
+
protected static $aStack = array();
-
+
/**
* Store a context tag on the stack
* @param string $sTag
@@ -46,6 +53,11 @@ class ContextTag
static::$aStack[] = $sTag;
}
+ public static function AddContext($sTag)
+ {
+ static::$aStack[] = $sTag;
+ }
+
/**
* Cleanup the context stack
*/
@@ -53,7 +65,7 @@ class ContextTag
{
array_pop(static::$aStack);
}
-
+
/**
* Check if a given tag is present in the stack
* @param string $sTag
@@ -63,13 +75,28 @@ class ContextTag
{
return in_array($sTag, static::$aStack);
}
-
+
/**
* Get the whole stack as an array
- * @return hash
+ * @return array
*/
public static function GetStack()
{
return static::$aStack;
}
-}
\ No newline at end of file
+
+ /**
+ * Get all the predefined context tags
+ * @return array
+ */
+ public static function GetTags()
+ {
+ return array(
+ ContextTag::TAG_REST,
+ ContextTag::TAG_SYNCHRO,
+ ContextTag::TAG_SETUP,
+ ContextTag::TAG_CONSOLE,
+ ContextTag::TAG_CRON,
+ ContextTag::TAG_PORTAL);
+ }
+}
diff --git a/core/dbobject.class.php b/core/dbobject.class.php
index 74389851f..276217563 100644
--- a/core/dbobject.class.php
+++ b/core/dbobject.class.php
@@ -1912,7 +1912,7 @@ abstract class DBObject implements iDisplay
return "Bad type";
}
- elseif ($oAtt instanceof AttributeClassAttCodeSet)
+ elseif (($oAtt instanceof AttributeClassAttCodeSet) || ($oAtt instanceof AttributeEnumSet))
{
if (is_string($toCheck))
{
diff --git a/core/ormset.class.inc.php b/core/ormset.class.inc.php
index 9879d8b49..8ceb884c1 100644
--- a/core/ormset.class.inc.php
+++ b/core/ormset.class.inc.php
@@ -164,6 +164,17 @@ class ormSet
return $aValues;
}
+ public function GetLabels()
+ {
+ $aLabels = array();
+ $aValues = $this->GetValues();
+ foreach ($aValues as $sValue)
+ {
+ $aLabels[$sValue] = $sValue;
+ }
+ return $aLabels;
+ }
+
/**
* @return array of tag labels indexed by code for only the added tags
*/
@@ -377,4 +388,4 @@ class ormSet
}
-}
\ No newline at end of file
+}
diff --git a/core/trigger.class.inc.php b/core/trigger.class.inc.php
index e3c33f824..8240d57ef 100644
--- a/core/trigger.class.inc.php
+++ b/core/trigger.class.inc.php
@@ -56,15 +56,49 @@ abstract class Trigger extends cmdbAbstractObject
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("description", array("allowed_values" => null, "sql" => "description", "default_value" => null, "is_null_allowed" => false, "depends_on" => array())));
MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("action_list", array("linked_class" => "lnkTriggerAction", "ext_key_to_me" => "trigger_id", "ext_key_to_remote" => "action_id", "allowed_values" => null, "count_min" => 1, "count_max" => 0, "depends_on" => array())));
+ $aTags = ContextTag::GetTags();
+ $sTags = implode(',', $aTags);
+ MetaModel::Init_AddAttribute( new AttributeEnumSet("context", array("allowed_values" => new ValueSetEnum($sTags), "sql" => "context", "depends_on" => array(), "is_null_allowed" => true, "max_items" => 12)));
// Display lists
- MetaModel::Init_SetZListItems('details', array('finalclass', 'description', 'action_list')); // Attributes to be displayed for the complete details
+ MetaModel::Init_SetZListItems('details', array('finalclass', 'description', 'context', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass')); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
+ /**
+ * Check if the trigger can be used in the current context
+ *
+ * @return bool true if context OK
+ * @throws \ArchivedObjectException
+ * @throws \CoreException
+ */
+ public function IsContextValid()
+ {
+ // Check the context
+ $oContext = $this->Get('context');
+ $bChecked = false;
+ $bValid = false;
+ foreach ($oContext->GetValues() as $sValue)
+ {
+ $bChecked = true;
+ if (ContextTag::Check($sValue))
+ {
+ $bValid = true;
+ break;
+ }
+ }
+ if ($bChecked && !$bValid)
+ {
+ // Trigger does not match the current context
+ return false;
+ }
+
+ return true;
+ }
+
/**
* @param $aContextArgs
*
@@ -73,6 +107,15 @@ abstract class Trigger extends cmdbAbstractObject
*/
public function DoActivate($aContextArgs)
{
+ // Check the context
+ if (!$this->IsContextValid())
+ {
+ // Trigger does not match the current context
+ IssueLog::Info("Context NOT valid for: ".$this->Get('friendlyname'));
+ return;
+ }
+ IssueLog::Info("Context VALID for: ".$this->Get('friendlyname'));
+
// Find the related actions
$oLinkedActions = $this->Get('action_list');
while ($oLink = $oLinkedActions->Fetch())
@@ -133,7 +176,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', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
+ MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', '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
@@ -258,7 +301,7 @@ class TriggerOnPortalUpdate extends TriggerOnObject
MetaModel::Init_InheritAttributes();
// Display lists
- MetaModel::Init_SetZListItems('details', array('description', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
+ MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', '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
}
@@ -292,7 +335,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', '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', '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
@@ -326,7 +369,7 @@ class TriggerOnStateEnter extends TriggerOnStateChange
MetaModel::Init_InheritAttributes();
// Display lists
- MetaModel::Init_SetZListItems('details', array('description', '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', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('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
@@ -360,7 +403,7 @@ class TriggerOnStateLeave extends TriggerOnStateChange
MetaModel::Init_InheritAttributes();
// Display lists
- MetaModel::Init_SetZListItems('details', array('description', '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', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('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
@@ -394,7 +437,7 @@ class TriggerOnObjectCreate extends TriggerOnObject
MetaModel::Init_InheritAttributes();
// Display lists
- MetaModel::Init_SetZListItems('details', array('description', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
+ MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
@@ -428,7 +471,7 @@ class TriggerOnObjectDelete extends TriggerOnObject
MetaModel::Init_InheritAttributes();
// Display lists
- MetaModel::Init_SetZListItems('details', array('description', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
+ MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
@@ -464,7 +507,7 @@ class TriggerOnObjectUpdate extends TriggerOnObject
MetaModel::Init_AddAttribute(new AttributeClassAttCodeSet('target_attcodes', array("allowed_values" => null, "class_field" => "target_class", "sql" => "target_attcodes", "default_value" => null, "is_null_allowed" => true, "max_items" => 20, "min_items" => 0, "attribute_definition_exclusion_list" => "AttributeDashboard,AttributeExternalField,AttributeFinalClass,AttributeFriendlyName,AttributeObsolescenceDate,AttributeObsolescenceFlag,AttributeSubItem", "attribute_definition_list" => null, "depends_on" => array('target_class'))));
// Display lists
- MetaModel::Init_SetZListItems('details', array('description', 'target_class', 'filter', 'target_attcodes', 'action_list')); // Attributes to be displayed for the complete details
+ MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'target_attcodes', 'action_list')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
@@ -599,7 +642,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', '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', '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
diff --git a/datamodels/2.x/authent-local/model.authent-local.php b/datamodels/2.x/authent-local/model.authent-local.php
index 19981bebc..9f342dc42 100755
--- a/datamodels/2.x/authent-local/model.authent-local.php
+++ b/datamodels/2.x/authent-local/model.authent-local.php
@@ -179,7 +179,7 @@ class UserLocal extends UserInternal
public function IsPasswordValid()
{
- if (ContextTag::Check('Setup'))
+ if (ContextTag::Check(ContextTag::TAG_SETUP))
{
// during the setup, the admin account can have whatever password you want ...
return true;
@@ -190,7 +190,7 @@ class UserLocal extends UserInternal
public function getPasswordValidityMessage()
{
- if (ContextTag::Check('Setup'))
+ if (ContextTag::Check(ContextTag::TAG_SETUP))
{
// during the setup, the admin account can have whatever password you want ...
return null;
diff --git a/datamodels/2.x/itop-core-update/ajax.php b/datamodels/2.x/itop-core-update/ajax.php
index 2d0ba9c1a..ce60866ef 100644
--- a/datamodels/2.x/itop-core-update/ajax.php
+++ b/datamodels/2.x/itop-core-update/ajax.php
@@ -23,7 +23,7 @@ require_once(MODULESROOT.'itop-core-update/src/Controller/AjaxController.php');
MetaModel::LoadConfig(utils::GetConfig());
-new ContextTag('Setup');
+new ContextTag(ContextTag::TAG_SETUP);
$oUpdateController = new AjaxController(MODULESROOT.'itop-core-update/view', 'itop-core-update');
$oUpdateController->DisableInDemoMode();
diff --git a/datamodels/2.x/itop-core-update/index.php b/datamodels/2.x/itop-core-update/index.php
index af136b500..ac4897d81 100644
--- a/datamodels/2.x/itop-core-update/index.php
+++ b/datamodels/2.x/itop-core-update/index.php
@@ -10,7 +10,7 @@ use Combodo\iTop\CoreUpdate\Controller\UpdateController;
use ContextTag;
require_once(APPROOT.'application/startup.inc.php');
-new ContextTag('Setup');
+new ContextTag(ContextTag::TAG_SETUP);
$oUpdateController = new UpdateController(MODULESROOT.'itop-core-update/view', 'itop-core-update');
$oUpdateController->DisableInDemoMode();
diff --git a/datamodels/2.x/itop-portal-base/portal/public/index.php b/datamodels/2.x/itop-portal-base/portal/public/index.php
index 805bbd5da..04d090984 100644
--- a/datamodels/2.x/itop-portal-base/portal/public/index.php
+++ b/datamodels/2.x/itop-portal-base/portal/public/index.php
@@ -23,7 +23,7 @@ use Symfony\Component\HttpFoundation\Request;
require_once MODULESROOT.'itop-portal-base/portal/config/bootstrap.php';
// Stacking context tag so it knows we are in the portal
-$oContext = new ContextTag('GUI:Portal');
+$oContext = new ContextTag(ContextTag::TAG_PORTAL);
$oContext2 = new ContextTag('Portal:' . $_ENV['PORTAL_ID']);
// Note: Manually refactored ternary condition to be PHP 5.x compatible
diff --git a/datamodels/2.x/itop-portal-base/portal/src/UrlMaker/AbstractPortalUrlMaker.php b/datamodels/2.x/itop-portal-base/portal/src/UrlMaker/AbstractPortalUrlMaker.php
index 97eff720d..eb965a86b 100644
--- a/datamodels/2.x/itop-portal-base/portal/src/UrlMaker/AbstractPortalUrlMaker.php
+++ b/datamodels/2.x/itop-portal-base/portal/src/UrlMaker/AbstractPortalUrlMaker.php
@@ -100,7 +100,7 @@ abstract class AbstractPortalUrlMaker implements iDBObjectURLMaker
switch ($sMode)
{
case 'view':
- if (!ContextTag::Check('GUI:Portal') || $oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sClass, $iId))
+ if (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sClass, $iId))
{
$sObjectQueryString = $oUrlGenerator->generate('p_object_view', array('sObjectClass' => $sClass, 'sObjectId' => $iId));
}
@@ -109,11 +109,11 @@ abstract class AbstractPortalUrlMaker implements iDBObjectURLMaker
case 'edit':
default:
// Checking if user is allowed to edit object, if not we check if it can at least view it.
- if (!ContextTag::Check('GUI:Portal') || $oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY, $sClass, $iId))
+ if (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_MODIFY, $sClass, $iId))
{
$sObjectQueryString = $oUrlGenerator->generate('p_object_edit', array('sObjectClass' => $sClass, 'sObjectId' => $iId));
}
- elseif (!ContextTag::Check('GUI:Portal') || $oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sClass, $iId))
+ elseif (!ContextTag::Check(ContextTag::TAG_PORTAL) || $oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sClass, $iId))
{
$sObjectQueryString = $oUrlGenerator->generate('p_object_view', array('sObjectClass' => $sClass, 'sObjectId' => $iId));
}
diff --git a/dictionaries/en.dictionary.itop.core.php b/dictionaries/en.dictionary.itop.core.php
index ad1ac55af..9399c5bfd 100644
--- a/dictionaries/en.dictionary.itop.core.php
+++ b/dictionaries/en.dictionary.itop.core.php
@@ -535,6 +535,18 @@ Dict::Add('EN US', 'English', 'English', array(
'Class:Trigger/Attribute:action_list+' => 'Actions performed when the trigger is activated',
'Class:Trigger/Attribute:finalclass' => 'Trigger sub-class',
'Class:Trigger/Attribute:finalclass+' => 'Name of the final class',
+ 'Class:Trigger/Attribute:context/Value:REST/JSON' => 'REST',
+ 'Class:Trigger/Attribute:context/Value:REST/JSON+' => 'REST/JSON',
+ 'Class:Trigger/Attribute:context/Value:Synchro' => 'Synchro',
+ 'Class:Trigger/Attribute:context/Value:Synchro+' => 'Synchro',
+ 'Class:Trigger/Attribute:context/Value:Setup' => 'Setup',
+ 'Class:Trigger/Attribute:context/Value:Setup+' => 'Setup',
+ 'Class:Trigger/Attribute:context/Value:GUI:Console' => 'Console',
+ 'Class:Trigger/Attribute:context/Value:GUI:Console+' => 'GUI:Console',
+ 'Class:Trigger/Attribute:context/Value:CRON' => 'CRON',
+ 'Class:Trigger/Attribute:context/Value:CRON+' => 'CRON',
+ 'Class:Trigger/Attribute:context/Value:GUI:Portal' => 'Portal',
+ 'Class:Trigger/Attribute:context/Value:GUI:Portal+' => 'GUI:Portal',
));
//
diff --git a/dictionaries/fr.dictionary.itop.core.php b/dictionaries/fr.dictionary.itop.core.php
index 2e2e0e7d2..3213c067b 100644
--- a/dictionaries/fr.dictionary.itop.core.php
+++ b/dictionaries/fr.dictionary.itop.core.php
@@ -533,6 +533,18 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Class:Trigger/Attribute:action_list+' => '',
'Class:Trigger/Attribute:finalclass' => 'Sous-classe de Déclencheur',
'Class:Trigger/Attribute:finalclass+' => 'Nom de la classe instanciable',
+ 'Class:Trigger/Attribute:context/Value:REST/JSON' => 'REST',
+ 'Class:Trigger/Attribute:context/Value:REST/JSON+' => 'REST/JSON',
+ 'Class:Trigger/Attribute:context/Value:Synchro' => 'Synchro',
+ 'Class:Trigger/Attribute:context/Value:Synchro+' => 'Synchro',
+ 'Class:Trigger/Attribute:context/Value:Setup' => 'Setup',
+ 'Class:Trigger/Attribute:context/Value:Setup+' => 'Setup',
+ 'Class:Trigger/Attribute:context/Value:GUI:Console' => 'Console',
+ 'Class:Trigger/Attribute:context/Value:GUI:Console+' => 'GUI:Console',
+ 'Class:Trigger/Attribute:context/Value:CRON' => 'CRON',
+ 'Class:Trigger/Attribute:context/Value:CRON+' => 'CRON',
+ 'Class:Trigger/Attribute:context/Value:GUI:Portal' => 'Portal',
+ 'Class:Trigger/Attribute:context/Value:GUI:Portal+' => 'GUI:Portal',
));
//
diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php
index 0b4f45369..83ad48760 100644
--- a/lib/composer/autoload_classmap.php
+++ b/lib/composer/autoload_classmap.php
@@ -45,6 +45,7 @@ return array(
'AttributeEmailAddress' => $baseDir . '/core/attributedef.class.inc.php',
'AttributeEncryptedString' => $baseDir . '/core/attributedef.class.inc.php',
'AttributeEnum' => $baseDir . '/core/attributedef.class.inc.php',
+ 'AttributeEnumSet' => $baseDir . '/core/attributedef.class.inc.php',
'AttributeExternalField' => $baseDir . '/core/attributedef.class.inc.php',
'AttributeExternalKey' => $baseDir . '/core/attributedef.class.inc.php',
'AttributeFinalClass' => $baseDir . '/core/attributedef.class.inc.php',
diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php
index 9b6a75236..82c2ef070 100644
--- a/lib/composer/autoload_static.php
+++ b/lib/composer/autoload_static.php
@@ -275,6 +275,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
'AttributeEmailAddress' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
'AttributeEncryptedString' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
'AttributeEnum' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
+ 'AttributeEnumSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
'AttributeExternalField' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
'AttributeExternalKey' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
'AttributeFinalClass' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php',
diff --git a/setup/applicationinstaller.class.inc.php b/setup/applicationinstaller.class.inc.php
index f191fa7de..5403e3bf3 100644
--- a/setup/applicationinstaller.class.inc.php
+++ b/setup/applicationinstaller.class.inc.php
@@ -685,7 +685,7 @@ class ApplicationInstaller
$oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
$oProductionEnv->InitDataModel($oConfig, true); // load data model only
- $oContextTag = new ContextTag('Setup');
+ $oContextTag = new ContextTag(ContextTag::TAG_SETUP);
// Migrate columns
self::MoveColumns($sDBPrefix);
@@ -878,7 +878,7 @@ class ApplicationInstaller
$oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
$oProductionEnv->InitDataModel($oConfig, true); // load data model and connect to the database
- $oContextTag = new ContextTag('Setup');
+ $oContextTag = new ContextTag(ContextTag::TAG_SETUP);
self::$bMetaModelStarted = true; // No need to reload the final MetaModel in case the installer runs synchronously
// Perform here additional DB setup... profiles, etc...
@@ -945,7 +945,7 @@ class ApplicationInstaller
if (!self::$bMetaModelStarted)
{
$oProductionEnv->InitDataModel($oConfig, false); // load data model and connect to the database
- $oContextTag = new ContextTag('Setup');
+ $oContextTag = new ContextTag(ContextTag::TAG_SETUP);
self::$bMetaModelStarted = true; // No need to reload the final MetaModel in case the installer runs synchronously
}
@@ -1018,7 +1018,7 @@ class ApplicationInstaller
// Record which modules are installed...
$oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
$oProductionEnv->InitDataModel($oConfig, true); // load data model and connect to the database
- $oContextTag = new ContextTag('Setup');
+ $oContextTag = new ContextTag(ContextTag::TAG_SETUP);
if (!$oProductionEnv->RecordInstallation($oConfig, $sDataModelVersion, $aSelectedModuleCodes, $aSelectedExtensionCodes, $sInstallComment))
{
diff --git a/setup/compiler.class.inc.php b/setup/compiler.class.inc.php
index 803a771e9..f8a943f54 100644
--- a/setup/compiler.class.inc.php
+++ b/setup/compiler.class.inc.php
@@ -1528,6 +1528,25 @@ EOF
// Exclusion list of AttributeDefinition Classes to filter class_field (empty means no exclusion)
$aParameters['attribute_definition_exclusion_list'] = $this->GetPropString($oField, 'attribute_definition_exclusion_list', '');
}
+ elseif ($sAttType == 'AttributeEnumSet')
+ {
+ $aTagFieldsInfo[] = $sAttCode;
+ $oValues = $oField->GetUniqueElement('values');
+ $oValueNodes = $oValues->getElementsByTagName('value');
+ $aValues = array();
+ foreach($oValueNodes as $oValue)
+ {
+ // new style... $aValues[] = self::QuoteForPHP($oValue->textContent);
+ $aValues[] = $oValue->textContent;
+ }
+ // new style... $sValues = 'array('.implode(', ', $aValues).')';
+ $sValues = '"'.implode(',', $aValues).'"';
+ $aParameters['allowed_values'] = "new ValueSetEnum($sValues)";
+ $aParameters['sql'] = $this->GetMandatoryPropString($oField, 'sql');
+ $aParameters['is_null_allowed'] = $this->GetPropBoolean($oField, 'is_null_allowed', false);
+ $aParameters['depends_on'] = $sDependencies;
+ $aParameters['max_items'] = $this->GetPropNumber($oField, 'max_items', 12);
+ }
elseif ($sAttType == 'AttributeQueryAttCodeSet')
{
$aTagFieldsInfo[] = $sAttCode;
diff --git a/synchro/synchrodatasource.class.inc.php b/synchro/synchrodatasource.class.inc.php
index 72e5f7769..eac1c4048 100644
--- a/synchro/synchrodatasource.class.inc.php
+++ b/synchro/synchrodatasource.class.inc.php
@@ -2957,7 +2957,7 @@ class SynchroExecution
$this->m_bIsImportPhaseDateKnown = ($oImportPhaseStartDate != null);
$this->m_oImportPhaseStartDate = $oImportPhaseStartDate;
- $this->m_oCtx = new ContextTag('Synchro');
+ $this->m_oCtx = new ContextTag(ContextTag::TAG_SYNCHRO);
$this->m_oCtx1 = new ContextTag('Synchro:'.$oDataSource->GetRawName()); // More precise context information
}
diff --git a/test/core/TriggerTest.php b/test/core/TriggerTest.php
new file mode 100644
index 000000000..e9c703cec
--- /dev/null
+++ b/test/core/TriggerTest.php
@@ -0,0 +1,32 @@
+Set('context', ContextTag::TAG_PORTAL.', '.ContextTag::TAG_CRON);
+ $this->assertFalse($oTrigger->IsContextValid());
+ ContextTag::AddContext(ContextTag::TAG_SETUP);
+ $this->assertFalse($oTrigger->IsContextValid());
+ ContextTag::AddContext(ContextTag::TAG_CRON);
+ $this->assertTrue($oTrigger->IsContextValid());
+ }
+}
diff --git a/webservices/cron.php b/webservices/cron.php
index ca023f193..a406f4718 100644
--- a/webservices/cron.php
+++ b/webservices/cron.php
@@ -44,7 +44,7 @@ if (!file_exists($sConfigFile))
require_once(APPROOT.'/application/startup.inc.php');
-$oCtx = new ContextTag('CRON');
+$oCtx = new ContextTag(ContextTag::TAG_CRON);
function ReadMandatoryParam($oP, $sParam, $sSanitizationFilter = 'parameter')
{
diff --git a/webservices/rest.php b/webservices/rest.php
index 5c020402b..433f2b365 100644
--- a/webservices/rest.php
+++ b/webservices/rest.php
@@ -66,7 +66,7 @@ if (!function_exists('json_last_error_msg')) {
// Main
//
$oP = new ajax_page('rest');
-$oCtx = new ContextTag('REST/JSON');
+$oCtx = new ContextTag(ContextTag::TAG_REST);
$sVersion = utils::ReadParam('version', null, false, 'raw_data');
$sOperation = utils::ReadParam('operation', null);