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 adress this use case, we must overload 2
methods, one for the “Creation Form” and one for the
“Modify Form”. 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 GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '') { // This function is invoked when the object is EDITED on the Console // It is called for each and every field of the object, // but we just want to change the behavior for a single field if ($sAttCode == 'location_id') { // Combine our mandatory Flag with those impose by a parent class return(OPT_ATT_MANDATORY | parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState)); } return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState); } public function GetInitialStateAttributeFlags($sAttCode, &$aReasons = array()) { // This function is invoked when the object is CREATED on the Console // It is called for each and every field of the object, // but we just want to change the behavior for a single field if (($sAttCode == 'location_id')) { // Combine our mandatory Flag with those impose by a parent class return(OPT_ATT_MANDATORY | parent::GetInitialStateAttributeFlags($sAttCode, $aReasons)); } // For other fields than "location_id" ask the parent class to do the job return parent::GetInitialStateAttributeFlags($sAttCode, $aReasons); }
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 each class Server and NetworkDevice.
- class:Server
-
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '') { ... } public function GetInitialStateAttributeFlags($sAttCode, &$aReasons = array()) { ...}
- class:NetworkDevice
-
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '') { ... } public function GetInitialStateAttributeFlags($sAttCode, &$aReasons = array()) { ...}
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') { ...