Force a field to be mandatory on sub-classes only
Prerequisite: You must be familiar with the wiki syntax and have already created an extension.
- learning:
- Force a field to be filled for some sub-classes only
- level:
- Intermediate
- domains:
- PHP, Constrain
- methods:
- GetAttributeFlags, GetInitialStateAttributeFlags
- min version:
- 2.1.0
This use case is just one way of forcing a field to be provided.
But it does not work for DataSynchro and REST/JSON API.
Mandatory for Datacenter devices
In this use case, we want the location_id
field
declared on the PhysicalDevice class to be mandatory on
DatacenterDevice only. To summarize:
-
Location must be mandatory on every classes under DatacenterDevice: NAS, Network Device, SAN switch, Server, Storage System and Tape library,
-
Location must remains optional on all other Physical Devices classes, such as Mobile Phone for eg.
FYI: In the
standard datamodel, DatacenterDevice is one of the child class of
PhysicalDevice and location_id
is an optional field on
Physical Devices.
This case is tricky as iTop Datamodel does not allow to
overwrite on a sub-class, an attribute defined on a parent class.
location_id
field is declared on PhysicalDevice class
which is the parent class of DatacenterDevice.
location_id
is not
directly a field of DatacenterDevice class:
- itop_design / classes
-
<class id="DatacenterDevice"> <fields> <field id="location_id"> <is_null_allowed _delta="redefine">false</is_null_allowed> </field> </fields> </class>
To address this use case, we must subscribe to 2 events, one for the “Creation Form” and one for the “Modify Form”.
<class id="Server" _delta="must_exist"> <event_listeners> <event_listener id="evtSetCreationFlags" _delta="define"> <!-- Id of the event does not have to be the same as the function, but why not --> <event>EVENT_DB_SET_INITIAL_ATTRIBUTES_FLAGS</event> <rank>10</rank> <!-- The callback must be the name of an existing class method. The name is free --> <callback>evtSetCreationFlags</callback> </event_listener> <event_listener id="evtSetModificationFlags" _delta="define"> <event>EVENT_DB_SET_ATTRIBUTES_FLAGS</event> <rank>10</rank> <callback>evtSetModificationFlags</callback> </event_listener> </event_listeners>
We force location
to be provided at creation and we
prevent location from being removed on modification. Location can
still be changed in object modification form.
- class:DatacenterDevice
-
public function evtSetCreationFlags(Combodo\iTop\Service\Events\EventData $oEventData) { // Cautious the method to call on creation is different from the one in modification $this->ForceInitialAttributeFlags('location_id', OPT_ATT_MANDATORY); } public function evtSetModificationFlags(Combodo\iTop\Service\Events\EventData $oEventData) { // Cautious the method to call on modification is different from the one in creation $this->ForceAttributeFlags('location_id', OPT_ATT_MANDATORY); }
location_id
and not location_name
because
AttributeExternalField are not requested in the form, only the id
isMigration: No visible effect on setup, but objects not compliant can no more be modified in the Console or Portal, until a location is provided. Create an audit rule to retrieve objects not compliant to this new constrain and fix them.
Only Server and Network Devices
In this use case, we want the location_id
field to
be mandatory for Server and NetworkDevice but not
for the other sub-classes of PhysicalDevice.
The solution is similar to the above case, just declare the above methods on the class PhysicalDevice And subscribe to the event on each class Server and NetworkDevice.
- class:PhysicalDevice
-
public function evtSetCreationFlags(Combodo\iTop\Service\Events\EventData $oEventData) { $this->ForceInitialAttributeFlags('location_id', OPT_ATT_MANDATORY); } public function evtSetModificationFlags(Combodo\iTop\Service\Events\EventData $oEventData) { $this->ForceAttributeFlags('location_id', OPT_ATT_MANDATORY); }
- itop_design / classes
-
<class id="Server"> <event_listeners> <event_listener id="evtSetCreationFlags" _delta="define"> <event>EVENT_DB_SET_INITIAL_ATTRIBUTES_FLAGS</event> <rank>10</rank> <callback>evtSetCreationFlags</callback> </event_listener> <event_listener id="evtSetModificationFlags" _delta="define"> <event>EVENT_DB_SET_ATTRIBUTES_FLAGS</event> <rank>10</rank> <callback>evtSetModificationFlags</callback> </event_listener> </event_listeners> </class> <class id="NetworkDevice"> <event_listeners> <event_listener id="evtSetCreationFlags" _delta="define"> <event>EVENT_DB_SET_INITIAL_ATTRIBUTES_FLAGS</event> <rank>10</rank> <callback>evtSetCreationFlags</callback> </event_listener> <event_listener id="evtSetModificationFlags" _delta="define"> <event>EVENT_DB_SET_ATTRIBUTES_FLAGS</event> <rank>10</rank> <callback>evtSetModificationFlags</callback> </event_listener> </event_listeners> </class>
All DatacenterDevice but Tape library
This use case: we want the location_id
field to be
mandatory for all DatacenterDevice except for Tape
library
The solution is similar to the above case, just declare the
above methods on class DatacenterDevice and within the function
test if the finalclass is not TapeLibrary
.
Here is the method to get and test the finalclass value within PHP method
If ($this->Get('finalclass') != 'TapeLibrary') { ...