diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php
index 7157eff45..b64ccd5b3 100644
--- a/application/cmdbabstract.class.inc.php
+++ b/application/cmdbabstract.class.inc.php
@@ -2132,7 +2132,7 @@ HTML;
$sDisplayValueForHtml = utils::EscapeHtml($sDisplayValue);
$sHTMLValue = <<
-
+
{$sValidationSpan}{$sReloadSpan}
HTML;
break;
@@ -5716,4 +5716,130 @@ JS
'AttributeOneWayPassword',
);
}
+
+ /**
+ * @return void
+ * @throws \CoreException
+ */
+ final protected function EventInsertRequested()
+ {
+ $sClass = get_class($this);
+ if ($sClass == 'UserRequest') {
+ IssueLog::Debug("CRUD: DBInsert $sClass::0 Requested", LogChannels::DM_CRUD);
+ }
+ $this->FireEvent(EVENT_SERVICE_DB_INSERT_REQUESTED);
+ }
+
+ /**
+ * @return void
+ * @throws \CoreException
+ */
+ final protected function EventInsertBefore()
+ {
+ $sClass = get_class($this);
+ if ($sClass == 'UserRequest') {
+ IssueLog::Debug("CRUD: DBInsert $sClass::0 About to write in DB", LogChannels::DM_CRUD);
+ }
+ $this->FireEvent(EVENT_SERVICE_DB_BEFORE_INSERT);
+ }
+
+ /**
+ * @return void
+ * @throws \CoreException
+ */
+ final protected function EventInsertAfter()
+ {
+ $sClass = get_class($this);
+ if ($sClass == 'UserRequest') {
+ IssueLog::Debug("CRUD: $sClass::{$this->m_iKey} Inserted in DB", LogChannels::DM_CRUD);
+ }
+
+ $this->FireEvent(EVENT_SERVICE_DB_AFTER_INSERT);
+ }
+
+ /**
+ * @param array $aEventData
+ *
+ * @return void
+ * @throws \CoreException
+ */
+ final protected function EventCheckToWrite(array $aEventData)
+ {
+ $this->FireEvent(EVENT_SERVICE_DB_CHECK_TO_WRITE, $aEventData);
+ }
+
+ /**
+ * @param array $aEventData
+ *
+ * @return void
+ * @throws \CoreException
+ */
+ final protected function EventCheckToDelete(array $aEventData)
+ {
+ $this->FireEvent(EVENT_SERVICE_DB_CHECK_TO_DELETE, $aEventData);
+ }
+
+ /**
+ * @return void
+ * @throws \CoreException
+ */
+ final protected function EventUpdateRequested()
+ {
+ $sClass = get_class($this);
+ $sKey = $sClass.'::'.$this->GetKey();
+ if ($sClass == 'UserRequest') {
+ IssueLog::Debug("CRUD: DBUpdate $sKey Requested", LogChannels::DM_CRUD);
+ }
+
+ $this->FireEvent(EVENT_SERVICE_DB_UPDATE_REQUESTED);
+ }
+
+ /**
+ * @return void
+ * @throws \CoreException
+ */
+ final protected function EventUpdateBefore()
+ {
+ $sClass = get_class($this);
+ $sKey = $sClass.'::'.$this->GetKey();
+ if ($sClass == 'UserRequest') {
+ IssueLog::Debug("CRUD: DBUpdate $sKey About to be written in DB", LogChannels::DM_CRUD);
+ }
+ $this->FireEvent(EVENT_SERVICE_DB_BEFORE_UPDATE);
+ }
+
+ /**
+ * @param array $aEventData
+ *
+ * @return void
+ * @throws \CoreException
+ */
+ final protected function EventUpdateAfter(array $aEventData)
+ {
+ $sClass = get_class($this);
+ $sKey = $sClass.'::'.$this->GetKey();
+ if ($sClass == 'UserRequest') {
+ IssueLog::Debug("CRUD: DBUpdate $sKey Updated", LogChannels::DM_CRUD);
+ }
+ $this->FireEvent(EVENT_SERVICE_DB_AFTER_UPDATE, $aEventData);
+ }
+
+ /**
+ * @return void
+ * @throws \CoreException
+ */
+ final protected function EventDeleteBefore()
+ {
+ $this->FireEvent(EVENT_SERVICE_DB_BEFORE_DELETE);
+ }
+
+ /**
+ * @return void
+ * @throws \CoreException
+ */
+ final protected function EventDeleteAfter()
+ {
+ $this->FireEvent(EVENT_SERVICE_DB_AFTER_DELETE);
+ }
+
}
diff --git a/application/datamodel.application.xml b/application/datamodel.application.xml
index 418736f0b..1fc532c58 100644
--- a/application/datamodel.application.xml
+++ b/application/datamodel.application.xml
@@ -186,7 +186,219 @@
-
+
+ An object insert in the database has been requested. All changes to the object will be persisted automatically.
+ DBObject::OnInsert
+
+
+ The object inserted
+ DBObject
+
+
+ Debug string
+ string
+
+
+
+
+ An object is about to be inserted in the database (no change possible)
+ DBObject::OnInsert
+
+
+ The object inserted
+ DBObject
+
+
+ Debug string
+ string
+
+
+
+
+ An object has been inserted into the database (but not reloaded). All changes to the object will be persisted automatically.
+ DBObject::AfterInsert
+
+
+ The object inserted
+ DBObject
+
+
+ Debug string
+ string
+
+
+
+
+ An object update has been requested. All changes to the object will be persisted automatically.
+ DBObject::OnUpdate, DBObject::DoComputeValues
+
+
+ The object updated
+ DBObject
+
+
+ Debug string
+ string
+
+
+
+
+ An object is about to be updated in the database (no change possible)
+ DBObject::OnUpdate
+
+
+ The object updated
+ DBObject
+
+
+ Debug string
+ string
+
+
+
+
+ An object has been updated into the database and reloaded. All changes to the object will be persisted automatically.
+ DBObject::AfterUpdate
+
+
+ The object updated
+ DBObject
+
+
+ Debug string
+ string
+
+
+
+
+ An object is about to be deleted in the database
+ DBObject::OnDelete
+
+
+ The object deleted
+ DBObject
+
+
+ Debug string
+ string
+
+
+
+
+ An object has been deleted into the database
+ DBObject::AfterDelete
+
+
+ The object deleted
+ DBObject
+
+
+ Debug string
+ string
+
+
+
+
+ A stimulus is about to be applied to an object
+
+
+ The object where the stimulus is to be applied
+ DBObject
+
+
+ Current stimulus applied
+ string
+
+
+ Debug string
+ string
+
+
+
+
+ A stimulus has been applied to an object
+
+
+ The object where the stimulus has been applied
+ DBObject
+
+
+ Current stimulus applied
+ string
+
+
+ Debug string
+ string
+
+
+
+
+ An object has been re-loaded from the database
+
+
+ The object re-loaded
+ DBObject
+
+
+ Debug string
+ string
+
+
+
+
+ Check an object before it is written into the database (no change possible)
+ cmdbAbstractObject::DoCheckToWrite
+
+
+ The object to check
+ DBObject
+
+
+ Array of strings where all the errors found during the object checking are added
+ array
+
+
+ Debug string
+ string
+
+
+
+
+ Check an object before it is deleted from the database (no change possible)
+ cmdbAbstractObject::DoCheckToDelete
+
+
+ The object to check
+ DBObject
+
+
+ Array of strings where all the errors found during the object checking are added
+ array
+
+
+ Debug string
+ string
+
+
+
+
+ A document has been downloaded from the GUI
+
+
+ The object containing the document
+ DBObject
+
+
+ The document downloaded
+ ormDocument
+
+
+ Debug string
+ string
+
+
+
+
The current page is completely displayed
Class hierarchy of the displayed page
@@ -200,7 +412,7 @@
-
+
Inform the listeners about the connection states
diff --git a/core/datamodel.core.xml b/core/datamodel.core.xml
index 95f6140ee..b24417e75 100644
--- a/core/datamodel.core.xml
+++ b/core/datamodel.core.xml
@@ -11,234 +11,6 @@
-
-
- An object insert in the database has been requested. All changes to the object will be persisted automatically.
- DBObject::OnInsert
-
-
- The object inserted
- DBObject
-
-
- Debug string
- string
-
-
-
-
- An object is about to be inserted in the database (no change possible)
- DBObject::OnInsert
-
-
- The object inserted
- DBObject
-
-
- Debug string
- string
-
-
-
-
- An object has been inserted into the database (but not reloaded). All changes to the object will be persisted automatically.
- DBObject::AfterInsert
-
-
- The object inserted
- DBObject
-
-
- Debug string
- string
-
-
-
-
- An object update has been requested. All changes to the object will be persisted automatically.
- DBObject::OnUpdate, DBObject::DoComputeValues
-
-
- The object updated
- DBObject
-
-
- Debug string
- string
-
-
-
-
- An object is about to be updated in the database (no change possible)
- DBObject::OnUpdate
-
-
- The object updated
- DBObject
-
-
- Debug string
- string
-
-
-
-
- An object has been updated into the database (but not reloaded). All changes to the object will be LOST.
- DBObject::AfterUpdate
-
-
- The object updated
- DBObject
-
-
- Debug string
- string
-
-
-
-
- An object has been updated into the database and reloaded. All changes to the object will be persisted automatically.
- DBObject::AfterUpdate
-
-
- The object updated
- DBObject
-
-
- Debug string
- string
-
-
-
-
- An object is about to be deleted in the database
- DBObject::OnDelete
-
-
- The object deleted
- DBObject
-
-
- Debug string
- string
-
-
-
-
- An object has been deleted into the database
- DBObject::AfterDelete
-
-
- The object deleted
- DBObject
-
-
- Debug string
- string
-
-
-
-
- A stimulus is about to be applied to an object
-
-
- The object where the stimulus is to be applied
- DBObject
-
-
- Current stimulus applied
- string
-
-
- Debug string
- string
-
-
-
-
- A stimulus has been applied to an object
-
-
- The object where the stimulus has been applied
- DBObject
-
-
- Current stimulus applied
- string
-
-
- Debug string
- string
-
-
-
-
- An object has been re-loaded from the database
-
-
- The object re-loaded
- DBObject
-
-
- Debug string
- string
-
-
-
-
- Check an object before it is written into the database (no change possible)
- cmdbAbstractObject::DoCheckToWrite
-
-
- The object to check
- DBObject
-
-
- Array of strings where all the errors found during the object checking are added
- array
-
-
- Debug string
- string
-
-
-
-
- Check an object before it is deleted from the database (no change possible)
- cmdbAbstractObject::DoCheckToDelete
-
-
- The object to check
- DBObject
-
-
- Array of strings where all the errors found during the object checking are added
- array
-
-
- Debug string
- string
-
-
-
-
- A document has been downloaded from the GUI
-
-
- The object containing the document
- DBObject
-
-
- The document downloaded
- ormDocument
-
-
- Debug string
- string
-
-
-
-
diff --git a/core/dbobject.class.php b/core/dbobject.class.php
index ce3a35e0b..2fc3dd91b 100644
--- a/core/dbobject.class.php
+++ b/core/dbobject.class.php
@@ -150,6 +150,8 @@ abstract class DBObject implements iDisplay
*/
protected $m_sEventUniqId = '';
+ private static $aUpdateReentrance = [];
+
/**
* DBObject constructor.
@@ -2341,7 +2343,7 @@ abstract class DBObject implements iDisplay
$oKPI = new ExecutionKPI();
$this->DoCheckToWrite();
- $this->FireEvent(EVENT_SERVICE_DB_CHECK_TO_WRITE, array('error_messages' => &$this->m_aCheckIssues));
+ $this->EventCheckToWrite(['error_messages' => &$this->m_aCheckIssues]);
$oKPI->ComputeStats('CheckToWrite', get_class($this));
if (count($this->m_aCheckIssues) == 0)
{
@@ -2370,7 +2372,7 @@ abstract class DBObject implements iDisplay
{
$this->m_aDeleteIssues = array(); // Ok
- $this->FireEvent(EVENT_SERVICE_DB_CHECK_TO_DELETE, array('error_messages' => &$this->m_aDeleteIssues));
+ $this->EventCheckToDelete(['error_messages' => &$this->m_aDeleteIssues]);
if ($this->InSyncScope())
{
@@ -2810,16 +2812,12 @@ abstract class DBObject implements iDisplay
}
$sClass = get_class($this);
- if ($sClass == 'UserRequest') {
- IssueLog::Debug("CRUD: DBInsert $sClass::0 Requested", LogChannels::DM_CRUD);
- }
-
$sRootClass = MetaModel::GetRootClass($sClass);
// Ensure the update of the values (we are accessing the data directly)
$this->DoComputeValues();
$this->OnInsert();
- $this->FireEvent(EVENT_SERVICE_DB_INSERT_REQUESTED);
+ $this->EventInsertRequested();
if ($this->m_iKey < 0)
{
@@ -2864,10 +2862,7 @@ abstract class DBObject implements iDisplay
}
}
- if ($sClass == 'UserRequest') {
- IssueLog::Debug("CRUD: DBInsert $sClass::0 About to write in DB", LogChannels::DM_CRUD);
- }
- $this->FireEvent(EVENT_SERVICE_DB_BEFORE_INSERT);
+ $this->EventInsertBefore();
$iTransactionRetry = 1;
$bIsTransactionEnabled = MetaModel::GetConfig()->Get('db_core_transactions_enabled');
@@ -2953,15 +2948,11 @@ abstract class DBObject implements iDisplay
$this->AfterInsert();
- if ($sClass == 'UserRequest') {
- IssueLog::Debug("CRUD: $sClass::{$this->m_iKey} Inserted in DB", LogChannels::DM_CRUD);
- }
-
// Prevent DBUpdate at this point (reentrance protection)
$sClass = get_class($this);
$sClassKey = $sClass.'::'.$this->m_iKey;
self::$aUpdateReentrance[$sClassKey] = true;
- $this->FireEvent(EVENT_SERVICE_DB_AFTER_INSERT_NO_RELOAD);
+ $this->EventInsertAfter();
unset(self::$aUpdateReentrance[$sClassKey]);
// Activate any existing trigger
@@ -3171,7 +3162,6 @@ abstract class DBObject implements iDisplay
$this->m_iKey = self::GetNextTempId(get_class($this));
}
- private static $aUpdateReentrance = [];
/**
* Update an object in DB
@@ -3194,9 +3184,6 @@ abstract class DBObject implements iDisplay
// Protect against reentrance (e.g. cascading the update of ticket logs)
$sClass = get_class($this);
$sKey = $sClass.'::'.$this->GetKey();
- if ($sClass == 'UserRequest') {
- IssueLog::Debug("CRUD: DBUpdate $sKey Requested", LogChannels::DM_CRUD);
- }
if (array_key_exists($sKey, self::$aUpdateReentrance))
{
@@ -3231,7 +3218,7 @@ abstract class DBObject implements iDisplay
}
}
$this->OnUpdate();
- $this->FireEvent(EVENT_SERVICE_DB_UPDATE_REQUESTED);
+ $this->EventUpdateRequested();
// Freeze the changes at this point
$this->InitPreviousValuesForUpdatedAttributes();
@@ -3295,10 +3282,7 @@ abstract class DBObject implements iDisplay
$iIsTransactionRetryDelay = MetaModel::GetConfig()->Get('db_core_transactions_retry_delay_ms');
$iTransactionRetry = $iTransactionRetryCount;
}
- if ($sClass == 'UserRequest') {
- IssueLog::Debug("CRUD: DBUpdate $sKey About to be written in DB", LogChannels::DM_CRUD);
- }
- $this->FireEvent(EVENT_SERVICE_DB_BEFORE_UPDATE);
+ $this->EventUpdateBefore();
while ($iTransactionRetry > 0)
{
try
@@ -3451,15 +3435,11 @@ abstract class DBObject implements iDisplay
$this->AfterUpdate();
- if ($sClass == 'UserRequest') {
- IssueLog::Debug("CRUD: DBUpdate $sKey Updated", LogChannels::DM_CRUD);
- }
- $this->FireEvent(EVENT_SERVICE_DB_AFTER_UPDATE_NO_RELOAD, ['changes' => $aChanges]);
// Reload to get the external/computed attributes
$this->Reload(true);
- $this->FireEvent(EVENT_SERVICE_DB_AFTER_UPDATE, ['changes' => $aChanges]);
+ $this->EventUpdateAfter(['changes' => $aChanges]);
}
catch (Exception $e)
{
@@ -3681,7 +3661,7 @@ abstract class DBObject implements iDisplay
}
$this->OnDelete();
- $this->FireEvent(EVENT_SERVICE_DB_BEFORE_DELETE);
+ $this->EventDeleteBefore();
// Activate any existing trigger
$sClass = get_class($this);
@@ -3792,7 +3772,7 @@ abstract class DBObject implements iDisplay
}
$this->AfterDelete();
- $this->FireEvent(EVENT_SERVICE_DB_AFTER_DELETE);
+ $this->EventDeleteAfter();
$this->m_bIsInDB = false;
@@ -5859,5 +5839,45 @@ abstract class DBObject implements iDisplay
}
EventService::FireEvent(new EventData($sEvent, $aEventSources, $aEventData));
}
+
+ protected function EventInsertRequested()
+ {
+ }
+
+ protected function EventInsertBefore()
+ {
+ }
+
+ protected function EventInsertAfter()
+ {
+ }
+
+ protected function EventCheckToWrite(array $aEventData)
+ {
+ }
+
+ protected function EventCheckToDelete(array $aEventData)
+ {
+ }
+
+ protected function EventUpdateRequested()
+ {
+ }
+
+ protected function EventUpdateBefore()
+ {
+ }
+
+ protected function EventUpdateAfter(array $aEventData)
+ {
+ }
+
+ protected function EventDeleteBefore()
+ {
+ }
+
+ protected function EventDeleteAfter()
+ {
+ }
}
diff --git a/datamodels/2.x/itop-attachments/datamodel.itop-attachments.xml b/datamodels/2.x/itop-attachments/datamodel.itop-attachments.xml
index afaf41963..676a912a3 100755
--- a/datamodels/2.x/itop-attachments/datamodel.itop-attachments.xml
+++ b/datamodels/2.x/itop-attachments/datamodel.itop-attachments.xml
@@ -203,6 +203,40 @@
}
}]]>
+
+ /**
+ * @param array $aEventData
+ *
+ * @return void
+ * @throws \CoreException
+ */
+
+ false
+ protected
+ Overload-ExNihilo
+ FireEvent(EVENT_SERVICE_ATTACHMENT_AFTER_UPDATE);
+ }
+]]>
+
+
+ /**
+ * @return void
+ * @throws \CoreException
+ */
+
+ false
+ protected
+ Overload-ExNihilo
+ FireEvent(EVENT_SERVICE_ATTACHMENT_AFTER_DELETE);
+ }
+]]>
+
@@ -253,4 +287,38 @@
+
+
+ An attachment has been updated in database.
+ Attachment::AfterUpdate
+
+
+ The object updated
+ DBObject
+
+
+ Array of all the attributes changed
+ array
+
+
+ Debug string
+ string
+
+
+
+
+ An attachment has been deleted from database.
+ Attachment::AfterDelete
+
+
+ The object deleted
+ DBObject
+
+
+ Debug string
+ string
+
+
+
+
diff --git a/setup/compiler.class.inc.php b/setup/compiler.class.inc.php
index fdd8a9a3d..517947f72 100644
--- a/setup/compiler.class.inc.php
+++ b/setup/compiler.class.inc.php
@@ -1076,7 +1076,7 @@ EOF
$oDescription = $oEvent->GetOptionalElement('description');
$sDescription = empty($oDescription) ? '' : $oDescription->GetText('');
- $sConstant = 'EVENT_SERVICE_'.strtoupper(SetupUtils::FromCamelCase($sName));
+ $sConstant = $sName;
$sOutput = "define('$sConstant', '$sName');\n";
$sOutput .= "Combodo\iTop\Service\EventService::RegisterEvent('$sName', '$sDescription', '$sModuleName');\n";
diff --git a/setup/setuputils.class.inc.php b/setup/setuputils.class.inc.php
index f595f0101..d0b1e2c56 100644
--- a/setup/setuputils.class.inc.php
+++ b/setup/setuputils.class.inc.php
@@ -2174,20 +2174,6 @@ JS
return $aOptionalExtensions;
}
-
-
- public static function FromCamelCase($sInput) {
- $sPattern = '!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!';
- preg_match_all($sPattern, $sInput, $aMatches);
- $aRet = $aMatches[0];
- foreach ($aRet as &$sMatch) {
- $sMatch = $sMatch == strtoupper($sMatch) ?
- strtolower($sMatch) :
- lcfirst($sMatch);
- }
- return implode('_', $aRet);
- }
-
}
/**
diff --git a/test/ItopDataTestCase.php b/test/ItopDataTestCase.php
index 460c27139..ee4e44f3d 100644
--- a/test/ItopDataTestCase.php
+++ b/test/ItopDataTestCase.php
@@ -27,8 +27,10 @@ namespace Combodo\iTop\Test\UnitTest;
*/
use ArchivedObjectException;
-use CMDBSource;
use CMDBObject;
+use CMDBSource;
+use Combodo\iTop\Service\EventData;
+use Combodo\iTop\Service\EventService;
use Contact;
use DBObject;
use DBObjectSet;
@@ -73,6 +75,9 @@ class ItopDataTestCase extends ItopTestCase
// For cleanup
private $aCreatedObjects = array();
+ // Counts
+ public $aReloadCount = [];
+
const USE_TRANSACTION = true;
const CREATE_TEST_ORG = false;
@@ -96,6 +101,8 @@ class ItopDataTestCase extends ItopTestCase
{
$this->CreateTestOrganization();
}
+
+ EventService::RegisterListener(EVENT_SERVICE_DB_OBJECT_RELOAD, [$this, 'CountObjectReload']);
}
/**
@@ -790,6 +797,44 @@ class ItopDataTestCase extends ItopTestCase
$this->iTestOrgId = $oOrg->GetKey();
}
+ public function ResetReloadCount()
+ {
+ $this->aReloadCount = [];
+ }
+
+ public function DebugReloadCount($sMsg, $bResetCount = true)
+ {
+ $iTotalCount = 0;
+ $aTotalPerClass = [];
+ foreach ($this->aReloadCount as $sClass => $aCountByKeys) {
+ $iClassCount = 0;
+ foreach ($aCountByKeys as $iCount) {
+ $iClassCount += $iCount;
+ }
+ $iTotalCount += $iClassCount;
+ $aTotalPerClass[$sClass] = $iClassCount;
+ }
+ $this->debug("$sMsg - $iTotalCount reload(s)");
+ foreach ($this->aReloadCount as $sClass => $aCountByKeys) {
+ $this->debug(" $sClass => $aTotalPerClass[$sClass] reload(s)");
+ foreach ($aCountByKeys as $sKey => $iCount) {
+ $this->debug(" $sClass::$sKey => $iCount");
+ }
+ }
+ if ($bResetCount) {
+ $this->ResetReloadCount();
+ }
+ }
+
+ public function CountObjectReload(EventData $oData)
+ {
+ $oObject = $oData->Get('object');
+ $sClass = get_class($oObject);
+ $sKey = $oObject->GetKey();
+ $iCount = $this->aReloadCount[$sClass][$sKey] ?? 0;
+ $this->aReloadCount[$sClass][$sKey] = 1 + $iCount;
+ }
+
/**
* Assert that a series of operations will trigger a given number of MySL queries
*
@@ -811,7 +856,7 @@ class ItopDataTestCase extends ItopTestCase
}
else
{
- // Otherwise PHP Unit will consider that no assertion has been made
+ // Otherwise, PHP Unit will consider that no assertion has been made
static::assertTrue(true);
}
}
diff --git a/test/core/DBObjectTest.php b/test/core/DBObjectTest.php
index 0a861ee63..7c0341b62 100644
--- a/test/core/DBObjectTest.php
+++ b/test/core/DBObjectTest.php
@@ -243,6 +243,51 @@ class DBObjectTest extends ItopDataTestCase
});
}
+ /**
+ * @covers DBObject::NewObject
+ * @covers DBObject::Get
+ * @covers DBObject::Set
+ */
+ public function testInsertNoReloadAttributeRefresh_ExternalKeysAndFields()
+ {
+ $this->ResetReloadCount();
+
+ static::assertDBQueryCount(0, function() use (&$oObject){
+ $oObject = \MetaModel::NewObject('Person', array('name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2));
+ });
+ static::assertDBQueryCount(49, function() use (&$oObject) {
+ $oObject->DBInsertNoReload();
+ });
+ $this->DebugReloadCount("Person::DBInsertNoReload()");
+
+ static::assertDBQueryCount(3, function() use (&$oObject){
+ static::assertEquals('Demo', $oObject->Get('org_id_friendlyname'));
+ static::assertEquals('Grenoble', $oObject->Get('location_id_friendlyname'));
+ });
+ $this->DebugReloadCount("Get('org_id_friendlyname') and Get('location_id_friendlyname')");
+
+ // External key given as an id
+ static::assertDBQueryCount(1, function() use (&$oObject){
+ $oObject->Set('org_id', 2);
+ static::assertEquals('IT Department', $oObject->Get('org_id_friendlyname'));
+ });
+ $this->DebugReloadCount("Set('org_id', 2) andGet('org_id_friendlyname')");
+
+ // External key given as an object
+ static::assertDBQueryCount(1, function() use (&$oBordeaux){
+ $oBordeaux = \MetaModel::GetObject('Location', 1);
+ });
+ $this->DebugReloadCount("GetObject('Location', 1)");
+
+ static::assertDBQueryCount(5, function() use (&$oBordeaux, &$oObject){
+ $oObject->Set('location_id', $oBordeaux);
+ static::assertEquals('IT Department', $oObject->Get('org_id_friendlyname'));
+ static::assertEquals('IT Department', $oObject->Get('org_name'));
+ static::assertEquals('Bordeaux', $oObject->Get('location_id_friendlyname'));
+ });
+ $this->DebugReloadCount("Set('location_id',...) Get('org_id_friendlyname') Get('org_name') Get('location_id_friendlyname')");
+ }
+
public function testSetExtKeyUnsetDependentAttribute()
{
$oObject = \MetaModel::NewObject('Person', array('name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2));