diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php
index 637aee863..1b18299cd 100644
--- a/core/attributedef.class.inc.php
+++ b/core/attributedef.class.inc.php
@@ -284,6 +284,11 @@ abstract class AttributeDefinition
}
// table, key field, name field
+
+ /**
+ * @return string
+ * @deprecated never used
+ */
public function ListDBJoins()
{
return "";
@@ -710,7 +715,11 @@ abstract class AttributeDefinition
{
return null;
}
-
+
+ /**
+ * @return mixed|null
+ * @deprecated never used
+ */
public function MakeValue()
{
$sComputeFunc = $this->Get("compute_func");
@@ -5898,9 +5907,15 @@ class AttributeExternalField extends AttributeDefinition
* @see TagSetFieldData
* @since 2.6 N°931 tag fields
*/
-class AttributeTagSet extends AttributeDBField
+class AttributeTagSet extends AttributeDBFieldVoid
{
const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_STRING;
+ static public function ListExpectedParams()
+ {
+ return array_merge(parent::ListExpectedParams(), array("is_null_allowed"));
+ }
+ public function GetDefaultValue(DBObject $oHostObject = null) {return null;}
+ public function IsNullAllowed() {return $this->Get("is_null_allowed");}
public function GetEditClass() {
return "String";
@@ -5968,6 +5983,24 @@ class AttributeTagSet extends AttributeDBField
return $oTagSet;
}
+ /**
+ * Get the value from a given string (plain text, CSV import)
+ *
+ * @param string $sProposedValue
+ * @param bool $bLocalizedValue
+ * @param string $sSepItem
+ * @param string $sSepAttribute
+ * @param string $sSepValue
+ * @param string $sAttributeQualifier
+ *
+ * @return mixed null if no match could be found
+ * @throws \Exception
+ */
+ public function MakeValueFromString($sProposedValue, $bLocalizedValue = false, $sSepItem = null, $sSepAttribute = null, $sSepValue = null, $sAttributeQualifier = null)
+ {
+ // TODO $bLocalizedValue
+ return $this->MakeRealValue($sProposedValue, null);
+ }
public function GetNullValue() {
return new ormTagSet(MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()), $this->GetCode());
@@ -6023,7 +6056,7 @@ class AttributeTagSet extends AttributeDBField
*/
public function GetAsHTML($value, $oHostObject = null, $bLocalize = true)
{
- if (is_object($value) && ($value instanceof ormTagSet))
+ if ($value instanceof ormTagSet)
{
if ($bLocalize)
{
@@ -6033,9 +6066,19 @@ class AttributeTagSet extends AttributeDBField
{
$aValues = $value->GetValue();
}
- return implode(' ', $aValues);
+ if (empty($aValues))
+ {
+ return '';
+ }
+ return ''.implode('', $aValues).'';
}
- return null;
+ if (is_string($value))
+ {
+ $oValue = $this->MakeRealValue($value, $oHostObject);
+ return $this->GetAsHTML($oValue, $oHostObject, $bLocalize);
+ }
+ return parent::GetAsHTML($value, $oHostObject, $bLocalize);
+
}
/**
@@ -6094,7 +6137,7 @@ class AttributeTagSet extends AttributeDBField
{
$aValues = $value->GetValue();
}
- $sRes = implode(' ', $aValues);
+ $sRes = implode('|', $aValues);
}
else
{
diff --git a/core/cmdbchangeop.class.inc.php b/core/cmdbchangeop.class.inc.php
index f6145083d..dae48b873 100644
--- a/core/cmdbchangeop.class.inc.php
+++ b/core/cmdbchangeop.class.inc.php
@@ -242,6 +242,64 @@ class CMDBChangeOpSetAttributeScalar extends CMDBChangeOpSetAttribute
return $sResult;
}
}
+
+/**
+ * Record the modification of a tag set attribute
+ *
+ * @package iTopORM
+ */
+class CMDBChangeOpSetAttributeTagSet extends CMDBChangeOpSetAttribute
+{
+ public static function Init()
+ {
+ $aParams = array
+ (
+ "category" => "core/cmdb",
+ "key_type" => "",
+ "name_attcode" => "change",
+ "state_attcode" => "",
+ "reconc_keys" => array(),
+ "db_table" => "priv_changeop_setatt_tagset",
+ "db_key_field" => "id",
+ "db_finalclass_field" => "",
+ );
+ MetaModel::Init_Params($aParams);
+ MetaModel::Init_InheritAttributes();
+ MetaModel::Init_AddAttribute(new AttributeString("oldvalue", array("allowed_values"=>null, "sql"=>"oldvalue", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
+ MetaModel::Init_AddAttribute(new AttributeString("newvalue", array("allowed_values"=>null, "sql"=>"newvalue", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
+
+ // Display lists
+ MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for the complete details
+ MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for a list
+ }
+
+ /**
+ * Describe (as a text string) the modifications corresponding to this change
+ */
+ public function GetDescription()
+ {
+ $sResult = '';
+ $sTargetObjectClass = $this->Get('objclass');
+ $oTargetObjectKey = $this->Get('objkey');
+ $sAttCode = $this->Get('attcode');
+ $oTargetSearch = new DBObjectSearch($sTargetObjectClass);
+ $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
+
+ $oMonoObjectSet = new DBObjectSet($oTargetSearch);
+ if (UserRights::IsActionAllowedOnAttribute($sTargetObjectClass, $sAttCode, UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
+ {
+ if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) return ''; // Protects against renamed attributes...
+
+ $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
+ $sAttName = $oAttDef->GetLabel();
+ $sNewValue = $this->Get('newvalue');
+ $sOldValue = $this->Get('oldvalue');
+ $sResult = $oAttDef->DescribeChangeAsHTML($sOldValue, $sNewValue);
+ }
+ return $sResult;
+ }
+}
+
/**
* Record the modification of an URL
*
diff --git a/core/cmdbobject.class.inc.php b/core/cmdbobject.class.inc.php
index 7089057bf..b75559c6d 100644
--- a/core/cmdbobject.class.inc.php
+++ b/core/cmdbobject.class.inc.php
@@ -409,7 +409,19 @@ abstract class CMDBObject extends DBObject
$oMyChangeOp->Set("newvalue", $value);
$iId = $oMyChangeOp->DBInsertNoReload();
}
- else
+ elseif ($oAttDef instanceOf AttributeTagSet)
+ {
+ // Tag Set
+ //
+ $oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeTagSet");
+ $oMyChangeOp->Set("objclass", get_class($this));
+ $oMyChangeOp->Set("objkey", $this->GetKey());
+ $oMyChangeOp->Set("attcode", $sAttCode);
+ $oMyChangeOp->Set("oldvalue", implode(' ', $original->GetValue()));
+ $oMyChangeOp->Set("newvalue", implode(' ', $value->GetValue()));
+ $iId = $oMyChangeOp->DBInsertNoReload();
+ }
+ else
{
// Scalars
//
diff --git a/core/excelbulkexport.class.inc.php b/core/excelbulkexport.class.inc.php
index ed15c9465..0a93193b4 100644
--- a/core/excelbulkexport.class.inc.php
+++ b/core/excelbulkexport.class.inc.php
@@ -188,11 +188,16 @@ EOF
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
$sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
}
- else if ($value instanceOf ormDocument)
- {
- $oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
- $sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
- }
+ else if ($value instanceOf ormDocument)
+ {
+ $oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
+ $sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
+ }
+ else if ($value instanceOf ormTagSet)
+ {
+ $oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
+ $sRet = $oAttDef->GetAsCSV($value, '', '', $oObj);
+ }
else
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
diff --git a/core/metamodel.class.php b/core/metamodel.class.php
index 3c5b06e41..711074b43 100644
--- a/core/metamodel.class.php
+++ b/core/metamodel.class.php
@@ -1024,7 +1024,7 @@ abstract class MetaModel
/**
* array of ("classname" => array of attributes)
*
- * @var array
+ * @var \AttributeDefinition[]
*/
private static $m_aAttribDefs = array();
/**
diff --git a/core/tagsetfield.class.inc.php b/core/tagsetfield.class.inc.php
index 5a583de36..0947b7190 100644
--- a/core/tagsetfield.class.inc.php
+++ b/core/tagsetfield.class.inc.php
@@ -83,12 +83,12 @@ abstract class TagSetFieldData extends cmdbAbstractObject
"allowed_values" => null,
"sql" => "is_default",
"default_value" => false,
- "is_null_allowed" => false,
+ "is_null_allowed" => true,
"depends_on" => array()
)));
- MetaModel::Init_SetZListItems('details', array('tag_code', 'tag_label', 'tag_description', 'is_default'));
+ MetaModel::Init_SetZListItems('details', array('tag_code', 'tag_label', 'tag_description', 'tag_class', 'tag_attcode'));
MetaModel::Init_SetZListItems('standard_search', array('tag_code', 'tag_label', 'tag_description', 'is_default'));
MetaModel::Init_SetZListItems('list', array('tag_code', 'tag_label', 'tag_description', 'is_default'));
}
diff --git a/css/light-grey.css b/css/light-grey.css
index 465e5821b..dead22504 100644
--- a/css/light-grey.css
+++ b/css/light-grey.css
@@ -2862,3 +2862,11 @@ table.listResults .originColor {
.menu-icon-select > .ui-menu-item {
padding: 0.3em 3%;
}
+.attribute-tagset {
+ display: inline-block;
+ padding: 3px;
+ background-color: grey;
+ color: white;
+ margin-right: 3px;
+ border-radius: 4px;
+}
diff --git a/css/light-grey.scss b/css/light-grey.scss
index 00fb6f8da..677e46e95 100644
--- a/css/light-grey.scss
+++ b/css/light-grey.scss
@@ -3259,4 +3259,13 @@ table.listResults .originColor{
}
.menu-icon-select > .ui-menu-item{
padding: .3em 3%;
+}
+
+.attribute-tagset{
+ display: inline-block;
+ padding: 3px;
+ background-color: grey;
+ color: white;
+ margin-right: 3px;
+ border-radius: 4px;
}
\ No newline at end of file
diff --git a/setup/compiler.class.inc.php b/setup/compiler.class.inc.php
index e64074cb0..e45518fbd 100644
--- a/setup/compiler.class.inc.php
+++ b/setup/compiler.class.inc.php
@@ -1395,7 +1395,6 @@ EOF
$aParameters['sql'] = $this->GetMandatoryPropString($oField, 'sql');
$aParameters['is_null_allowed'] = $this->GetPropBoolean($oField, 'is_null_allowed', false);
$aParameters['depends_on'] = $sDependencies;
- $aParameters['default_value'] = '';
}
else
{
diff --git a/setup/xmldataloader.class.inc.php b/setup/xmldataloader.class.inc.php
index d5f82a06c..da22e8712 100644
--- a/setup/xmldataloader.class.inc.php
+++ b/setup/xmldataloader.class.inc.php
@@ -273,6 +273,10 @@ class XMLDataLoader
$oDoc = new ormDocument($data, $sMimeType, $sFileName);
$oTargetObj->Set($sAttCode, $oDoc);
}
+ elseif ($oAttDef instanceof AttributeTagSet)
+ {
+ // TODO
+ }
else
{
$value = (string)$oSubNode;