N°931: Integrity controls + unit tests

This commit is contained in:
Eric
2018-09-11 14:10:05 +02:00
parent c706a2d77c
commit 1fc3b3a4ed
7 changed files with 550 additions and 387 deletions

View File

@@ -5977,7 +5977,7 @@ class AttributeTagSet extends AttributeDBFieldVoid
$aGoodTags = array();
foreach($aTagCodes as $sTagCode)
{
if ($oTagSet->TagsExist($sTagCode))
if ($oTagSet->IsValidTag($sTagCode))
{
$aGoodTags[] = $sTagCode;
}

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -20,8 +20,9 @@
/**
* <p>Stores data for {@link AttributeTagSet} fields
*
* <p>We will have an implementation for each class/field to be able to customize rights (generated in \MFCompiler::CompileClass).<br>
* Only this abstract class will exists in the DB : the implementations won't had any new field.
* <p>We will have an implementation for each class/field to be able to customize rights (generated in
* \MFCompiler::CompileClass).<br> 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];
}
}

View File

@@ -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',
));

View File

@@ -766,4 +766,7 @@ Opérateurs :<br/>
'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é',
));

View File

@@ -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();
}
}