From fae857175b448e2c511866e42fdd2abeb2fdad64 Mon Sep 17 00:00:00 2001 From: Eric Espie Date: Fri, 16 Dec 2022 11:07:41 +0100 Subject: [PATCH] =?UTF-8?q?N=C2=B04756=20-=20Ease=20extensibility=20for=20?= =?UTF-8?q?CRUD=20operations=20:=20Event=20Service=20-=20Changed=20CheckTo?= =?UTF-8?q?Write=20and=20CheckToDelete=20events=20and=20add=20two=20new=20?= =?UTF-8?q?events=20to=20set=20attributes=20flags?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/cmdbabstract.class.inc.php | 135 +++++++++++++++++++++++-- application/datamodel.application.xml | 48 +++++++-- core/dbobject.class.php | 49 +++++++-- 3 files changed, 206 insertions(+), 26 deletions(-) diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 7d5a4d6b6..4f4145a4a 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -39,8 +39,8 @@ use Combodo\iTop\Application\UI\Base\Layout\Object\ObjectFactory; use Combodo\iTop\Application\UI\Base\Layout\TabContainer\Tab\AjaxTab; use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock; use Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory; -use Combodo\iTop\Application\UI\Links\Indirect\BlockIndirectLinksViewTable; use Combodo\iTop\Application\UI\Links\Direct\BlockDirectLinksViewTable; +use Combodo\iTop\Application\UI\Links\Indirect\BlockIndirectLinksViewTable; use Combodo\iTop\Renderer\BlockRenderer; use Combodo\iTop\Renderer\Console\ConsoleFormRenderer; @@ -177,6 +177,13 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay */ protected $bAllowDelete; + + /** @var array attributes flags cache [target_state][attcode]['flags'] */ + protected $aAttributesFlags; + /** @var array initial attributes flags cache [attcode]['flags'] */ + protected $aInitialAttributesFlags; + + /** * Constructor from a row of data (as a hash 'attcode' => value) * @@ -5669,25 +5676,21 @@ JS } /** - * @param array $aEventData - * * @return void * @throws \CoreException */ - final protected function EventCheckToWrite(array $aEventData) + final protected function EventCheckToWrite() { - $this->FireEvent(EVENT_SERVICE_DB_CHECK_TO_WRITE, $aEventData); + $this->FireEvent(EVENT_SERVICE_DB_CHECK_TO_WRITE); } /** - * @param array $aEventData - * * @return void * @throws \CoreException */ - final protected function EventCheckToDelete(array $aEventData) + final protected function EventCheckToDelete() { - $this->FireEvent(EVENT_SERVICE_DB_CHECK_TO_DELETE, $aEventData); + $this->FireEvent(EVENT_SERVICE_DB_CHECK_TO_DELETE); } /** @@ -5748,4 +5751,118 @@ JS $this->FireEvent(EVENT_SERVICE_DB_UNARCHIVE); } + /** + * Append attribute flags + * + * @param string $sAttCode + * @param int $iFlags + * @param string $sTargetState + * @param string|null $sReason + * + * @return void + * @since 3.1.0 + */ + final public function AddAttributeFlags(string $sAttCode, int $iFlags, string $sTargetState = '', string $sReason = null) + { + if (!isset($this->aAttributesFlags[$sTargetState])) { + $this->aAttributesFlags[$sTargetState] = []; + } + $this->aAttributesFlags[$sTargetState][$sAttCode]['flags'] = ($this->aAttributesFlags[$sTargetState][$sAttCode]['flags'] ?? 0) | $iFlags; + if (!is_null($sReason)) { + $this->aAttributesFlags[$sTargetState][$sAttCode]['reasons'][] = $sReason; + } + } + + /** + * Force attribute state + * + * @param string $sAttCode + * @param int $iFlags + * @param string $sTargetState + * @param string|null $sReason + * + * @return void + * @since 3.1.0 + */ + final public function ForceAttributeFlags(string $sAttCode, int $iFlags, string $sTargetState = '', string $sReason = null) + { + if (!isset($this->aAttributesFlags[$sTargetState])) { + $this->aAttributesFlags[$sTargetState] = []; + } + $this->aAttributesFlags[$sTargetState][$sAttCode]['flags'] = $iFlags; + if (!is_null($sReason)) { + $this->aAttributesFlags[$sTargetState][$sAttCode]['reasons'] = [$sReason]; + } + } + + final protected function GetExtensionsAttributeFlags(string $sAttCode, array &$aReasons, string $sTargetState): int + { + if (!isset($this->aAttributesFlags[$sTargetState])) { + $this->aAttributesFlags[$sTargetState] = []; + $aEventData = [ + 'target_state' => $sTargetState, + ]; + $this->FireEvent(EVENT_SERVICE_DB_SET_ATTRIBUTES_FLAGS, $aEventData); + } + $iFlags = $this->aAttributesFlags[$sTargetState][$sAttCode]['flags'] ?? 0; + $aReasons += ($this->aAttributesFlags[$sTargetState][$sAttCode]['reasons'] ?? []); + + return $iFlags; + } + + + /** + * Append attribute flags + * + * @param string $sAttCode + * @param int $iFlags + * @param string|null $sReason + * + * @return void + * @since 3.1.0 + */ + final public function AddInitialAttributeFlags(string $sAttCode, int $iFlags, string $sReason = null) + { + if (!isset($this->aInitialAttributesFlags)) { + $this->aInitialAttributesFlags = []; + } + $this->aInitialAttributesFlags[$sAttCode]['flags'] = ($this->aInitialAttributesFlags[$sAttCode]['flags'] ?? 0) | $iFlags; + if (!is_null($sReason)) { + $this->aInitialAttributesFlags[$sAttCode]['reasons'][] = $sReason; + } + } + + /** + * Force attribute state + * + * @param string $sAttCode + * @param int $iFlags + * @param string|null $sReason + * + * @return void + * @since 3.1.0 + */ + final public function ForceInitialAttributeFlags(string $sAttCode, int $iFlags, string $sReason = null) + { + if (!isset($this->aInitialAttributesFlags)) { + $this->aInitialAttributesFlags = []; + } + $this->aInitialAttributesFlags[$sAttCode]['flags'] = $iFlags; + if (!is_null($sReason)) { + $this->aInitialAttributesFlags[$sAttCode]['reasons'] = [$sReason]; + } + } + + final protected function GetExtensionsInitialStateAttributeFlags(string $sAttCode, array &$aReasons): int + { + if (!isset($this->aInitialAttributesFlags)) { + $this->aInitialAttributesFlags = []; + $this->FireEvent(EVENT_SERVICE_DB_SET_INITIAL_ATTRIBUTES_FLAGS); + } + $iFlags = $this->aInitialAttributesFlags[$sAttCode]['flags'] ?? 0; + $aReasons += ($this->aInitialAttributesFlags[$sAttCode]['reasons'] ?? []); + + return $iFlags; + } + } diff --git a/application/datamodel.application.xml b/application/datamodel.application.xml index a9c6285f0..3057483f2 100644 --- a/application/datamodel.application.xml +++ b/application/datamodel.application.xml @@ -456,7 +456,7 @@ - Check an object before it is written into the database (no change possible) + Check an object before it is written into the database (no change possible). Call DBObject::AddCheckIssue() to signal an issue cmdbAbstractObject @@ -466,10 +466,6 @@ The object to check DBObject - - Array of strings where all the errors found during the object checking are added - array - Debug string string @@ -477,7 +473,7 @@ - Check an object before it is deleted from the database (no change possible) + Check an object before it is deleted from the database (no change possible). Call DBObject::AddDeleteIssue() to signal an issue cmdbAbstractObject @@ -487,10 +483,6 @@ The object to check DBObject - - Array of strings where all the errors found during the object checking are added - array - Debug string string @@ -529,6 +521,42 @@ + + Set object attributes flags. Call cmdbAbstractObject::AddAttributeFlags() for all the attributes to be set for this target state. + + cmdbAbstractObject + + + + The current object + DBObject + + + The target state in which to evaluate the flags + array + + + Debug string + string + + + + + Set object initial attributes flags. Call cmdbAbstractObject::AddInitialAttributeFlags() for all the initial attributes to be set initially. + + cmdbAbstractObject + + + + The current object + DBObject + + + Debug string + string + + + A document has been downloaded from the GUI diff --git a/core/dbobject.class.php b/core/dbobject.class.php index 30ff1c452..9f9490a14 100644 --- a/core/dbobject.class.php +++ b/core/dbobject.class.php @@ -1750,7 +1750,7 @@ abstract class DBObject implements iDisplay * * @param string $sAttCode $sAttCode The code of the attribute * @param array $aReasons To store the reasons why the attribute is read-only (info about the synchro replicas) - * @param string $sTargetState The target state in which to evalutate the flags, if empty the current state will be used + * @param string $sTargetState The target state in which to evaluate the flags, if empty the current state will be used * * @return integer the binary combination of flags for the given attribute in the given state of the object. * Values can be one of the OPT_ATT_HIDDEN, OPT_ATT_READONLY, OPT_ATT_MANDATORY, ... (see define in metamodel.class.php) @@ -1793,7 +1793,8 @@ abstract class DBObject implements iDisplay $iSynchroFlags |= OPT_ATT_READONLY; } } - return $iFlags | $iSynchroFlags; // Combine both sets of flags + $iExtensionsFlags = $this->GetExtensionsAttributeFlags($sAttCode, $aReasons, $sTargetState); + return $iFlags | $iSynchroFlags | $iExtensionsFlags; // Combine both sets of flags } /** @@ -1910,7 +1911,9 @@ abstract class DBObject implements iDisplay $sStateAttCode = MetaModel::GetStateAttributeCode($sClass); $iFlags = MetaModel::GetInitialStateAttributeFlags($sClass, $this->Get($sStateAttCode), $sAttCode); } - return $iFlags; // No need to care about the synchro flags since we'll be creating a new object anyway + + $iExtensionsFlags = $this->GetExtensionsInitialStateAttributeFlags($sAttCode, $aReasons); + return $iFlags | $iExtensionsFlags; // No need to care about the synchro flags since we'll be creating a new object anyway } /** @@ -2355,7 +2358,7 @@ abstract class DBObject implements iDisplay } $this->SetReadOnly('No modification allowed during CheckToWrite'); - $this->EventCheckToWrite(['error_messages' => &$this->m_aCheckIssues]); + $this->EventCheckToWrite(); $this->SetReadWrite(); $this->DoCheckToWrite(); @@ -2387,7 +2390,7 @@ abstract class DBObject implements iDisplay { $this->m_aDeleteIssues = array(); // Ok - $this->EventCheckToDelete(['error_messages' => &$this->m_aDeleteIssues]); + $this->EventCheckToDelete(); if ($this->InSyncScope()) { @@ -5818,6 +5821,28 @@ abstract class DBObject implements iDisplay return $this->m_oLinkHostObject; } + /** + * @param string $sIssue + * + * @return void + * @since 3.1.0 + */ + final public function AddCheckIssue(string $sIssue) + { + $this->m_aCheckIssues[] = $sIssue; + } + + /** + * @param string $sIssue + * + * @return void + * @since 3.1.0 + */ + final public function AddDeleteIssue(string $sIssue) + { + $this->m_aDeleteIssues[] = $sIssue; + } + /** * @param $sEvent * @param array $aEventData @@ -5854,11 +5879,11 @@ abstract class DBObject implements iDisplay { } - protected function EventCheckToWrite(array $aEventData) + protected function EventCheckToWrite() { } - protected function EventCheckToDelete(array $aEventData) + protected function EventCheckToDelete() { } @@ -5890,5 +5915,15 @@ abstract class DBObject implements iDisplay protected function EventUnarchive() { } + + protected function GetExtensionsAttributeFlags(string $sAttCode, array &$aReasons, string $sTargetState): int + { + return 0; + } + + protected function GetExtensionsInitialStateAttributeFlags(string $sAttCode, array &$aReasons): int + { + return 0; + } }