mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-22 10:08:45 +02:00
N°917: AttributeClassAttCodeSet created
This commit is contained in:
@@ -1654,12 +1654,8 @@ EOF
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
public static function GetFormElementForField(
|
||||
$oPage, $sClass, $sAttCode, $oAttDef, $value = '', $sDisplayValue = '', $iId = '', $sNameSuffix = '',
|
||||
$iFlags = 0, $aArgs = array(), $bPreserveCurrentValue = true
|
||||
) {
|
||||
static $iInputId = 0;
|
||||
$sFieldPrefix = '';
|
||||
public static function GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $value = '', $sDisplayValue = '', $iId = '', $sNameSuffix = '', $iFlags = 0, $aArgs = array(), $bPreserveCurrentValue = true)
|
||||
{
|
||||
$sFormPrefix = isset($aArgs['formPrefix']) ? $aArgs['formPrefix'] : '';
|
||||
$sFieldPrefix = isset($aArgs['prefix']) ? $sFormPrefix.$aArgs['prefix'] : $sFormPrefix;
|
||||
if ($sDisplayValue == '')
|
||||
@@ -2054,16 +2050,23 @@ EOF
|
||||
|
||||
break;
|
||||
|
||||
case 'ObjectAttcodeSet':
|
||||
$iFieldSize = $oAttDef->GetMaxSize();
|
||||
if (is_array($sDisplayValue))
|
||||
case 'ClassAttCodeSet':
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'/js/selectize.min.js');
|
||||
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/selectize.default.css');
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'/js/jquery.itop-tagset-widget.js');
|
||||
|
||||
$oPage->add_dict_entry('Core:AttributeTagSet:placeholder');
|
||||
|
||||
/** @var \ormSet $value */
|
||||
if (isset($aArgs['this']))
|
||||
{
|
||||
$sDisplayValue = implode(', ', $sDisplayValue);
|
||||
$oAttDef->SetTargetClass($aArgs['this']);
|
||||
}
|
||||
$sHTMLValue = "<div class=\"field_input_zone field_input_string\"><input title=\"$sHelpText\" type=\"text\" maxlength=\"$iFieldSize\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8')."\" id=\"$iId\"/></div>{$sValidationSpan}{$sReloadSpan}";
|
||||
$aEventsList[] ='validate';
|
||||
$aEventsList[] ='keyup';
|
||||
$aEventsList[] ='change';
|
||||
$sJson = $oAttDef->GetJsonForWidget($value);
|
||||
$sInputId = "attr_{$sFormPrefix}{$sAttCode}";
|
||||
$sHTMLValue = "<div class=\"field_input_zone field_input_tagset\"><input id='$sInputId' name='$sInputId' type='hidden' value='$sJson'></div>{$sValidationSpan}{$sReloadSpan}";
|
||||
$sScript = "$('#$sInputId').tagset_widget();";
|
||||
$oPage->add_ready_script($sScript);
|
||||
break;
|
||||
|
||||
case 'String':
|
||||
@@ -3315,6 +3318,17 @@ EOF
|
||||
$this->Set($sAttCode, $oTagSet);
|
||||
break;
|
||||
|
||||
case 'ClassAttCodeSet':
|
||||
/** @var ormSet $oSet */
|
||||
$oSet = $this->Get($sAttCode);
|
||||
if (is_null($oSet))
|
||||
{
|
||||
$oSet = new ormSet(get_class($this), $sAttCode);
|
||||
}
|
||||
$oSet->ApplyDelta($value);
|
||||
$this->Set($sAttCode, $oSet);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!is_null($value))
|
||||
{
|
||||
@@ -3506,6 +3520,7 @@ EOF
|
||||
break;
|
||||
|
||||
case 'TagSet':
|
||||
case 'ClassAttCodeSet':
|
||||
$sTagSetJson = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null, 'raw_data');
|
||||
$value = json_decode($sTagSetJson, true);
|
||||
break;
|
||||
@@ -4077,7 +4092,7 @@ EOF
|
||||
$sTip = addslashes($sTip);
|
||||
$sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );";
|
||||
|
||||
if ($oAttDef->GetEditClass() == 'TagSet')
|
||||
if (($oAttDef->GetEditClass() == 'TagSet') || ($oAttDef->GetEditClass() == 'ClassAttCodeSet'))
|
||||
{
|
||||
// Set the value by adding the values to the first one
|
||||
reset($aMultiValues);
|
||||
|
||||
@@ -31,6 +31,7 @@ require_once('ormstopwatch.class.inc.php');
|
||||
require_once('ormpassword.class.inc.php');
|
||||
require_once('ormcaselog.class.inc.php');
|
||||
require_once('ormlinkset.class.inc.php');
|
||||
require_once('ormset.class.inc.php');
|
||||
require_once('ormtagset.class.inc.php');
|
||||
require_once('htmlsanitizer.class.inc.php');
|
||||
require_once(APPROOT.'sources/autoload.php');
|
||||
@@ -6705,23 +6706,54 @@ class AttributeExternalField extends AttributeDefinition
|
||||
* @see TagSetFieldData
|
||||
* @since 2.6 N°931 tag fields
|
||||
*/
|
||||
class AttributeTagSet extends AttributeDBFieldVoid
|
||||
class AttributeTagSet extends AttributeSet
|
||||
{
|
||||
const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_TAG_SET;
|
||||
|
||||
static public function ListExpectedParams()
|
||||
{
|
||||
return array_merge(parent::ListExpectedParams(), array('is_null_allowed', 'tag_max_nb', 'tag_code_max_len'));
|
||||
return array_merge(parent::ListExpectedParams(), array('tag_code_max_len'));
|
||||
}
|
||||
|
||||
public function GetDefaultValue(DBObject $oHostObject = null)
|
||||
/**
|
||||
* @param \ormTagSet $oValue
|
||||
*
|
||||
* @return string JSON to be used in the itop.tagset_widget JQuery widget
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function GetJsonForWidget($oValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
$aJson = array();
|
||||
|
||||
public function IsNullAllowed()
|
||||
{
|
||||
return $this->Get("is_null_allowed");
|
||||
// possible_values
|
||||
$aTagSetObjectData = $this->GetAllowedValues();
|
||||
$aTagSetKeyValData = array();
|
||||
foreach($aTagSetObjectData as $sTagCode => $sTagLabel)
|
||||
{
|
||||
$aTagSetKeyValData[] = [
|
||||
'code' => $sTagCode,
|
||||
'label' => $sTagLabel,
|
||||
];
|
||||
}
|
||||
$aJson['possible_values'] = $aTagSetKeyValData;
|
||||
|
||||
if (is_null($oValue))
|
||||
{
|
||||
$aJson['partial_values'] = array();
|
||||
$aJson['orig_value'] = array();
|
||||
}
|
||||
else
|
||||
{
|
||||
$aJson['partial_values'] = $oValue->GetModifiedTags();
|
||||
$aJson['orig_value'] = array_merge($oValue->GetValue(), $oValue->GetModifiedTags());
|
||||
}
|
||||
$aJson['added'] = array();
|
||||
$aJson['removed'] = array();
|
||||
|
||||
$iMaxTags = $this->GetMaxItems();
|
||||
$aJson['max_tags_allowed'] = $iMaxTags;
|
||||
|
||||
return json_encode($aJson);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6745,7 +6777,7 @@ class AttributeTagSet extends AttributeDBFieldVoid
|
||||
}
|
||||
else
|
||||
{
|
||||
$oTagSet = new ormTagSet($sClass, $sAttCode, $this->GetTagMaxNb());
|
||||
$oTagSet = new ormTagSet($sClass, $sAttCode, $this->GetMaxItems());
|
||||
}
|
||||
$aGoodTags = array();
|
||||
foreach($aTagCodes as $sTagCode)
|
||||
@@ -6757,7 +6789,7 @@ class AttributeTagSet extends AttributeDBFieldVoid
|
||||
if ($oTagSet->IsValidTag($sTagCode))
|
||||
{
|
||||
$aGoodTags[] = $sTagCode;
|
||||
if (!$bNoLimit && (count($aGoodTags) === $this->GetTagMaxNb()))
|
||||
if (!$bNoLimit && (count($aGoodTags) === $this->GetMaxItems()))
|
||||
{
|
||||
// extra and bad tags are ignored
|
||||
break;
|
||||
@@ -6769,11 +6801,6 @@ class AttributeTagSet extends AttributeDBFieldVoid
|
||||
return $oTagSet;
|
||||
}
|
||||
|
||||
public function GetTagMaxNb()
|
||||
{
|
||||
return $this->Get('tag_max_nb');
|
||||
}
|
||||
|
||||
public function GetTagCodeMaxLength()
|
||||
{
|
||||
return $this->Get('tag_code_max_len');
|
||||
@@ -6800,17 +6827,9 @@ class AttributeTagSet extends AttributeDBFieldVoid
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function GetSQLCol($bFullSpec = false)
|
||||
{
|
||||
$iLen = $this->GetMaxSize();
|
||||
return "VARCHAR($iLen)"
|
||||
.CMDBSource::GetSqlStringColumnDefinition()
|
||||
.($bFullSpec ? $this->GetSQLColSpec() : '');
|
||||
}
|
||||
|
||||
public function GetMaxSize()
|
||||
{
|
||||
return $iLen = ($this->GetTagMaxNb() * $this->GetTagCodeMaxLength()) + 1;
|
||||
return $iLen = ($this->GetMaxItems() * $this->GetTagCodeMaxLength()) + 1;
|
||||
}
|
||||
|
||||
public function RequiresIndex()
|
||||
@@ -6862,20 +6881,6 @@ class AttributeTagSet extends AttributeDBFieldVoid
|
||||
return $this->GetExistingTagsFromString($sValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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!
|
||||
*
|
||||
@@ -6887,7 +6892,7 @@ class AttributeTagSet extends AttributeDBFieldVoid
|
||||
*/
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
$oTagSet = new ormTagSet(MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()), $this->GetCode(), $this->GetTagMaxNb());
|
||||
$oTagSet = new ormTagSet(MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()), $this->GetCode(), $this->GetMaxItems());
|
||||
if (is_string($proposedValue) && !empty($proposedValue))
|
||||
{
|
||||
$proposedValue = trim("$proposedValue");
|
||||
@@ -6924,7 +6929,7 @@ class AttributeTagSet extends AttributeDBFieldVoid
|
||||
if ($bLocalizedValue && !empty($sProposedValue))
|
||||
{
|
||||
$oTagSet = new ormTagSet(MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()),
|
||||
$this->GetCode(), $this->GetTagMaxNb());
|
||||
$this->GetCode(), $this->GetMaxItems());
|
||||
$aLabels = explode($sSepItem, $sProposedValue);
|
||||
$aCodes = array();
|
||||
foreach($aLabels as $sTagLabel)
|
||||
@@ -6942,7 +6947,7 @@ class AttributeTagSet extends AttributeDBFieldVoid
|
||||
|
||||
public function GetNullValue()
|
||||
{
|
||||
return new ormTagSet(MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()), $this->GetCode(), $this->GetTagMaxNb());
|
||||
return new ormTagSet(MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()), $this->GetCode(), $this->GetMaxItems());
|
||||
}
|
||||
|
||||
public function IsNull($proposedValue)
|
||||
@@ -6989,18 +6994,6 @@ class AttributeTagSet extends AttributeDBFieldVoid
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sValue
|
||||
* @param null $oHostObj
|
||||
*
|
||||
* @return string
|
||||
* @throws \CoreWarning
|
||||
*/
|
||||
public function GetAsPlainText($sValue, $oHostObj = null)
|
||||
{
|
||||
return $this->GetValueLabel($sValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
@@ -7070,7 +7063,7 @@ class AttributeTagSet extends AttributeDBFieldVoid
|
||||
$aTagCodes = explode(' ', $value);
|
||||
$aValues = array();
|
||||
$oTagSet = new ormTagSet(MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()),
|
||||
$this->GetCode(), $this->GetTagMaxNb());
|
||||
$this->GetCode(), $this->GetMaxItems());
|
||||
foreach($aTagCodes as $sTagCode)
|
||||
{
|
||||
try
|
||||
@@ -7364,7 +7357,7 @@ class AttributeTagSet extends AttributeDBFieldVoid
|
||||
*/
|
||||
public function FromJSONToValue($json)
|
||||
{
|
||||
$oSet = new ormTagSet($this->GetHostClass(), $this->GetCode(), $this->GetTagMaxNb());
|
||||
$oSet = new ormTagSet($this->GetHostClass(), $this->GetCode(), $this->GetMaxItems());
|
||||
$oSet->SetValue($json);
|
||||
|
||||
return $oSet;
|
||||
@@ -9360,7 +9353,48 @@ class AttributeSet extends AttributeDBFieldVoid
|
||||
{
|
||||
static public function ListExpectedParams()
|
||||
{
|
||||
return array_merge(parent::ListExpectedParams(), array('is_null_allowed'));
|
||||
return array_merge(parent::ListExpectedParams(), array('is_null_allowed', 'max_items'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \ormSet $oValue
|
||||
*
|
||||
* @return string JSON to be used in the itop.tagset_widget JQuery widget
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function GetJsonForWidget($oValue)
|
||||
{
|
||||
$aJson = array();
|
||||
|
||||
// possible_values
|
||||
$aSetObjectData = $this->GetAllowedValues();
|
||||
$aSetKeyValData = array();
|
||||
foreach($aSetObjectData as $sCode => $sLabel)
|
||||
{
|
||||
$aSetKeyValData[] = [
|
||||
'code' => $sCode,
|
||||
'label' => $sLabel,
|
||||
];
|
||||
}
|
||||
$aJson['possible_values'] = $aSetKeyValData;
|
||||
|
||||
if (is_null($oValue))
|
||||
{
|
||||
$aJson['partial_values'] = array();
|
||||
$aJson['orig_value'] = array();
|
||||
}
|
||||
else
|
||||
{
|
||||
$aJson['partial_values'] = $oValue->GetModified();
|
||||
$aJson['orig_value'] = array_merge($oValue->GetValues(), $oValue->GetModified());
|
||||
}
|
||||
$aJson['added'] = array();
|
||||
$aJson['removed'] = array();
|
||||
|
||||
$iMaxTags = $this->GetMaxItems();
|
||||
$aJson['max_tags_allowed'] = $iMaxTags;
|
||||
|
||||
return json_encode($aJson);
|
||||
}
|
||||
|
||||
public function GetDefaultValue(DBObject $oHostObject = null)
|
||||
@@ -9384,6 +9418,10 @@ class AttributeSet extends AttributeDBFieldVoid
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
if ($value instanceof ormSet)
|
||||
{
|
||||
$value = $value->GetValues();
|
||||
}
|
||||
if (is_array($value))
|
||||
{
|
||||
return implode(', ', $value);
|
||||
@@ -9409,7 +9447,6 @@ class AttributeSet extends AttributeDBFieldVoid
|
||||
* @param string $sPrefix
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \CoreException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function FromSQLToValue($aCols, $sPrefix = '')
|
||||
@@ -9444,30 +9481,24 @@ class AttributeSet extends AttributeDBFieldVoid
|
||||
*/
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (empty($proposedValue))
|
||||
{
|
||||
return array();
|
||||
}
|
||||
if (is_string($proposedValue))
|
||||
$oSet = new ormSet(MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()), $this->GetCode(), $this->GetMaxItems());
|
||||
if (is_string($proposedValue) && !empty($proposedValue))
|
||||
{
|
||||
$proposedValue = trim("$proposedValue");
|
||||
$proposedValue = explode(',', $proposedValue);
|
||||
$aValues = array();
|
||||
foreach($proposedValue as $sValue)
|
||||
foreach (explode(',', $proposedValue) as $sCode)
|
||||
{
|
||||
$sValue = trim($sValue);
|
||||
$aValues[$sValue] = $sValue;
|
||||
$sValue = trim($sCode);
|
||||
$aValues[] = $sValue;
|
||||
}
|
||||
return $aValues;
|
||||
$oSet->SetValues($aValues);
|
||||
}
|
||||
|
||||
if (is_array($proposedValue))
|
||||
elseif ($proposedValue instanceof ormSet)
|
||||
{
|
||||
return $proposedValue;
|
||||
$oSet = $proposedValue;
|
||||
}
|
||||
|
||||
throw new CoreUnexpectedValue("Wrong format");
|
||||
|
||||
return $oSet;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -9488,14 +9519,25 @@ class AttributeSet extends AttributeDBFieldVoid
|
||||
return $this->MakeRealValue($sProposedValue, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|\ormSet
|
||||
* @throws \CoreException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetNullValue()
|
||||
{
|
||||
return null;
|
||||
return new ormSet(MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()), $this->GetCode(), $this->GetMaxItems());
|
||||
}
|
||||
|
||||
public function IsNull($proposedValue)
|
||||
{
|
||||
return empty($proposedValue);
|
||||
if (empty($proposedValue))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @var \ormSet $proposedValue */
|
||||
return $proposedValue->Count() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -9504,11 +9546,14 @@ class AttributeSet extends AttributeDBFieldVoid
|
||||
* @param $sValue
|
||||
*
|
||||
* @return string label corresponding to the given value (in plain text)
|
||||
* @throws \CoreWarning
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetValueLabel($sValue)
|
||||
{
|
||||
if ($sValue instanceof ormSet)
|
||||
{
|
||||
$sValue = $sValue->GetValues();
|
||||
}
|
||||
if (is_array($sValue))
|
||||
{
|
||||
return implode(', ', $sValue);
|
||||
@@ -9521,7 +9566,7 @@ class AttributeSet extends AttributeDBFieldVoid
|
||||
* @param null $oHostObj
|
||||
*
|
||||
* @return string
|
||||
* @throws \CoreWarning
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetAsPlainText($sValue, $oHostObj = null)
|
||||
{
|
||||
@@ -9532,7 +9577,6 @@ class AttributeSet extends AttributeDBFieldVoid
|
||||
* @param $value
|
||||
*
|
||||
* @return string
|
||||
* @throws \CoreWarning
|
||||
*/
|
||||
public function ScalarToSQL($value)
|
||||
{
|
||||
@@ -9540,6 +9584,10 @@ class AttributeSet extends AttributeDBFieldVoid
|
||||
{
|
||||
return '';
|
||||
}
|
||||
if ($value instanceof ormSet)
|
||||
{
|
||||
$value = $value->GetValues();
|
||||
}
|
||||
if (is_array($value))
|
||||
{
|
||||
return implode(', ', $value);
|
||||
@@ -9554,29 +9602,54 @@ class AttributeSet extends AttributeDBFieldVoid
|
||||
*
|
||||
* @return string|null
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetAsHTML($value, $oHostObject = null, $bLocalize = true)
|
||||
{
|
||||
if ($value instanceof ormSet)
|
||||
{
|
||||
$value = $value->GetValues();
|
||||
}
|
||||
if (is_array($value))
|
||||
{
|
||||
return implode(', ', $value);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function GetMaxItems()
|
||||
{
|
||||
return $this->Get('max_items');
|
||||
}
|
||||
}
|
||||
|
||||
class AttributeObjectAttCodeSet extends AttributeSet
|
||||
class AttributeClassAttCodeSet extends AttributeSet
|
||||
{
|
||||
private $sTargetClass;
|
||||
|
||||
/**
|
||||
* @param \DBObject $oHostObj
|
||||
*
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function SetTargetClass($oHostObj)
|
||||
{
|
||||
if (!empty($oHostObj))
|
||||
{
|
||||
$sTargetClass = $this->Get('class_field');
|
||||
$sClass = $oHostObj->Get($sTargetClass);
|
||||
$this->sTargetClass = $sClass;
|
||||
}
|
||||
}
|
||||
|
||||
static public function ListExpectedParams()
|
||||
{
|
||||
return array_merge(parent::ListExpectedParams(), array('class'));
|
||||
return array_merge(parent::ListExpectedParams(), array('class_field', 'attribute_definition_list'));
|
||||
}
|
||||
|
||||
public function GetEditClass()
|
||||
{
|
||||
return "ObjectAttcodeSet";
|
||||
return "ClassAttCodeSet";
|
||||
}
|
||||
|
||||
public function GetMaxSize()
|
||||
@@ -9584,6 +9657,43 @@ class AttributeObjectAttCodeSet extends AttributeSet
|
||||
return 255;
|
||||
}
|
||||
|
||||
public function GetAllowedValues($aArgs = array(), $sContains = '')
|
||||
{
|
||||
if (!empty($this->sTargetClass))
|
||||
{
|
||||
$aAllowedAttributes = array();
|
||||
$aAllAttributes = MetaModel::GetAttributesList($this->sTargetClass);
|
||||
$sAttDefList = $this->Get('attribute_definition_list');
|
||||
if (!empty($sAttDefList))
|
||||
{
|
||||
$aAllowedDefs = array();
|
||||
foreach(explode(',', $sAttDefList) as $sAttDefName)
|
||||
{
|
||||
$sAttDefName = trim($sAttDefName);
|
||||
$aAllowedDefs[$sAttDefName] = $sAttDefName;
|
||||
}
|
||||
foreach($aAllAttributes as $sAttCode)
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef($this->sTargetClass, $sAttCode);
|
||||
if (isset($aAllowedDefs[get_class($oAttDef)]))
|
||||
{
|
||||
$aAllowedAttributes[$sAttCode] = MetaModel::GetLabel($this->sTargetClass, $sAttCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach($aAllAttributes as $sAttCode)
|
||||
{
|
||||
$aAllowedAttributes[$sAttCode] = MetaModel::GetLabel($this->sTargetClass, $sAttCode);
|
||||
}
|
||||
}
|
||||
return $aAllowedAttributes;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* force an allowed value (type conversion and possibly forces a value as mySQL would do upon writing!
|
||||
*
|
||||
@@ -9595,45 +9705,68 @@ class AttributeObjectAttCodeSet extends AttributeSet
|
||||
*/
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
$aAllowedAttributes = array();
|
||||
$sClass = '';
|
||||
if (!empty($oHostObj))
|
||||
{
|
||||
$sTargetClass = $this->Get('class');
|
||||
$sClass = $oHostObj->Get($sTargetClass);
|
||||
$aAllowedAttributes = MetaModel::GetAttributesList($sClass);
|
||||
}
|
||||
$oSet = new ormSet(MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()), $this->GetCode(), $this->GetMaxItems());
|
||||
$this->SetTargetClass($oHostObj);
|
||||
$aAllowedAttributes = $this->GetAllowedValues();
|
||||
if (is_string($proposedValue) && !empty($proposedValue))
|
||||
{
|
||||
$proposedValue = trim("$proposedValue");
|
||||
$proposedValue = explode(',', $proposedValue);
|
||||
$aValues = array();
|
||||
foreach($proposedValue as $sValue)
|
||||
foreach(explode(',', $proposedValue) as $sValue)
|
||||
{
|
||||
$sAttCode = trim($sValue);
|
||||
if (empty($aAllowedAttributes) || in_array($sAttCode, $aAllowedAttributes))
|
||||
if (empty($aAllowedAttributes) || isset($aAllowedAttributes[$sAttCode]))
|
||||
{
|
||||
$aValues[$sAttCode] = $sAttCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new CoreUnexpectedValue("The attribute {$sAttCode} does not exist in class {$sClass}");
|
||||
throw new CoreUnexpectedValue("The attribute {$sAttCode} does not exist in class {$this->sTargetClass}");
|
||||
}
|
||||
}
|
||||
return $aValues;
|
||||
$oSet->SetValues($aValues);
|
||||
}
|
||||
elseif ($proposedValue instanceof ormSet)
|
||||
{
|
||||
$oSet = $proposedValue;
|
||||
}
|
||||
|
||||
return $proposedValue;
|
||||
return $oSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @param \DBObject $oHostObject
|
||||
* @param bool $bLocalize
|
||||
*
|
||||
* @return string|null
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetAsHTML($value, $oHostObject = null, $bLocalize = true)
|
||||
{
|
||||
$this->SetTargetClass($oHostObject);
|
||||
if ($value instanceof ormSet)
|
||||
{
|
||||
$value = $value->GetValues();
|
||||
}
|
||||
if (is_array($value))
|
||||
{
|
||||
if (!empty($this->sTargetClass) && $bLocalize)
|
||||
{
|
||||
$aLocalizedValues = array();
|
||||
foreach($value as $sAttCode)
|
||||
{
|
||||
$aLocalizedValues[] = MetaModel::GetLabel($this->sTargetClass, $sAttCode);
|
||||
}
|
||||
$value = $aLocalizedValues;
|
||||
}
|
||||
return implode(', ', $value);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The attribute dedicated to the friendly name automatic attribute (not written)
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
|
||||
/**
|
||||
* The attribute dedicated to the friendly name automatic attribute (not written)
|
||||
*
|
||||
|
||||
@@ -1301,6 +1301,34 @@ abstract class DBObject implements iDisplay
|
||||
|
||||
return "Bad type";
|
||||
}
|
||||
elseif ($oAtt instanceof AttributeClassAttCodeSet)
|
||||
{
|
||||
if (is_string($toCheck))
|
||||
{
|
||||
$oTag = new ormSet(get_class($this), $sAttCode);
|
||||
try
|
||||
{
|
||||
$aValues = array();
|
||||
foreach(explode(',', $toCheck) as $sValue)
|
||||
{
|
||||
$aValues[] = trim($sValue);
|
||||
}
|
||||
$oTag->SetValues($aValues);
|
||||
} catch (Exception $e)
|
||||
{
|
||||
return "Set value '$toCheck' is not a valid set";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($toCheck instanceof ormSet)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return "Bad type";
|
||||
}
|
||||
elseif ($oAtt->IsScalar())
|
||||
{
|
||||
$aValues = $oAtt->GetAllowedValues($this->ToArgsForQuery());
|
||||
|
||||
379
core/ormset.class.inc.php
Normal file
379
core/ormset.class.inc.php
Normal file
@@ -0,0 +1,379 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) 2010-2018 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* Date: 24/08/2018
|
||||
* Time: 14:35
|
||||
*/
|
||||
final class ormSet
|
||||
{
|
||||
private $sClass; // class of the field
|
||||
private $sAttCode; // attcode of the field
|
||||
private $aOriginalObjects = null;
|
||||
|
||||
/**
|
||||
* Object from the original set, minus the removed objects
|
||||
*/
|
||||
private $aPreserved = array();
|
||||
|
||||
/**
|
||||
* New items
|
||||
*/
|
||||
private $aAdded = array();
|
||||
|
||||
/**
|
||||
* Removed items
|
||||
*/
|
||||
private $aRemoved = array();
|
||||
|
||||
/**
|
||||
* Modified items (mass edit)
|
||||
*/
|
||||
private $aModified = array();
|
||||
|
||||
/**
|
||||
* @var int Max number of tags in collection
|
||||
*/
|
||||
private $iLimit;
|
||||
|
||||
/**
|
||||
* __toString magical function overload.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$aValue = $this->GetValues();
|
||||
if (!empty($aValue))
|
||||
{
|
||||
return implode(', ', $aValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ' ';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ormSet constructor.
|
||||
*
|
||||
* @param string $sClass
|
||||
* @param string $sAttCode
|
||||
* @param int $iLimit
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct($sClass, $sAttCode, $iLimit = 12)
|
||||
{
|
||||
$this->sAttCode = $sAttCode;
|
||||
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
if (!$oAttDef instanceof AttributeSet)
|
||||
{
|
||||
throw new Exception("ormSet: field {$sClass}:{$sAttCode} is not a set");
|
||||
}
|
||||
$this->sClass = $sClass;
|
||||
$this->iLimit = $iLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetClass()
|
||||
{
|
||||
return $this->sClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetAttCode()
|
||||
{
|
||||
return $this->sAttCode;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array $aItems
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue when a code is invalid
|
||||
*/
|
||||
public function SetValues($aItems)
|
||||
{
|
||||
if (!is_array($aItems))
|
||||
{
|
||||
throw new CoreUnexpectedValue("Wrong value {$aItems} for {$this->sClass}:{$this->sAttCode}");
|
||||
}
|
||||
|
||||
$oValues = array();
|
||||
$iCount = 0;
|
||||
$bError = false;
|
||||
foreach($aItems as $oItem)
|
||||
{
|
||||
$iCount++;
|
||||
if (($this->iLimit != 0) && ($iCount > $this->iLimit))
|
||||
{
|
||||
$bError = true;
|
||||
continue;
|
||||
}
|
||||
$oValues[] = $oItem;
|
||||
}
|
||||
|
||||
$this->aPreserved = &$oValues;
|
||||
$this->aRemoved = array();
|
||||
$this->aAdded = array();
|
||||
$this->aModified = array();
|
||||
$this->aOriginalObjects = $oValues;
|
||||
|
||||
if ($bError)
|
||||
{
|
||||
throw new CoreException("Maximum number of items ({$this->iLimit}) reached for {$this->sClass}:{$this->sAttCode}");
|
||||
}
|
||||
}
|
||||
|
||||
public function Count()
|
||||
{
|
||||
return count($this->aPreserved) + count($this->aAdded) - count($this->aRemoved);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array of codes
|
||||
*/
|
||||
public function GetValues()
|
||||
{
|
||||
$aValues = array_merge($this->aPreserved, $this->aAdded);
|
||||
|
||||
sort($aValues);
|
||||
|
||||
return $aValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array of tag labels indexed by code for only the added tags
|
||||
*/
|
||||
private function GetAdded()
|
||||
{
|
||||
return $this->aAdded;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array of tag labels indexed by code for only the removed tags
|
||||
*/
|
||||
private function GetRemoved()
|
||||
{
|
||||
return $this->aRemoved;
|
||||
}
|
||||
|
||||
/** Get the delta with another ItemSet
|
||||
*
|
||||
* $aDelta['added] = array of tag codes for only the added tags
|
||||
* $aDelta['removed'] = array of tag codes for only the removed tags
|
||||
*
|
||||
* @param \ormSet $oOtherSet
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetDelta(ormSet $oOtherSet)
|
||||
{
|
||||
$oSet = new ormSet($this->sClass, $this->sAttCode);
|
||||
// Set the initial value
|
||||
$aOrigItems = $this->GetValues();
|
||||
$oSet->SetValues($aOrigItems);
|
||||
|
||||
// now remove everything
|
||||
foreach($aOrigItems as $oItem)
|
||||
{
|
||||
$oSet->Remove($oItem);
|
||||
}
|
||||
|
||||
// now add the tags of the other ItemSet
|
||||
foreach($oOtherSet->GetValues() as $oItem)
|
||||
{
|
||||
$oSet->Add($oItem);
|
||||
}
|
||||
|
||||
$aDelta = array();
|
||||
$aDelta['added'] = $oSet->GetAdded();
|
||||
$aDelta['removed'] = $oSet->GetRemoved();
|
||||
|
||||
return $aDelta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[] list of codes for partial entries
|
||||
*/
|
||||
public function GetModified()
|
||||
{
|
||||
return $this->aModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a delta to the current ItemSet
|
||||
* $aDelta['added] = array of tag code for only the added tags
|
||||
* $aDelta['removed'] = array of tag code for only the removed tags
|
||||
*
|
||||
* @param $aDelta
|
||||
*
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function ApplyDelta($aDelta)
|
||||
{
|
||||
if (isset($aDelta['removed']))
|
||||
{
|
||||
foreach($aDelta['removed'] as $oItem)
|
||||
{
|
||||
$this->Remove($oItem);
|
||||
}
|
||||
}
|
||||
if (isset($aDelta['added']))
|
||||
{
|
||||
foreach($aDelta['added'] as $oItem)
|
||||
{
|
||||
$this->Add($oItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $oItem
|
||||
*
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function Add($oItem)
|
||||
{
|
||||
if ($this->Count() === $this->iLimit)
|
||||
{
|
||||
throw new CoreException("Maximum number of items ({$this->iLimit}) reached for {$this->sClass}:{$this->sAttCode}");
|
||||
}
|
||||
if ($this->IsItemInList($this->aPreserved, $oItem) || $this->IsItemInList($this->aAdded, $oItem))
|
||||
{
|
||||
// nothing to do, already existing tag
|
||||
return;
|
||||
}
|
||||
// if removed and added again
|
||||
if (($this->RemoveItemFromList($this->aRemoved, $oItem)) !== false)
|
||||
{
|
||||
// put it back into preserved
|
||||
$this->aPreserved[] = $oItem;
|
||||
// no need to add it to aModified : was already done when calling RemoveItem method
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->aAdded[] = $oItem;
|
||||
$this->aModified[] = $oItem;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $oItem
|
||||
*/
|
||||
public function Remove($oItem)
|
||||
{
|
||||
if ($this->IsItemInList($this->aRemoved, $oItem))
|
||||
{
|
||||
// nothing to do, already removed tag
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->RemoveItemFromList($this->aAdded, $oItem) !== false)
|
||||
{
|
||||
$this->aModified[] = $oItem;
|
||||
|
||||
return; // if present in added, can't be in preserved !
|
||||
}
|
||||
|
||||
if ($this->RemoveItemFromList($this->aPreserved, $oItem) !== false)
|
||||
{
|
||||
$this->aModified[] = $oItem;
|
||||
$this->aRemoved[] = $oItem;
|
||||
}
|
||||
}
|
||||
|
||||
private function IsItemInList($aItemList, $oItem)
|
||||
{
|
||||
return in_array($oItem, $aItemList);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DBObject[] $aItemList
|
||||
* @param $oItem
|
||||
*
|
||||
* @return bool|\DBObject false if not found, else the removed element
|
||||
*/
|
||||
private function RemoveItemFromList(&$aItemList, $oItem)
|
||||
{
|
||||
if (!($this->IsItemInList($aItemList, $oItem)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
foreach ($aItemList as $index => $value)
|
||||
{
|
||||
if ($value === $oItem)
|
||||
{
|
||||
unset($aItemList[$index]);
|
||||
return $oItem;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the added and removed arrays for bulk edit
|
||||
*
|
||||
* @param string[] $aItems
|
||||
*
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function GenerateDiffFromItems($aItems)
|
||||
{
|
||||
foreach($this->GetValues() as $oCurrentItem)
|
||||
{
|
||||
if (!in_array($oCurrentItem, $aItems))
|
||||
{
|
||||
$this->Remove($oCurrentItem);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($aItems as $oNewItem)
|
||||
{
|
||||
$this->Add($oNewItem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare Item Set
|
||||
*
|
||||
* @param \ormSet $other
|
||||
*
|
||||
* @return bool true if same tag set
|
||||
*/
|
||||
public function Equals(ormSet $other)
|
||||
{
|
||||
return implode(', ', $this->GetValue()) === implode(', ', $other->GetValue());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -277,7 +277,6 @@ abstract class TagSetFieldData extends cmdbAbstractObject
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display Tag Usage
|
||||
*
|
||||
@@ -333,6 +332,11 @@ abstract class TagSetFieldData extends cmdbAbstractObject
|
||||
|
||||
public static function GetClassName($sClass)
|
||||
{
|
||||
if ($sClass == 'TagSetFieldData')
|
||||
{
|
||||
$aWords = preg_split('/(?=[A-Z]+)/', $sClass);
|
||||
return trim(implode(' ', $aWords));
|
||||
}
|
||||
try
|
||||
{
|
||||
$aTagFieldInfo = self::ExtractTagFieldName($sClass);
|
||||
|
||||
@@ -427,7 +427,7 @@ class TriggerOnObjectUpdate extends TriggerOnObject
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_InheritAttributes();
|
||||
MetaModel::Init_AddAttribute(new AttributeObjectAttCodeSet('target_attcodes', array("allowed_values" => null, "class" => "target_class", "sql" => "target_attcodes", "default_value" => null, "is_null_allowed" => true, "depends_on" => array('target_class'))));
|
||||
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_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
|
||||
@@ -444,11 +444,13 @@ class TriggerOnObjectUpdate extends TriggerOnObject
|
||||
}
|
||||
|
||||
// Check the attribute
|
||||
$aAttCodes = $this->Get('target_attcodes');
|
||||
$oAttCodeSet = $this->Get('target_attcodes');
|
||||
$aAttCodes = $oAttCodeSet->GetValues();
|
||||
if (empty($aAttCodes))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach($aAttCodes as $sAttCode)
|
||||
{
|
||||
if (array_key_exists($sAttCode, $aChanges))
|
||||
|
||||
@@ -200,6 +200,7 @@
|
||||
<sql>tagfield</sql>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<tracking_level>all</tracking_level>
|
||||
<max_items>12</max_items>
|
||||
</field>
|
||||
</fields>
|
||||
<methods>
|
||||
|
||||
@@ -595,7 +595,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:TriggerOnObjectUpdate' => 'Trigger (on object update)',
|
||||
'Class:TriggerOnObjectUpdate+' => 'Trigger on object update of [a child class of] the given class',
|
||||
'Class:TriggerOnObjectUpdate/Attribute:target_attcodes' => 'Target attributes',
|
||||
'Class:TriggerOnObjectUpdate/Attribute:target_attcodes' => 'Target fields',
|
||||
'Class:TriggerOnObjectUpdate/Attribute:target_attcodes+' => '',
|
||||
));
|
||||
|
||||
|
||||
@@ -1395,7 +1395,7 @@ EOF
|
||||
$aParameters['sql'] = $this->GetMandatoryPropString($oField, 'sql');
|
||||
$aParameters['is_null_allowed'] = $this->GetPropBoolean($oField, 'is_null_allowed', false);
|
||||
$aParameters['depends_on'] = $sDependencies;
|
||||
$aParameters['tag_max_nb'] = $this->GetPropNumber($oField, 'tag_max_nb', 12);
|
||||
$aParameters['max_items'] = $this->GetPropNumber($oField, 'max_items', 12);
|
||||
$aParameters['tag_code_max_len'] = $this->GetPropNumber($oField, 'tag_code_max_len', 20);
|
||||
if ($aParameters['tag_code_max_len'] > 255)
|
||||
{
|
||||
|
||||
@@ -253,7 +253,7 @@ class TagSetFieldDataTest extends ItopDataTestCase
|
||||
{
|
||||
/** @var \AttributeTagSet $oAttDef */
|
||||
$oAttDef = \MetaModel::GetAttributeDef(TAG_CLASS, TAG_ATTCODE);
|
||||
$iMaxTags = $oAttDef->GetTagMaxNb();
|
||||
$iMaxTags = $oAttDef->GetMaxItems();
|
||||
for ($i = 0; $i < $iMaxTags; $i++)
|
||||
{
|
||||
$sTagCode = 'MaxTag'.$i;
|
||||
|
||||
Reference in New Issue
Block a user