diff --git a/core/action.class.inc.php b/core/action.class.inc.php index 824cebdad..b07ad65ac 100644 --- a/core/action.class.inc.php +++ b/core/action.class.inc.php @@ -199,7 +199,7 @@ abstract class ActionNotification extends Action // - Attributes to be displayed for the complete details MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'trigger_list')); // - Attributes to be displayed for a list - MetaModel::Init_SetZListItems('list', array('finalclass', 'name', 'description', 'status')); + MetaModel::Init_SetZListItems('list', array('finalclass', 'description', 'status')); // Search criteria // - Criteria of the std search form // MetaModel::Init_SetZListItems('standard_search', array('name')); @@ -289,7 +289,7 @@ class ActionEmail extends ActionNotification )); // - Attributes to be displayed for a list - MetaModel::Init_SetZListItems('list', array('name', 'status', 'to', 'subject')); + MetaModel::Init_SetZListItems('list', array('status', 'to', 'subject')); // Search criteria // - Standard criteria of the search MetaModel::Init_SetZListItems('standard_search', array('name', 'description', 'status', 'subject')); diff --git a/core/trigger.class.inc.php b/core/trigger.class.inc.php index dde325629..84a5d05e8 100644 --- a/core/trigger.class.inc.php +++ b/core/trigger.class.inc.php @@ -36,7 +36,7 @@ abstract class Trigger extends cmdbAbstractObject "category" => "grant_by_profile,core/cmdb", "key_type" => "autoincrement", "name_attcode" => "description", - "complementary_name_attcode" => array('finalclass'), + "complementary_name_attcode" => array('finalclass', 'triggering_class'), "state_attcode" => "", "reconc_keys" => array('description'), "db_table" => "priv_trigger", @@ -50,11 +50,13 @@ abstract class Trigger extends cmdbAbstractObject MetaModel::Init_AddAttribute(new AttributeLinkedSetIndirect("action_list", array("linked_class" => "lnkTriggerAction", "ext_key_to_me" => "trigger_id", "ext_key_to_remote" => "action_id", "allowed_values" => null, "count_min" => 1, "count_max" => 0, "depends_on" => array()))); $aTags = ContextTag::GetTags(); - MetaModel::Init_AddAttribute( new AttributeEnumSet("context", array("allowed_values" => null, "possible_values" => new ValueSetEnumPadded($aTags), "sql" => "context", "depends_on" => array(), "is_null_allowed" => true, "max_items" => 12))); + MetaModel::Init_AddAttribute(new AttributeEnumSet("context", array("allowed_values" => null, "possible_values" => new ValueSetEnumPadded($aTags), "sql" => "context", "depends_on" => array(), "is_null_allowed" => true, "max_items" => 12))); + // "triggering_class" is a computed field, fed by TriggerOnObject::ComputeValues, so it can be displayed in complementary_name + MetaModel::Init_AddAttribute(new AttributeString("triggering_class", array("allowed_values" => null, "sql" => "triggering_class", "default_value" => null, "is_null_allowed" => true, "depends_on" => array()))); // Display lists - MetaModel::Init_SetZListItems('details', array('finalclass', 'description', 'context', 'action_list')); // Attributes to be displayed for the complete details - MetaModel::Init_SetZListItems('list', array('finalclass')); // Attributes to be displayed for a list + MetaModel::Init_SetZListItems('details', array('finalclass', 'description', 'context', 'action_list', 'triggering_class')); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('list', array('finalclass', 'triggering_class')); // Attributes to be displayed for a list // Search criteria // MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form // MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form @@ -200,6 +202,17 @@ abstract class TriggerOnObject extends Trigger } } + /** + * @throws \CoreException + */ + public function ComputeValues() + { + parent::ComputeValues(); + // Copy the "triggering class name" in parent field, so it can be used in complementary_name of Trigger + $this->Set('triggering_class', $this->Get('target_class')); + } + + /** * Check whether the given object is in the scope of this trigger * and can potentially be the subject of notifications diff --git a/datamodels/2.x/itop-structure/module.itop-structure.php b/datamodels/2.x/itop-structure/module.itop-structure.php index 4b917bc46..c6f5f08e2 100644 --- a/datamodels/2.x/itop-structure/module.itop-structure.php +++ b/datamodels/2.x/itop-structure/module.itop-structure.php @@ -95,8 +95,29 @@ if (!class_exists('StructureInstaller')) */ public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion) { - if (version_compare($sPreviousVersion, '3.0.0', '<')) - { + // Search for existing TriggerOnObject where the Trigger string triggering_class is empty and set them with target_class field value + if (version_compare($sPreviousVersion, '3.1.0', '<')) { + SetupLog::Info("| Feed computed field triggering_class on existing Triggers."); + + $sTableToSet = MetaModel::DBGetTable('Trigger', 'triggering_class'); + $sTableToRead = MetaModel::DBGetTable('TriggerOnObject', 'target_class'); + $oAttDefToSet = MetaModel::GetAttributeDef('Trigger', 'triggering_class'); + $oAttDefToRead = MetaModel::GetAttributeDef('TriggerOnObject', 'target_class'); + + $aColumnsToSets = array_keys($oAttDefToSet->GetSQLColumns()); + $sColumnToSet = $aColumnsToSets[0]; // We know that a string has only one column + $aColumnsToReads = array_keys($oAttDefToRead->GetSQLColumns()); + $sColumnToRead = $aColumnsToReads[0]; // We know that a string has only one column + + $sRepair = "UPDATE `$sTableToSet` JOIN `$sTableToRead` ON `$sTableToSet`.id = `$sTableToRead`.id SET `$sTableToSet`.`$sColumnToSet` = `$sTableToRead`.`$sColumnToRead` WHERE `$sTableToSet`.`$sColumnToSet` = ''"; + SetupLog::Debug("| | Query: ".$sRepair); + CMDBSource::Query($sRepair); + $iNbProcessed = CMDBSource::AffectedRows(); + SetupLog::Info("| | ".$iNbProcessed." triggers processed."); + } + + // Add default configuration, so Persons are notified if mentioned on any Caselog + if (version_compare($sPreviousVersion, '3.0.0', '<')) { SetupLog::Info("Adding default triggers/action for Person objects mentions. All DM classes with at least 1 log attribute will be concerned..."); $sPersonClass = 'Person'; @@ -172,7 +193,7 @@ if (!class_exists('StructureInstaller')) // Build the corresponding action and link it to the triggers if (count($aCreatedTriggerIds) > 0) { $oAction = MetaModel::NewObject('ActionEmail'); - $oAction->Set('name', 'Email mentioned person'); + $oAction->Set('name', 'Notification to persons mentioned in case logs'); $oAction->Set('status', 'enabled'); $oAction->Set('from', '$current_contact->email$'); $oAction->Set('to', 'SELECT Person WHERE id = :mentioned->id'); diff --git a/dictionaries/en.dictionary.itop.core.php b/dictionaries/en.dictionary.itop.core.php index 9326771a7..ac12c0abb 100644 --- a/dictionaries/en.dictionary.itop.core.php +++ b/dictionaries/en.dictionary.itop.core.php @@ -579,16 +579,19 @@ While editing, click on the magnifier to get pertinent examples', // Dict::Add('EN US', 'English', 'English', array( - 'Class:Trigger' => 'Trigger', - 'Class:Trigger+' => 'Custom event handler', - 'Class:Trigger/Attribute:description' => 'Description', - 'Class:Trigger/Attribute:description+' => 'one line description', - 'Class:Trigger/Attribute:action_list' => 'Triggered actions', - 'Class:Trigger/Attribute:action_list+' => 'Actions performed when the trigger is activated', - 'Class:Trigger/Attribute:finalclass' => 'Trigger sub-class', - 'Class:Trigger/Attribute:finalclass+' => 'Name of the final class', - 'Class:Trigger/Attribute:context' => 'Context', - 'Class:Trigger/Attribute:context+' => 'Context to allow the trigger to start', + 'Class:Trigger' => 'Trigger', + 'Class:Trigger+' => 'Custom event handler', + 'Class:Trigger/ComplementaryName' => '%1$s, class restriction: %2$s', + 'Class:Trigger/Attribute:description' => 'Description', + 'Class:Trigger/Attribute:description+' => 'one line description', + 'Class:Trigger/Attribute:action_list' => 'Triggered actions', + 'Class:Trigger/Attribute:action_list+' => 'Actions performed when the trigger is activated', + 'Class:Trigger/Attribute:finalclass' => 'Trigger sub-class', + 'Class:Trigger/Attribute:finalclass+' => 'Name of the final class', + 'Class:Trigger/Attribute:context' => 'Context', + 'Class:Trigger/Attribute:context+' => 'Context to allow the trigger to start', + 'Class:Trigger/Attribute:triggering_class' => 'Triggering class', + 'Class:Trigger/Attribute:triggering_class+' => 'Class triggering, if applicable for this type of trigger', )); // @@ -596,14 +599,14 @@ Dict::Add('EN US', 'English', 'English', array( // Dict::Add('EN US', 'English', 'English', array( - 'Class:TriggerOnObject' => 'Trigger (class dependent)', - 'Class:TriggerOnObject+' => 'Trigger on a given class of objects', - 'Class:TriggerOnObject/Attribute:target_class' => 'Target class', - 'Class:TriggerOnObject/Attribute:target_class+' => '', - 'Class:TriggerOnObject/Attribute:filter' => 'Filter', - 'Class:TriggerOnObject/Attribute:filter+' => 'Limit the object list (of the target class) which will activate the trigger', - 'TriggerOnObject:WrongFilterQuery' => 'Wrong filter query: %1$s', - 'TriggerOnObject:WrongFilterClass' => 'The filter query must return objects of class "%1$s"', + 'Class:TriggerOnObject' => 'Trigger (class dependent)', + 'Class:TriggerOnObject+' => 'Trigger on a given class of objects', + 'Class:TriggerOnObject/Attribute:target_class' => 'Target class', + 'Class:TriggerOnObject/Attribute:target_class+' => 'Objects in this class will activate the trigger', + 'Class:TriggerOnObject/Attribute:filter' => 'Filter', + 'Class:TriggerOnObject/Attribute:filter+' => 'Limit the object list (of the target class) which will activate the trigger', + 'TriggerOnObject:WrongFilterQuery' => 'Wrong filter query: %1$s', + 'TriggerOnObject:WrongFilterClass' => 'The filter query must return objects of class "%1$s"', )); // diff --git a/dictionaries/fr.dictionary.itop.core.php b/dictionaries/fr.dictionary.itop.core.php index fa3fa91a1..f895f9b34 100644 --- a/dictionaries/fr.dictionary.itop.core.php +++ b/dictionaries/fr.dictionary.itop.core.php @@ -580,16 +580,19 @@ En édition, cliquez sur la loupe pour obtenir des exemples pertinents.', // Dict::Add('FR FR', 'French', 'Français', array( - 'Class:Trigger' => 'Déclencheur', - 'Class:Trigger+' => '', - 'Class:Trigger/Attribute:description' => 'Description', - 'Class:Trigger/Attribute:description+' => '', - 'Class:Trigger/Attribute:action_list' => 'Actions déclenchées', - 'Class:Trigger/Attribute:action_list+' => 'Actions effectuées quand le déclencheur est activé', - 'Class:Trigger/Attribute:finalclass' => 'Sous-classe de Déclencheur', - 'Class:Trigger/Attribute:finalclass+' => 'Nom de la classe instanciable', - 'Class:Trigger/Attribute:context' => 'Contexte', - 'Class:Trigger/Attribute:context+' => 'Contexte de déclenchement', + 'Class:Trigger' => 'Déclencheur', + 'Class:Trigger+' => '', + 'Class:Trigger/ComplementaryName' => '%1$s, limité à la classe : %2$s', + 'Class:Trigger/Attribute:description' => 'Description', + 'Class:Trigger/Attribute:description+' => '', + 'Class:Trigger/Attribute:action_list' => 'Actions déclenchées', + 'Class:Trigger/Attribute:action_list+' => 'Actions effectuées quand le déclencheur est activé', + 'Class:Trigger/Attribute:finalclass' => 'Sous-classe de Déclencheur', + 'Class:Trigger/Attribute:finalclass+' => 'Nom de la classe instanciable', + 'Class:Trigger/Attribute:context' => 'Contexte', + 'Class:Trigger/Attribute:context+' => 'Contexte de déclenchement', + 'Class:Trigger/Attribute:triggering_class' => 'Classe concernée', + 'Class:Trigger/Attribute:triggering_class+' => 'Classe concernée par ce déclencheur', )); // @@ -597,14 +600,14 @@ Dict::Add('FR FR', 'French', 'Français', array( // Dict::Add('FR FR', 'French', 'Français', array( - 'Class:TriggerOnObject' => 'Déclencheur sur modification de données', - 'Class:TriggerOnObject+' => '', - 'Class:TriggerOnObject/Attribute:target_class' => 'Classe cible', - 'Class:TriggerOnObject/Attribute:target_class+' => '', - 'Class:TriggerOnObject/Attribute:filter' => 'Filtre', - 'Class:TriggerOnObject/Attribute:filter+' => 'Permet de limiter la liste des objets (de la classe cible) pour lesquels le déclencheur s\'activera', - 'TriggerOnObject:WrongFilterQuery' => 'Requête de filtrage incorrecte: %1$s', - 'TriggerOnObject:WrongFilterClass' => 'La requête de filtrage doit retourner des objets de la classe "%1$s"', + 'Class:TriggerOnObject' => 'Déclencheur sur modification de données', + 'Class:TriggerOnObject+' => '', + 'Class:TriggerOnObject/Attribute:target_class' => 'Classe cible', + 'Class:TriggerOnObject/Attribute:target_class+' => 'Classe d\'objets allant activer ce déclencheur', + 'Class:TriggerOnObject/Attribute:filter' => 'Filtre', + 'Class:TriggerOnObject/Attribute:filter+' => 'Permet de limiter la liste des objets (de la classe cible) activant le déclencheur', + 'TriggerOnObject:WrongFilterQuery' => 'Requête de filtrage incorrecte: %1$s', + 'TriggerOnObject:WrongFilterClass' => 'La requête de filtrage doit retourner des objets de la classe "%1$s"', )); //