N°6228 - Refactor after review

This commit is contained in:
Eric Espie
2023-11-20 09:22:41 +01:00
parent f72d8f4955
commit 8e0d6d1f00
11 changed files with 302 additions and 516 deletions

View File

@@ -2463,11 +2463,11 @@ abstract class DBObject implements iDisplay
}
/**
* Trigger onObjectUpdate on the remote object when an object pointed by a LinkSet is modified, added or removed
* Trigger onObjectUpdate on the target object when an object pointed by a LinkSet is modified, added or removed
*
* @since 3.1.1 3.2.0 N°6531 method creation
*/
final protected function TriggerOnRemoteObjectUpdate(): void
final protected function ActivateOnObjectUpdateTriggersForTargetObjects(): void
{
$aPreviousValues = $this->ListPreviousValuesForUpdatedAttributes();
@@ -2476,72 +2476,42 @@ abstract class DBObject implements iDisplay
/** @var AttributeExternalKey $oExtKeyWithMirrorLinkAttDef */
$oExtKeyWithMirrorLinkAttDef = MetaModel::GetAttributeDef(get_class($this), $sExtKeyWithMirrorLinkAttCode);
$oRemoteObject = $this->GetRemoteObject($oExtKeyWithMirrorLinkAttDef, $this->Get($sExtKeyWithMirrorLinkAttCode));
if (is_null($oRemoteObject)) {
continue;
}
/** @var AttributeLinkedSet $oAttDefMirrorLink */
$oAttDefMirrorLink = $oExtKeyWithMirrorLinkAttDef->GetMirrorLinkAttribute();
if (is_null($oAttDefMirrorLink)) {
// No LinkSet pointing to me
continue;
}
$sAttCodeMirrorLink = $oAttDefMirrorLink->GetCode();
$sTargetObjectClass = $oExtKeyWithMirrorLinkAttDef->GetTargetClass();
if (array_key_exists($sExtKeyWithMirrorLinkAttCode, $aPreviousValues)) {
// need to update remote old + new
$sPreviousRemoteObjectKey = $aPreviousValues[$sExtKeyWithMirrorLinkAttCode];
$oPreviousRemoteObject = $this->GetRemoteObject($oExtKeyWithMirrorLinkAttDef, $sPreviousRemoteObjectKey);
if (false === is_null($oPreviousRemoteObject)) {
$this->TriggerRemoteObject($oPreviousRemoteObject, $sAttCodeMirrorLink);
}
// need to update old target also
$sPreviousTargetObjectKey = $aPreviousValues[$sExtKeyWithMirrorLinkAttCode];
$oPreviousTargetObject = static::GetObjectIfNotInCRUDStack($sTargetObjectClass, $sPreviousTargetObjectKey);
$this->ActivateOnObjectUpdateTriggers($oPreviousTargetObject, [$sAttCodeMirrorLink]);
}
// we need to update remote with current lnk instance
$this->TriggerRemoteObject($oRemoteObject, $sAttCodeMirrorLink);
$oTargetObject = static::GetObjectIfNotInCRUDStack($sTargetObjectClass, $this->Get($sExtKeyWithMirrorLinkAttCode));
$this->ActivateOnObjectUpdateTriggers($oTargetObject, [$sAttCodeMirrorLink]);
}
}
private function TriggerRemoteObject(DBObject $oRemoteObject, string $sAttCodeMirrorLink): void
final static protected function GetObjectIfNotInCRUDStack($sClass, $sKey)
{
// indicates that $sAttCodeMirrorLink has been modified for the trigger
$oRemoteObject->m_aPreviousValuesForUpdatedAttributes[$sAttCodeMirrorLink] = $oRemoteObject->Get($sAttCodeMirrorLink);
$this->TriggerOnObjectUpdate($oRemoteObject);
}
private function GetRemoteObject(AttributeExternalKey $oAttDef, $sRemoteObjectKey, bool $bWithConstraintProperty = false)
{
$sRemoteObjectClass = $oAttDef->GetTargetClass();
/** @noinspection NotOptimalIfConditionsInspection */
/** @noinspection TypeUnsafeComparisonInspection */
if (utils::IsNullOrEmptyString($sRemoteObjectClass)
|| utils::IsNullOrEmptyString($sRemoteObjectKey)
|| ($sRemoteObjectKey == 0) // non-strict comparison as we might have bad surprises
) {
if (DBObject::IsObjectCurrentlyInCrud($sClass, $sKey)) {
return null;
}
/** @var AttributeLinkedSet $oAttDefMirrorLink */
$oAttDefMirrorLink = $oAttDef->GetMirrorLinkAttribute();
if (is_null($oAttDefMirrorLink)) {
return null;
}
if ($bWithConstraintProperty && (false === $oAttDefMirrorLink->GetHasConstraint())) {
return null;
}
if (DBObject::IsObjectCurrentlyInCrud($sRemoteObjectClass, $sRemoteObjectKey)) {
return null;
}
return MetaModel::GetObject($sRemoteObjectClass, $sRemoteObjectKey, false);
return MetaModel::GetObject($sClass, $sKey, false);
}
/**
* Cascade CheckToWrite to Target Objects With LinkSet Pointing To Me
* @since 3.1.1 3.2.0 N°6228 method creation
*/
final protected function CheckPhpConstraint(bool $bIsCheckToDelete = false): void
final protected function CheckToWriteForTargetObjects(bool $bIsCheckToDelete = false): void
{
$aChanges = $this->ListChanges();
@@ -2550,58 +2520,58 @@ abstract class DBObject implements iDisplay
/** @var AttributeExternalKey $oExtKeyWithMirrorLinkAttDef */
$oExtKeyWithMirrorLinkAttDef = MetaModel::GetAttributeDef(get_class($this), $sExtKeyWithMirrorLinkAttCode);
$oRemoteObject = $this->GetRemoteObject($oExtKeyWithMirrorLinkAttDef, $this->Get($sExtKeyWithMirrorLinkAttCode), true);
if (is_null($oRemoteObject)) {
continue;
}
/** @var AttributeLinkedSet $oAttDefMirrorLink */
$oAttDefMirrorLink = $oExtKeyWithMirrorLinkAttDef->GetMirrorLinkAttribute();
if (is_null($oAttDefMirrorLink)) {
if (is_null($oAttDefMirrorLink) || (false === $oAttDefMirrorLink->HasPHPConstraint())) {
continue;
}
$sAttCodeMirrorLink = $oAttDefMirrorLink->GetCode();
$sTargetObjectClass = $oExtKeyWithMirrorLinkAttDef->GetTargetClass();
$oTargetObject = static::GetObjectIfNotInCRUDStack($sTargetObjectClass, $this->Get($sExtKeyWithMirrorLinkAttCode));
if ($this->IsNew()) {
$this->CheckRemotePhpConstraintOnObject('add', $oRemoteObject, $sAttCodeMirrorLink, false);
$this->CheckToWriteForSingleTargetObject_Internal('add', $oTargetObject, $sAttCodeMirrorLink, false);
} else if ($bIsCheckToDelete) {
$this->CheckRemotePhpConstraintOnObject('remove', $oRemoteObject, $sAttCodeMirrorLink, true);
$this->CheckToWriteForSingleTargetObject_Internal('remove', $oTargetObject, $sAttCodeMirrorLink, true);
} else {
if (array_key_exists($sExtKeyWithMirrorLinkAttCode, $aChanges)) {
// need to update remote old + new
$aPreviousValues = $this->ListPreviousValuesForUpdatedAttributes();
$sPreviousRemoteObjectKey = $aPreviousValues[$sExtKeyWithMirrorLinkAttCode];
$oPreviousRemoteObject = $this->GetRemoteObject($oExtKeyWithMirrorLinkAttDef, $sPreviousRemoteObjectKey, true);
if (false === is_null($oPreviousRemoteObject)) {
$this->CheckRemotePhpConstraintOnObject('remove', $oPreviousRemoteObject, $sAttCodeMirrorLink, false);
}
$this->CheckRemotePhpConstraintOnObject('add', $oRemoteObject, $sAttCodeMirrorLink, false);
$sPreviousTargetObjectKey = $aPreviousValues[$sExtKeyWithMirrorLinkAttCode];
$oPreviousTargetObject = static::GetObjectIfNotInCRUDStack($sTargetObjectClass, $sPreviousTargetObjectKey);
$this->CheckToWriteForSingleTargetObject_Internal('remove', $oPreviousTargetObject, $sAttCodeMirrorLink, false);
$this->CheckToWriteForSingleTargetObject_Internal('add', $oTargetObject, $sAttCodeMirrorLink, false);
} else {
$this->CheckRemotePhpConstraintOnObject('modify', $oRemoteObject, $sAttCodeMirrorLink, false); // we need to update remote with current lnk instance
$this->CheckToWriteForSingleTargetObject_Internal('modify', $oTargetObject, $sAttCodeMirrorLink, false); // we need to update remote with current lnk instance
}
}
}
}
private function CheckRemotePhpConstraintOnObject(string $sAction, DBObject $oRemoteObject, string $sAttCodeMirrorLink, bool $bIsCheckToDelete): void
private function CheckToWriteForSingleTargetObject_Internal(string $sAction, ?DBObject $oTargetObject, string $sAttCodeMirrorLink, bool $bIsCheckToDelete): void
{
$this->LogCRUDDebug(__METHOD__, "action: $sAction ".get_class($oRemoteObject).'::'.$oRemoteObject->GetKey()." ($sAttCodeMirrorLink)");
if (is_null($oTargetObject)) {
return;
}
/** @var \ormLinkSet $oRemoteValue */
$oRemoteValue = $oRemoteObject->Get($sAttCodeMirrorLink);
$this->LogCRUDDebug(__METHOD__, "action: $sAction ".get_class($oTargetObject).'::'.$oTargetObject->GetKey()." ($sAttCodeMirrorLink)");
/** @var \ormLinkSet $oTargetValue */
$oTargetValue = $oTargetObject->Get($sAttCodeMirrorLink);
switch ($sAction) {
case 'add':
$oRemoteValue->AddItem($this);
$oTargetValue->AddItem($this);
break;
case 'remove':
$oRemoteValue->RemoveItem($this->GetKey());
$oTargetValue->RemoveItem($this->GetKey());
break;
case 'modify':
$oRemoteValue->ModifyItem($this);
$oTargetValue->ModifyItem($this);
break;
}
$oRemoteObject->Set($sAttCodeMirrorLink, $oRemoteValue);
[$bCheckStatus, $aCheckIssues, $bSecurityIssue] = $oRemoteObject->CheckToWrite();
$oTargetObject->Set($sAttCodeMirrorLink, $oTargetValue);
[$bCheckStatus, $aCheckIssues, $bSecurityIssue] = $oTargetObject->CheckToWrite();
if (false === $bCheckStatus) {
if ($bIsCheckToDelete) {
$this->m_aDeleteIssues = array_merge($this->m_aDeleteIssues ?? [], $aCheckIssues);
@@ -2610,9 +2580,9 @@ abstract class DBObject implements iDisplay
}
$this->m_bSecurityIssue = $this->m_bSecurityIssue || $bSecurityIssue;
}
$aRemoteCheckWarnings = $oRemoteObject->GetCheckWarnings();
if (is_array($aRemoteCheckWarnings)) {
$this->m_aCheckWarnings = array_merge($this->m_aCheckWarnings ?? [], $aRemoteCheckWarnings);
$aTargetCheckWarnings = $oTargetObject->GetCheckWarnings();
if (is_array($aTargetCheckWarnings)) {
$this->m_aCheckWarnings = array_merge($this->m_aCheckWarnings ?? [], $aTargetCheckWarnings);
}
}
@@ -2657,7 +2627,7 @@ abstract class DBObject implements iDisplay
$this->DoCheckToWrite();
$oKPI->ComputeStatsForExtension($this, 'DoCheckToWrite');
$this->CheckPhpConstraint();
$this->CheckToWriteForTargetObjects();
if (count($this->m_aCheckIssues) == 0)
{
@@ -2754,7 +2724,7 @@ abstract class DBObject implements iDisplay
*
* an array of displayable error is added in {@see DBObject::$m_aDeleteIssues}
*
* @internal
* @internal
*
* @param \DeletionPlan $oDeletionPlan
*
@@ -2819,8 +2789,14 @@ abstract class DBObject implements iDisplay
*/
public function CheckToDelete(&$oDeletionPlan)
{
$this->MakeDeletionPlan($oDeletionPlan);
$oDeletionPlan->ComputeResults();
$this->AddCurrentObjectInCrudStack('DELETE');
try {
$this->MakeDeletionPlan($oDeletionPlan);
$oDeletionPlan->ComputeResults();
}
finally {
$this->RemoveCurrentObjectInCrudStack();
}
return (!$oDeletionPlan->FoundStopper());
}
@@ -2872,7 +2848,7 @@ abstract class DBObject implements iDisplay
{
// The value is a scalar, the comparison must be 100% strict
if($this->m_aOrigValues[$sAtt] !== $proposedValue)
{
{
//echo "$sAtt:<pre>\n";
//var_dump($this->m_aOrigValues[$sAtt]);
//var_dump($proposedValue);
@@ -2994,7 +2970,7 @@ abstract class DBObject implements iDisplay
/**
* Used only by insert, Meant to be overloaded
*
*
* @overwritable-hook You can extend this method in order to provide your own logic.
*/
protected function OnObjectKeyReady()
@@ -3102,7 +3078,7 @@ abstract class DBObject implements iDisplay
// fields in first array, values in the second
$aFieldsToWrite = array();
$aValuesToWrite = array();
if (!empty($this->m_iKey) && ($this->m_iKey >= 0))
{
// Add it to the list of fields to write
@@ -3111,7 +3087,7 @@ abstract class DBObject implements iDisplay
}
$aHierarchicalKeys = array();
foreach(MetaModel::ListAttributeDefs($sTableClass) as $sAttCode=>$oAttDef) {
// Skip this attribute if not defined in this table
if ((!MetaModel::IsAttributeOrigin($sTableClass, $sAttCode) && !$oAttDef->CopyOnAllTables())
@@ -3121,7 +3097,7 @@ abstract class DBObject implements iDisplay
$aAttColumns = $oAttDef->GetSQLValues($this->m_aCurrValues[$sAttCode]);
foreach($aAttColumns as $sColumn => $sValue)
{
$aFieldsToWrite[] = "`$sColumn`";
$aFieldsToWrite[] = "`$sColumn`";
$aValuesToWrite[] = CMDBSource::Quote($sValue);
}
if ($oAttDef->IsHierarchicalKey())
@@ -3145,7 +3121,7 @@ abstract class DBObject implements iDisplay
self::$m_aBulkInsertCols[$sClass][$sTable] = implode(', ', $aFieldsToWrite);
}
self::$m_aBulkInsertItems[$sClass][$sTable][] = '('.implode (', ', $aValuesToWrite).')';
$iNewKey = 999999; // TODO - compute next id....
}
else
@@ -3230,7 +3206,7 @@ abstract class DBObject implements iDisplay
// fields in first array, values in the second
$aFieldsToWrite = array();
$aValuesToWrite = array();
if (!empty($this->m_iKey) && ($this->m_iKey >= 0))
{
// Add it to the list of fields to write
@@ -3265,7 +3241,7 @@ abstract class DBObject implements iDisplay
$aAttColumns = $oAttDef->GetSQLValues($value);
foreach($aAttColumns as $sColumn => $sValue)
{
$aFieldsToWrite[] = "`$sColumn`";
$aFieldsToWrite[] = "`$sColumn`";
$aValuesToWrite[] = CMDBSource::Quote($sValue);
}
if ($oAttDef->IsHierarchicalKey())
@@ -3496,7 +3472,7 @@ abstract class DBObject implements iDisplay
* @throws \MySQLException
* @throws \OQLException
*/
public function PostInsertActions(): void
protected function PostInsertActions(): void
{
$this->FireEventAfterWrite([], true);
$oKPI = new ExecutionKPI();
@@ -3522,7 +3498,7 @@ abstract class DBObject implements iDisplay
$this->ActivateOnMentionTriggers(true);
// - Trigger for object pointing to the current object
$this->TriggerOnRemoteObjectUpdate();
$this->ActivateOnObjectUpdateTriggersForTargetObjects();
}
/**
@@ -3550,7 +3526,7 @@ abstract class DBObject implements iDisplay
$this->RecordObjCreation();
return $ret;
}
/**
* This function is automatically called after cloning an object with the "clone" PHP language construct
* The purpose of this method is to reset the appropriate attributes of the object in
@@ -3815,7 +3791,7 @@ abstract class DBObject implements iDisplay
* @throws \MySQLException
* @throws \OQLException
*/
public function PostUpdateActions(array $aChanges): void
protected function PostUpdateActions(array $aChanges): void
{
$this->FireEventAfterWrite($aChanges, false);
$oKPI = new ExecutionKPI();
@@ -3823,10 +3799,10 @@ abstract class DBObject implements iDisplay
$oKPI->ComputeStatsForExtension($this, 'AfterUpdate');
// - TriggerOnObjectUpdate
$this->TriggerOnObjectUpdate($this);
$this->ActivateOnObjectUpdateTriggers($this);
// - Trigger for object pointing to the current object
$this->TriggerOnRemoteObjectUpdate();
$this->ActivateOnObjectUpdateTriggersForTargetObjects();
$sClass = get_class($this);
if (MetaModel::HasLifecycle($sClass))
@@ -3874,15 +3850,19 @@ abstract class DBObject implements iDisplay
/**
* @param \DBObject $oObject
* @param array|null $aAttributes
*
* @return void
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
* @throws \OQLException
*/
private function TriggerOnObjectUpdate(DBObject $oObject): void
private function ActivateOnObjectUpdateTriggers(?DBObject $oObject, array $aAttributes = null): void
{
if (is_null($oObject)) {
return;
}
// - TriggerOnObjectUpdate
$aClassList = MetaModel::EnumParentClasses(get_class($oObject), ENUM_PARENT_CLASSES_ALL);
$aParams = array('class_list' => $aClassList);
@@ -3891,7 +3871,7 @@ abstract class DBObject implements iDisplay
while ($oTrigger = $oSet->Fetch()) {
/** @var \TriggerOnObjectUpdate $oTrigger */
try {
$oTrigger->DoActivate($oObject->ToArgs());
$oTrigger->DoActivateForSpecificAttributes($oObject->ToArgs(), $aAttributes);
}
catch (Exception $e) {
$oTrigger->LogException($e, $oObject);
@@ -4225,7 +4205,7 @@ abstract class DBObject implements iDisplay
$oKPI->ComputeStatsForExtension($this, 'AfterDelete');
// - Trigger for object pointing to the current object
$this->TriggerOnRemoteObjectUpdate();
$this->ActivateOnObjectUpdateTriggersForTargetObjects();
$this->m_bIsInDB = false;
$this->LogCRUDExit(__METHOD__);
@@ -4240,7 +4220,7 @@ abstract class DBObject implements iDisplay
* First, checks if the object can be deleted regarding database integrity.
* If the answer is yes, it performs any required cleanup (delete other objects or reset external keys) in addition to the object
* deletion.
*
*
* @api
*
* @param \DeletionPlan $oDeletionPlan Do not use: aims at dealing with recursion
@@ -4259,9 +4239,7 @@ abstract class DBObject implements iDisplay
public function DBDelete(&$oDeletionPlan = null)
{
$this->LogCRUDEnter(__METHOD__);
$this->AddCurrentObjectInCrudStack('DELETE');
try {
static $iLoopTimeLimit = null;
if ($iLoopTimeLimit == null) {
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
@@ -4269,17 +4247,15 @@ abstract class DBObject implements iDisplay
if (is_null($oDeletionPlan)) {
$oDeletionPlan = new DeletionPlan();
}
$this->MakeDeletionPlan($oDeletionPlan);
$oDeletionPlan->ComputeResults();
if ($oDeletionPlan->FoundStopper()) {
if (false === $this->CheckToDelete($oDeletionPlan)) {
$aIssues = $oDeletionPlan->GetIssues();
$this->LogCRUDError(__METHOD__, ' Errors: '.implode(', ', $aIssues));
throw new DeleteException('Found issue(s)', array('target_class' => get_class($this), 'target_id' => $this->GetKey(), 'issues' => implode(', ', $aIssues)));
}
// Getting and setting time limit are not symetric:
// Getting and setting time limit are not symmetric:
// www.php.net/manual/fr/function.set-time-limit.php#72305
$iPreviousTimeLimit = ini_get('max_execution_time');
@@ -4320,7 +4296,6 @@ abstract class DBObject implements iDisplay
set_time_limit(intval($iPreviousTimeLimit));
} finally {
$this->LogCRUDExit(__METHOD__);
$this->RemoveCurrentObjectInCrudStack();
}
return $oDeletionPlan;
@@ -4629,7 +4604,7 @@ abstract class DBObject implements iDisplay
*
* @api
*
*/
*/
public function Reset($sAttCode)
{
$this->Set($sAttCode, $this->GetDefaultValue($sAttCode));
@@ -4641,7 +4616,7 @@ abstract class DBObject implements iDisplay
* Suitable for use as a lifecycle action
*
* @api
*/
*/
public function Copy($sDestAttCode, $sSourceAttCode)
{
$oTypeValueToCopy = MetaModel::GetAttributeDef(get_class($this), $sSourceAttCode);
@@ -4971,7 +4946,7 @@ abstract class DBObject implements iDisplay
{
throw new CoreException("Unknown attribute '$sExtKeyAttCode' for the class ".get_class($this));
}
$oKeyAttDef = MetaModel::GetAttributeDef(get_class($this), $sExtKeyAttCode);
if (!$oKeyAttDef instanceof AttributeExternalKey)
{
@@ -4989,14 +4964,14 @@ abstract class DBObject implements iDisplay
$ret = $oRemoteObj->GetForTemplate($sRemoteAttCode);
}
}
else
else
{
switch($sPlaceholderAttCode)
{
case 'id':
$ret = $this->GetKey();
break;
case 'name()':
$ret = $this->GetName();
break;
@@ -5183,7 +5158,7 @@ abstract class DBObject implements iDisplay
if ($oOwner)
{
$sLinkSetOwnerClass = get_class($oOwner);
$oMyChangeOp = MetaModel::NewObject($sChangeOpClass);
$oMyChangeOp->Set("objclass", $sLinkSetOwnerClass);
$oMyChangeOp->Set("objkey", $iLinkSetOwnerId);
@@ -5210,7 +5185,7 @@ abstract class DBObject implements iDisplay
{
/** @var \AttributeLinkedSet $oLinkSet */
if (($oLinkSet->GetTrackingLevel() & LINKSET_TRACKING_LIST) == 0) continue;
$iLinkSetOwnerId = $this->Get($sExtKeyAttCode);
$oMyChangeOp = $this->PrepareChangeOpLinkSet($iLinkSetOwnerId, $oLinkSet, 'CMDBChangeOpSetAttributeLinksAddRemove');
if ($oMyChangeOp)
@@ -5428,9 +5403,9 @@ abstract class DBObject implements iDisplay
$this->m_aDeleteIssues = array(); // Ok
$this->FireEventCheckToDelete($oDeletionPlan);
$this->DoCheckToDelete($oDeletionPlan);
$this->CheckPhpConstraint(true);
$this->CheckToWriteForTargetObjects(true);
$oDeletionPlan->SetDeletionIssues($this, $this->m_aDeleteIssues, $this->m_bSecurityIssue);
$aDependentObjects = $this->GetReferencingObjects(true /* allow all data */);
// Getting and setting time limit are not symmetric:
@@ -5612,7 +5587,7 @@ abstract class DBObject implements iDisplay
$aSynchroClasses[] = $sTarget;
}
}
foreach($aSynchroClasses as $sClass)
{
if ($this instanceof $sClass)
@@ -6678,14 +6653,10 @@ abstract class DBObject implements iDisplay
// during insert key is reset from -1 to null
// so we need to handle null values (will give empty string after conversion)
$sConvertedId = (string)$sId;
if (((int)$sId) > 0) {
// When having a class hierarchy, we are saving the leaf class in the stack
$sClass = MetaModel::GetFinalClassName($sClass, $sId);
}
$oRootClass = MetaModel::GetRootClass($sClass);
foreach (self::$m_aCrudStack as $aCrudStackEntry) {
if (($sClass === $aCrudStackEntry['class'])
if (($oRootClass === $aCrudStackEntry['class'])
&& ($sConvertedId === $aCrudStackEntry['id'])) {
return true;
}
@@ -6700,12 +6671,14 @@ abstract class DBObject implements iDisplay
* @param string $sClass
*
* @return bool
* @throws \CoreException
* @since 3.1.0 N°5609
*/
final public static function IsClassCurrentlyInCrud(string $sClass): bool
{
$sRootClass = MetaModel::GetRootClass($sClass);
foreach (self::$m_aCrudStack as $aCrudStackEntry) {
if ($sClass === $aCrudStackEntry['class']) {
if ($sRootClass === $aCrudStackEntry['class']) {
return true;
}
}
@@ -6724,9 +6697,10 @@ abstract class DBObject implements iDisplay
private function AddCurrentObjectInCrudStack(string $sCrudType): void
{
$this->LogCRUDDebug(__METHOD__);
$sRootClass = MetaModel::GetRootClass(get_class($this));
self::$m_aCrudStack[] = [
'type' => $sCrudType,
'class' => get_class($this),
'class' => $sRootClass,
'id' => (string)$this->GetKey(), // GetKey() doesn't have type hinting, so forcing type to avoid getting an int
];
}