diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index a6642306d..503d26e93 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -5977,7 +5977,7 @@ class AttributeTagSet extends AttributeDBFieldVoid $aGoodTags = array(); foreach($aTagCodes as $sTagCode) { - if ($oTagSet->TagsExist($sTagCode)) + if ($oTagSet->IsValidTag($sTagCode)) { $aGoodTags[] = $sTagCode; } diff --git a/core/cmdbobject.class.inc.php b/core/cmdbobject.class.inc.php index 1f3694766..8f2cf1485 100644 --- a/core/cmdbobject.class.inc.php +++ b/core/cmdbobject.class.inc.php @@ -563,6 +563,12 @@ abstract class CMDBObject extends DBObject $this->DBUpdate(); } + /** + * @param null $oDeletionPlan + * + * @return \DeletionPlan|null + * @throws \DeleteException + */ public function DBDelete(&$oDeletionPlan = null) { return $this->DBDeleteTracked_Internal($oDeletionPlan); @@ -575,6 +581,12 @@ abstract class CMDBObject extends DBObject $this->DBDeleteTracked_Internal($oDeletionPlan); } + /** + * @param null $oDeletionPlan + * + * @return \DeletionPlan|null + * @throws \DeleteException + */ protected function DBDeleteTracked_Internal(&$oDeletionPlan = null) { $prevkey = $this->GetKey(); diff --git a/core/ormtagset.class.inc.php b/core/ormtagset.class.inc.php index 6a8af77d7..8bc7c1190 100644 --- a/core/ormtagset.class.inc.php +++ b/core/ormtagset.class.inc.php @@ -4,7 +4,7 @@ * * This file is part of iTop. * - * iTop is free software; you can redistribute it and/or modify + * 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. @@ -24,160 +24,147 @@ * Date: 24/08/2018 * Time: 14:35 */ - - final class ormTagSet { - private $sClass; // class of the tag field - private $sAttCode; // attcode of the tag field - private $aOriginalObjects = null; + private $sClass; // class of the tag field + private $sAttCode; // attcode of the tag field + private $aOriginalObjects = null; - /** - * @var bool - */ - private $bHasDelta = false; + /** + * @var bool + */ + private $bHasDelta = false; - /** - * Object from the original set, minus the removed objects - * @var DBObject[] array of iObjectId => DBObject - */ - private $aPreserved = array(); + /** + * Object from the original set, minus the removed objects + * + * @var DBObject[] array of iObjectId => DBObject + */ + private $aPreserved = array(); - /** - * @var DBObject[] New items - */ - private $aAdded = array(); + /** + * @var DBObject[] New items + */ + private $aAdded = array(); - /** - * @var DBObject[] Removed items - */ - private $aRemoved = array(); + /** + * @var DBObject[] Removed items + */ + private $aRemoved = array(); - /** - * __toString magical function overload. - */ - public function __toString() - { - return ''; - } + /** + * __toString magical function overload. + */ + public function __toString() + { + $aValue = $this->GetValue(); + if (!empty($aValue)) + { + return implode(' ', $aValue); + } + else + { + return ' '; + } + } - /** - * ormTagSet constructor. - * - * @param string $sClass - * @param string $sAttCode - * - * @throws \Exception - */ - public function __construct($sClass, $sAttCode) - { - $this->sAttCode = $sAttCode; + /** + * ormTagSet constructor. + * + * @param string $sClass + * @param string $sAttCode + * + * @throws \Exception + */ + public function __construct($sClass, $sAttCode) + { + $this->sAttCode = $sAttCode; - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); - if (!$oAttDef instanceof AttributeTagSet) - { - throw new Exception("ormTagSet: field {$sClass}:{$sAttCode} is not a tag"); - } - $this->sClass = $sClass; - } + $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); + if (!$oAttDef instanceof AttributeTagSet) + { + throw new Exception("ormTagSet: field {$sClass}:{$sAttCode} is not a tag"); + } + $this->sClass = $sClass; + } - /** - * - * @param array $aTagCodes - * - * @throws \CoreException - * @throws \CoreUnexpectedValue when a code is invalid - */ - public function SetValue($aTagCodes) - { - if (!is_array($aTagCodes)) - { - throw new CoreUnexpectedValue("Wrong value {$aTagCodes} for {$this->sClass}:{$this->sAttCode}"); - } + /** + * + * @param array $aTagCodes + * + * @throws \CoreException + * @throws \CoreUnexpectedValue when a code is invalid + */ + public function SetValue($aTagCodes) + { + if (!is_array($aTagCodes)) + { + throw new CoreUnexpectedValue("Wrong value {$aTagCodes} for {$this->sClass}:{$this->sAttCode}"); + } - $oTags = array(); - foreach($aTagCodes as $sTagCode) - { - $oTag = $this->GetTagFromCode($sTagCode); - $oTags[$oTag->GetKey()] = $oTag; - } + $oTags = array(); + foreach($aTagCodes as $sTagCode) + { + $oTag = $this->GetTagFromCode($sTagCode); + $oTags[$oTag->GetKey()] = $oTag; + } - $this->aPreserved = &$oTags; - $this->aRemoved = array(); - $this->aAdded = array(); - $this->aOriginalObjects = $oTags; - $this->bHasDelta = false; - } + $this->aPreserved = &$oTags; + $this->aRemoved = array(); + $this->aAdded = array(); + $this->aOriginalObjects = $oTags; + $this->bHasDelta = false; + } - /** - * @return array of tag codes - */ - public function GetValue() - { - $aValues = array(); - foreach ($this->aPreserved as $oTag) - { - try - { - $aValues[] = $oTag->Get('tag_code'); - } catch (CoreException $e) - { - IssueLog::Error($e->getMessage()); - } - } - foreach ($this->aAdded as $oTag) - { - try - { - $aValues[] = $oTag->Get('tag_code'); - } catch (CoreException $e) - { - IssueLog::Error($e->getMessage()); - } - } + /** + * @return array of tag codes + */ + public function GetValue() + { + $aValues = array(); + foreach($this->aPreserved as $oTag) + { + try + { + $aValues[] = $oTag->Get('tag_code'); + } catch (CoreException $e) + { + IssueLog::Error($e->getMessage()); + } + } + foreach($this->aAdded as $oTag) + { + try + { + $aValues[] = $oTag->Get('tag_code'); + } catch (CoreException $e) + { + IssueLog::Error($e->getMessage()); + } + } - sort($aValues); + sort($aValues); - return $aValues; - } + return $aValues; + } /** * @return array of tag labels indexed by code */ public function GetTags() - { - $aTags = array(); - foreach ($this->aPreserved as $oTag) - { - try - { - $aTags[$oTag->Get('tag_code')] = $oTag->Get('tag_label'); - } catch (CoreException $e) - { - IssueLog::Error($e->getMessage()); - } - } - foreach ($this->aAdded as $oTag) - { - try - { - $aTags[$oTag->Get('tag_code')] = $oTag->Get('tag_label'); - } catch (CoreException $e) - { - IssueLog::Error($e->getMessage()); - } - } - ksort($aTags); - return $aTags; - } - - /** - * @return array of tag labels indexed by code for only the added tags - */ - public function GetAddedTags() { $aTags = array(); - foreach ($this->aAdded as $oTag) + foreach($this->aPreserved as $oTag) + { + try + { + $aTags[$oTag->Get('tag_code')] = $oTag->Get('tag_label'); + } catch (CoreException $e) + { + IssueLog::Error($e->getMessage()); + } + } + foreach($this->aAdded as $oTag) { try { @@ -188,6 +175,28 @@ final class ormTagSet } } ksort($aTags); + + return $aTags; + } + + /** + * @return array of tag labels indexed by code for only the added tags + */ + public function GetAddedTags() + { + $aTags = array(); + foreach($this->aAdded as $oTag) + { + try + { + $aTags[$oTag->Get('tag_code')] = $oTag->Get('tag_label'); + } catch (CoreException $e) + { + IssueLog::Error($e->getMessage()); + } + } + ksort($aTags); + return $aTags; } @@ -197,7 +206,7 @@ final class ormTagSet public function GetRemovedTags() { $aTags = array(); - foreach ($this->aRemoved as $oTag) + foreach($this->aRemoved as $oTag) { try { @@ -208,6 +217,7 @@ final class ormTagSet } } ksort($aTags); + return $aTags; } @@ -222,29 +232,30 @@ final class ormTagSet * * @throws \CoreException * @throws \CoreUnexpectedValue + * @throws \Exception */ public function GetDelta(ormTagSet $oOtherTagSet) - { + { $oTag = new ormTagSet($this->sClass, $this->sAttCode); // Set the initial value - $aOrigTagCodes = $this->GetValue(); - $oTag->SetValue($aOrigTagCodes); + $aOrigTagCodes = $this->GetValue(); + $oTag->SetValue($aOrigTagCodes); // now remove everything - foreach($aOrigTagCodes as $sTagCode) - { - $oTag->RemoveTag($sTagCode); - } - // now add the tags of the other TagSet - foreach($oOtherTagSet->GetValue() as $sTagCode) - { - $oTag->AddTag($sTagCode); - } - $aDelta = array(); - $aDelta['added'] = $oTag->GetAddedTags(); - $aDelta['removed'] = $oTag->GetRemovedTags(); + foreach($aOrigTagCodes as $sTagCode) + { + $oTag->RemoveTag($sTagCode); + } + // now add the tags of the other TagSet + foreach($oOtherTagSet->GetValue() as $sTagCode) + { + $oTag->AddTag($sTagCode); + } + $aDelta = array(); + $aDelta['added'] = $oTag->GetAddedTags(); + $aDelta['removed'] = $oTag->GetRemovedTags(); - return $aDelta; - } + return $aDelta; + } /** * Apply a delta to the current TagSet @@ -255,179 +266,195 @@ final class ormTagSet * @throws \CoreUnexpectedValue */ public function ApplyDelta($aDelta) - { - if (isset($aDelta['removed'])) - { - foreach($aDelta['removed'] as $sTagCode => $aTagLabel) - { - $this->RemoveTag($sTagCode); - } - } - if (isset($aDelta['added'])) - { - foreach($aDelta['added'] as $sTagCode => $aTagLabel) - { - $this->AddTag($sTagCode); - } - } - } + { + if (isset($aDelta['removed'])) + { + foreach($aDelta['removed'] as $sTagCode => $aTagLabel) + { + $this->RemoveTag($sTagCode); + } + } + if (isset($aDelta['added'])) + { + foreach($aDelta['added'] as $sTagCode => $aTagLabel) + { + $this->AddTag($sTagCode); + } + } + } /** + * Check whether a tag code is valid or not for this TagSet + * * @param string $sTagCode * * @return bool + */ + public function IsValidTag($sTagCode) + { + try + { + $this->GetTagFromCode($sTagCode); + + return true; + } catch (Exception $e) + { + return false; + } + } + + /** + * @param $sTagCode + * + * @throws \CoreException + * @throws \CoreUnexpectedValue + */ + public function AddTag($sTagCode) + { + if ($this->IsTagInList($this->aPreserved, $sTagCode) || $this->IsTagInList($this->aAdded, $sTagCode)) + { + // nothing to do, already existing tag + return; + } + // if removed then added again + if (($oTag = $this->RemoveTagFromList($this->aRemoved, $sTagCode)) !== false) + { + // put it back into preserved + $this->aPreserved[] = $oTag; + } + else + { + $this->aAdded[] = $this->GetTagFromCode($sTagCode); + } + $this->UpdateHasDeltaFlag(); + } + + /** + * @param $sTagCode + */ + public function RemoveTag($sTagCode) + { + if ($this->IsTagInList($this->aRemoved, $sTagCode)) + { + // nothing to do, already removed tag + return; + } + // if added then remove it + if (($oTag = $this->RemoveTagFromList($this->aAdded, $sTagCode)) === false) + { + // if present then remove it + if (($oTag = $this->RemoveTagFromList($this->aPreserved, $sTagCode)) !== false) + { + $this->aRemoved[] = $oTag; + } + } + $this->UpdateHasDeltaFlag(); + } + + private function IsTagInList($aTagList, $sTagCode) + { + foreach($aTagList as $oTag) + { + /** @var \TagSetFieldData $oTag */ + try + { + $sCode = $oTag->Get('tag_code'); + if ($sCode === $sTagCode) + { + return true; + } + } catch (CoreException $e) + { + IssueLog::Error($e->getMessage()); + } + } + + return false; + } + + private function RemoveTagFromList(&$aTagList, $sTagCode) + { + foreach($aTagList as $index => $oTag) + { + /** @var \TagSetFieldData $oTag */ + try + { + $sCode = $oTag->Get('tag_code'); + if ($sCode === $sTagCode) + { + unset($aTagList[$index]); + + return $oTag; + } + } catch (CoreException $e) + { + IssueLog::Error($e->getMessage()); + } + } + + return false; + } + + private function UpdateHasDeltaFlag() + { + if ((count($this->aAdded) == 0) && (count($this->aRemoved) == 0)) + { + $this->bHasDelta = false; + } + else + { + $this->bHasDelta = true; + } + } + + + /** + * @param $sTagCode + * + * @return DBObject tag + * @throws \CoreUnexpectedValue * @throws \CoreException */ - public function TagsExist($sTagCode) - { - try - { - $this->GetTagFromCode($sTagCode); - return true; - } catch (CoreUnexpectedValue $e) - { - return false; - } - } + private function GetTagFromCode($sTagCode) + { + $aAllowedTags = $this->GetAllowedTags(); + foreach($aAllowedTags as $oAllowedTag) + { + if ($oAllowedTag->Get('tag_code') === $sTagCode) + { + return $oAllowedTag; + } + } + throw new CoreUnexpectedValue("{$sTagCode} is not defined as a valid tag for {$this->sClass}:{$this->sAttCode}"); + } - /** - * @param $sTagCode - * - * @throws \CoreException - * @throws \CoreUnexpectedValue - */ - public function AddTag($sTagCode) - { - if ($this->IsTagInList($this->aPreserved, $sTagCode) || $this->IsTagInList($this->aAdded, $sTagCode)) - { - // nothing to do, already existing tag - return; - } - // if removed then added again - if (($oTag = $this->RemoveTagFromList($this->aRemoved, $sTagCode)) !== false) - { - // put it back into preserved - $this->aPreserved[] = $oTag; - } - else - { - $this->aAdded[] = $this->GetTagFromCode($sTagCode); - } - $this->UpdateHasDeltaFlag(); - } + /** + * @return array + */ + private function GetAllowedTags() + { + return TagSetFieldData::GetAllowedValues($this->sClass, $this->sAttCode); + } - /** - * @param $sTagCode - * - * @throws \CoreException - * @throws \CoreUnexpectedValue - */ - public function RemoveTag($sTagCode) - { - if ($this->IsTagInList($this->aRemoved, $sTagCode)) - { - // nothing to do, already removed tag - return; - } - // if added then remove it - if (($oTag = $this->RemoveTagFromList($this->aAdded, $sTagCode)) === false) - { - // if present then remove it - if (($oTag = $this->RemoveTagFromList($this->aPreserved, $sTagCode)) !== false) - { - $this->aRemoved[] = $oTag; - } - } - $this->UpdateHasDeltaFlag(); - } + /** + * Compare Tag Set + * + * @param \ormTagSet $other + * + * @return bool true if same tag set + */ + public function Equals(ormTagSet $other) + { + if ($this->GetTagDataClass() !== $other->GetTagDataClass()) + { + return false; + } - private function IsTagInList($aTagList, $sTagCode) - { - foreach ($aTagList as $oTag) - { - $sCode = $oTag->Get('tag_code'); - if ($sCode === $sTagCode) - { - return true; - } - } - return false; - } + return implode(' ', $this->GetValue()) === implode(' ', $other->GetValue()); + } - private function RemoveTagFromList(&$aTagList, $sTagCode) - { - foreach ($aTagList as $index => $oTag) - { - $sCode = $oTag->Get('tag_code'); - if ($sCode === $sTagCode) - { - unset($aTagList[$index]); - return $oTag; - } - } - return false; - } - - private function UpdateHasDeltaFlag() - { - if ((count($this->aAdded) == 0) && (count($this->aRemoved) == 0)) - { - $this->bHasDelta = false; - } - else - { - $this->bHasDelta = true; - } - } - - /** - * @param $sTagCode - * - * @return DBObject tag - * @throws \CoreUnexpectedValue - * @throws \CoreException - */ - private function GetTagFromCode($sTagCode) - { - $aAllowedTags = $this->GetAllowedTags(); - foreach($aAllowedTags as $oAllowedTag) - { - if ($oAllowedTag->Get('tag_code') === $sTagCode) - { - return $oAllowedTag; - } - } - throw new CoreUnexpectedValue("{$sTagCode} is not defined as a valid tag for {$this->sClass}:{$this->sAttCode}"); - } - - /** - * @return array - * @throws \CoreException - * @throws \Exception - */ - private function GetAllowedTags() - { - return TagSetFieldData::GetAllowedValues($this->sClass, $this->sAttCode); - } - - /** - * Compare Tag Set - * - * @param \ormTagSet $other - * - * @return bool true if same tag set - */ - public function Equals(ormTagSet $other) - { - if ($this->GetTagDataClass() !== $other->GetTagDataClass()) - { - return false; - } - return implode(' ',$this->GetValue()) === implode(' ', $other->GetValue()); - } - - public function GetTagDataClass() - { - return MetaModel::GetTagDataClass($this->sClass, $this->sAttCode); - } + public function GetTagDataClass() + { + return MetaModel::GetTagDataClass($this->sClass, $this->sAttCode); + } } \ No newline at end of file diff --git a/core/tagsetfield.class.inc.php b/core/tagsetfield.class.inc.php index 3970d04b5..196e15350 100644 --- a/core/tagsetfield.class.inc.php +++ b/core/tagsetfield.class.inc.php @@ -20,8 +20,9 @@ /** *

Stores data for {@link AttributeTagSet} fields * - *

We will have an implementation for each class/field to be able to customize rights (generated in \MFCompiler::CompileClass).
- * Only this abstract class will exists in the DB : the implementations won't had any new field. + *

We will have an implementation for each class/field to be able to customize rights (generated in + * \MFCompiler::CompileClass).
Only this abstract class will exists in the DB : the implementations won't had any + * new field. * * @since 2.6 N°931 tag fields */ @@ -29,64 +30,68 @@ abstract class TagSetFieldData extends cmdbAbstractObject { private static $m_aAllowedValues = array(); - public static function Init() - { - $aParams = array - ( - 'category' => 'bizmodel', - 'key_type' => 'autoincrement', - 'name_attcode' => array('tag_label'), - 'state_attcode' => '', - 'reconc_keys' => array('tag_code'), - 'db_table' => 'priv_tagfielddata', - 'db_key_field' => 'id', - 'db_finalclass_field' => 'finalclass', - ); + /** + * @throws \CoreException + * @throws \Exception + */ + public static function Init() + { + $aParams = array + ( + 'category' => 'bizmodel', + 'key_type' => 'autoincrement', + 'name_attcode' => array('tag_label'), + 'state_attcode' => '', + 'reconc_keys' => array('tag_code'), + 'db_table' => 'priv_tagfielddata', + 'db_key_field' => 'id', + 'db_finalclass_field' => 'finalclass', + ); - MetaModel::Init_Params($aParams); - MetaModel::Init_InheritAttributes(); + MetaModel::Init_Params($aParams); + MetaModel::Init_InheritAttributes(); - MetaModel::Init_AddAttribute(new AttributeString("tag_code", array( - "allowed_values" => null, - "sql" => 'tag_code', - "default_value" => '', - "is_null_allowed" => false, - "depends_on" => array() - ))); - MetaModel::Init_AddAttribute(new AttributeString("tag_label", array( - "allowed_values" => null, - "sql" => 'tag_label', - "default_value" => '', - "is_null_allowed" => false, - "depends_on" => array() - ))); - MetaModel::Init_AddAttribute(new AttributeString("tag_description", array( - "allowed_values" => null, - "sql" => 'tag_description', - "default_value" => '', - "is_null_allowed" => true, - "depends_on" => array() - ))); - MetaModel::Init_AddAttribute(new AttributeString("tag_class", array( - "allowed_values" => null, - "sql" => 'tag_class', - "default_value" => '', - "is_null_allowed" => false, - "depends_on" => array() - ))); - MetaModel::Init_AddAttribute(new AttributeString("tag_attcode", array( - "allowed_values" => null, - "sql" => 'tag_attcode', - "default_value" => '', - "is_null_allowed" => false, - "depends_on" => array() - ))); + MetaModel::Init_AddAttribute(new AttributeString("tag_code", array( + "allowed_values" => null, + "sql" => 'tag_code', + "default_value" => '', + "is_null_allowed" => false, + "depends_on" => array() + ))); + MetaModel::Init_AddAttribute(new AttributeString("tag_label", array( + "allowed_values" => null, + "sql" => 'tag_label', + "default_value" => '', + "is_null_allowed" => false, + "depends_on" => array() + ))); + MetaModel::Init_AddAttribute(new AttributeString("tag_description", array( + "allowed_values" => null, + "sql" => 'tag_description', + "default_value" => '', + "is_null_allowed" => true, + "depends_on" => array() + ))); + MetaModel::Init_AddAttribute(new AttributeString("tag_class", array( + "allowed_values" => null, + "sql" => 'tag_class', + "default_value" => '', + "is_null_allowed" => false, + "depends_on" => array() + ))); + MetaModel::Init_AddAttribute(new AttributeString("tag_attcode", array( + "allowed_values" => null, + "sql" => 'tag_attcode', + "default_value" => '', + "is_null_allowed" => false, + "depends_on" => array() + ))); - MetaModel::Init_SetZListItems('details', array('tag_code', 'tag_label', 'tag_description')); - MetaModel::Init_SetZListItems('standard_search', array('tag_code', 'tag_label', 'tag_description')); - MetaModel::Init_SetZListItems('list', array('tag_code', 'tag_label', 'tag_description')); - } + MetaModel::Init_SetZListItems('details', array('tag_code', 'tag_label', 'tag_description')); + MetaModel::Init_SetZListItems('standard_search', array('tag_code', 'tag_label', 'tag_description')); + MetaModel::Init_SetZListItems('list', array('tag_code', 'tag_label', 'tag_description')); + } public function ComputeValues() { @@ -122,11 +127,30 @@ abstract class TagSetFieldData extends cmdbAbstractObject unset(self::$m_aAllowedValues[$sTagDataClass]); } + /** + * @throws \CoreException + * @throws \MissingQueryArgument + * @throws \MySQLException + * @throws \MySQLHasGoneAwayException + * @throws \OQLException + */ public function DoCheckToWrite() { // Check that code and labels are uniques $sTagCode = $this->Get('tag_code'); + // Check tag_code syntax + if (!preg_match("@^[a-zA-Z0-9]{1,20}$@", $sTagCode)) + { + $this->m_aCheckIssues[] = Dict::S('Core:TagSetFieldData:ErrorTagCodeSyntax'); + } + $sTagLabel = $this->Get('tag_label'); + if (empty($sTagLabel) || (strpos($sTagLabel, "|") !== false)) + { + // Label must not contain | character + $this->m_aCheckIssues[] = Dict::S('Core:TagSetFieldData:ErrorTagLabelSyntax'); + } + $id = $this->GetKey(); $sClassName = get_class($this); if (empty($id)) @@ -151,6 +175,28 @@ abstract class TagSetFieldData extends cmdbAbstractObject parent::DoCheckToWrite(); } + /** + * @throws \CoreException + */ + public function OnUpdate() + { + parent::OnUpdate(); + $aChanges = $this->ListChanges(); + if (array_key_exists('tag_code', $aChanges)) + { + throw new CoreException(Dict::S('Core:TagSetFieldData:ErrorCodeUpdateNotAllowed')); + } + } + + /** + * @param $sClass + * @param $sAttCode + * + * @return mixed + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \MySQLException + */ public static function GetAllowedValues($sClass, $sAttCode) { $sTagDataClass = MetaModel::GetTagDataClass($sClass, $sAttCode); @@ -162,6 +208,7 @@ abstract class TagSetFieldData extends cmdbAbstractObject $oSet = new DBObjectSet($oSearch); self::$m_aAllowedValues[$sTagDataClass] = $oSet->ToArray(); } + return self::$m_aAllowedValues[$sTagDataClass]; } } \ No newline at end of file diff --git a/dictionaries/en.dictionary.itop.core.php b/dictionaries/en.dictionary.itop.core.php index 56776820f..9d64cc960 100644 --- a/dictionaries/en.dictionary.itop.core.php +++ b/dictionaries/en.dictionary.itop.core.php @@ -663,7 +663,7 @@ Dict::Add('EN US', 'English', 'English', array( 'SynchroDataSource:Definition' => 'Definition', 'Core:SynchroAttributes' => 'Attributes', 'Core:SynchroStatus' => 'Status', - 'Core:Synchro:ErrorsLabel' => 'Errors', + 'Core:Synchro:ErrorsLabel' => 'Errors', 'Core:Synchro:CreatedLabel' => 'Created', 'Core:Synchro:ModifiedLabel' => 'Modified', 'Core:Synchro:UnchangedLabel' => 'Unchanged', @@ -690,7 +690,7 @@ Dict::Add('EN US', 'English', 'English', array( 'Core:Synchro:label_obj_disappeared_errors' => 'Errors (%1$s)', 'Core:Synchro:label_obj_disappeared_no_action' => 'No Action (%1$s)', 'Core:Synchro:label_obj_unchanged' => 'Unchanged (%1$s)', - 'Core:Synchro:label_obj_updated' => 'Updated (%1$s)', + 'Core:Synchro:label_obj_updated' => 'Updated (%1$s)', 'Core:Synchro:label_obj_updated_errors' => 'Errors (%1$s)', 'Core:Synchro:label_obj_new_unchanged' => 'Unchanged (%1$s)', 'Core:Synchro:label_obj_new_updated' => 'Updated (%1$s)', @@ -699,8 +699,8 @@ Dict::Add('EN US', 'English', 'English', array( 'Core:SynchroLogTitle' => '%1$s - %2$s', 'Core:Synchro:Nb_Replica' => 'Replica processed: %1$s', 'Core:Synchro:Nb_Class:Objects' => '%1$s: %2$s', - 'Class:SynchroDataSource/Error:AtLeastOneReconciliationKeyMustBeSpecified' => 'At Least one reconciliation key must be specified, or the reconciliation policy must be to use the primary key.', - 'Class:SynchroDataSource/Error:DeleteRetentionDurationMustBeSpecified' => 'A delete retention period must be specified, since objects are to be deleted after being marked as obsolete', + 'Class:SynchroDataSource/Error:AtLeastOneReconciliationKeyMustBeSpecified' => 'At Least one reconciliation key must be specified, or the reconciliation policy must be to use the primary key.', + 'Class:SynchroDataSource/Error:DeleteRetentionDurationMustBeSpecified' => 'A delete retention period must be specified, since objects are to be deleted after being marked as obsolete', 'Class:SynchroDataSource/Error:DeletePolicyUpdateMustBeSpecified' => 'Obsolete objects are to be updated, but no update is specified.', 'Class:SynchroDataSource/Error:DataTableAlreadyExists' => 'The table %1$s already exists in the database. Please use another name for the synchro data table.', 'Core:SynchroReplica:PublicData' => 'Public Data', @@ -829,16 +829,16 @@ Dict::Add('EN US', 'English', 'English', array( 'Core:ExecProcess:Code255' => 'PHP Error (parsing, or runtime)', // Attribute Duration - 'Core:Duration_Seconds' => '%1$ds', - 'Core:Duration_Minutes_Seconds' =>'%1$dmin %2$ds', - 'Core:Duration_Hours_Minutes_Seconds' => '%1$dh %2$dmin %3$ds', - 'Core:Duration_Days_Hours_Minutes_Seconds' => '%1$sd %2$dh %3$dmin %4$ds', + 'Core:Duration_Seconds' => '%1$ds', + 'Core:Duration_Minutes_Seconds' =>'%1$dmin %2$ds', + 'Core:Duration_Hours_Minutes_Seconds' => '%1$dh %2$dmin %3$ds', + 'Core:Duration_Days_Hours_Minutes_Seconds' => '%1$sd %2$dh %3$dmin %4$ds', // Explain working time computing 'Core:ExplainWTC:ElapsedTime' => 'Time elapsed (stored as "%1$s")', 'Core:ExplainWTC:StopWatch-TimeSpent' => 'Time spent for "%1$s"', 'Core:ExplainWTC:StopWatch-Deadline' => 'Deadline for "%1$s" at %2$d%%', - + // Bulk export 'Core:BulkExport:MissingParameter_Param' => 'Missing parameter "%1$s"', 'Core:BulkExport:InvalidParameter_Query' => 'Invalid value for the parameter "query". There is no Query Phrasebook corresponding to the id: "%1$s".', @@ -914,8 +914,11 @@ Dict::Add('EN US', 'English', 'English', array( // Class: TagSetFieldData // Dict::Add('EN US', 'English', 'English', array( - 'Class:TagSetFieldData' => 'List of tags', - 'Class:TagSetFieldData+' => '', + 'Class:TagSetFieldData' => 'List of tags', + 'Class:TagSetFieldData+' => '', 'Core:TagSetFieldData:ErrorDeleteUsedTag' => 'Used tags cannot be deleted', 'Core:TagSetFieldData:ErrorDuplicateTagCodeOrLabel' => 'Tags codes or labels must be unique', + 'Core:TagSetFieldData:ErrorTagCodeSyntax' => 'Tags code should match [a-zA-Z0-9]{1,20} syntax', + 'Core:TagSetFieldData:ErrorTagLabelSyntax' => 'Tags label should not contain | nor be empty', + 'Core:TagSetFieldData:ErrorCodeUpdateNotAllowed' => 'Tags code cannot be changed', )); diff --git a/dictionaries/fr.dictionary.itop.core.php b/dictionaries/fr.dictionary.itop.core.php index 56c9eb98d..fc7a14f0c 100644 --- a/dictionaries/fr.dictionary.itop.core.php +++ b/dictionaries/fr.dictionary.itop.core.php @@ -766,4 +766,7 @@ Opérateurs :
'Core:Validator:MustSelectOne' => 'Veuillez choisir une valeur', 'Core:TagSetFieldData:ErrorDeleteUsedTag' => 'Impossible de supprimer une étiquette utilisée', 'Core:TagSetFieldData:ErrorDuplicateTagCodeOrLabel' => 'Les codes et noms des étiquettes doivent être unique', + 'Core:TagSetFieldData:ErrorTagCodeSyntax' => 'Le code de l\'étiquette doit avoir la syntaxe suivante : [a-zA-Z0-9]{1,20}', + 'Core:TagSetFieldData:ErrorTagLabelSyntax' => 'Le nom de l\'étiquette ne doit pas être vide ni contenir le caractère \'|\'', + 'Core:TagSetFieldData:ErrorCodeUpdateNotAllowed' => 'Le code de l\'étiquette ne peut pas être changé', )); diff --git a/test/core/TagSetFieldDataTest.php b/test/core/TagSetFieldDataTest.php index e463e9a4d..689b1eb73 100644 --- a/test/core/TagSetFieldDataTest.php +++ b/test/core/TagSetFieldDataTest.php @@ -16,9 +16,12 @@ use TagSetFieldData; class TagSetFieldDataTest extends ItopDataTestCase { - // Need commit to create the FULLTEXT INDEX of MySQL + // Need database COMMIT in order to create the FULLTEXT INDEX of MySQL const USE_TRANSACTION = false; + /** + * @throws \CoreException + */ public function testGetAllowedValues() { $aAllowedValues = TagSetFieldData::GetAllowedValues(TAG_CLASS, TAG_ATTCODE); @@ -41,6 +44,9 @@ class TagSetFieldDataTest extends ItopDataTestCase static::assertEquals(4, $iCurrCount - $iInitialCount); } + /** + * @throws \CoreException + */ public function testDoCheckToWrite() { $aAllowedValues = TagSetFieldData::GetAllowedValues(TAG_CLASS, TAG_ATTCODE); @@ -78,7 +84,7 @@ class TagSetFieldDataTest extends ItopDataTestCase try { - $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag5', 'Fourth'); + $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'zembrek', 'Fourth'); } catch (\CoreException $e) { $this->debug($e->getMessage()); @@ -91,28 +97,38 @@ class TagSetFieldDataTest extends ItopDataTestCase /** * @throws \CoreException * @throws \CoreUnexpectedValue + * @throws \Exception */ public function testDoCheckToDelete() { $oTagData = $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag1', 'First'); $oTagData->DBDelete(); + // Create a tag $oTagData = $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag1', 'First'); + //Use it $oTicket = $this->CreateTicket(1); $oTicket->Set(TAG_ATTCODE, 'tag1'); $oTicket->DBWrite(); + + // Try to delete the tag, must complain ! try { $oTagData->DBDelete(); - } - catch (\CoreException $e) + } catch (\DeleteException $e) { static::assertTrue(true); + return; } + // Should not pass here static::assertFalse(true); } + /** + * @throws \CoreException + * @throws \Exception + */ public function testComputeValues() { $sTagClass = \MetaModel::GetTagDataClass(TAG_CLASS, TAG_ATTCODE); @@ -126,4 +142,59 @@ class TagSetFieldDataTest extends ItopDataTestCase static::assertEquals(TAG_ATTCODE, $oTagData->Get('tag_attcode')); } + /** + * Test invalid tag codes + * @dataProvider InvalidTagCodeProvider + * + * @expectedException \CoreException + * + * @param string $sTagCode + * + * @throws \CoreException + */ + public function testInvalidTagCode($sTagCode) + { + $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, $sTagCode, 'First'); + // Should not pass here + static::assertFalse(true); + } + + public function InvalidTagCodeProvider() + { + return array( + 'No space' => array('tag1 1'), + 'No _' => array('tag_1'), + 'No -' => array('tag-1'), + 'No %' => array('tag%1'), + 'Less than 21 chars' => array('012345678901234567890'), + 'At least one char' => array(''), + 'No #' => array('#tag'), + 'No !' => array('tag!'), + ); + } + + /** + * Test invalid tag labels + * @expectedException \CoreException + * @throws \CoreException + */ + public function testInvalidTagLabel() + { + $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag1', 'First|Second'); + // Should not pass here + static::assertFalse(true); + } + + /** + * Test that tag code cannot be modified + * @expectedException \CoreException + * @throws \CoreException + * @throws \CoreUnexpectedValue + */ + public function testUpdateCode() + { + $oTagData = $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag1', 'First'); + $oTagData->Set('tag_code', 'tag2'); + $oTagData->DBWrite(); + } }