NEW Add extension point to DataObject->hydrate()

This commit is contained in:
Matt Peel 2021-08-09 00:04:42 +12:00 committed by Matt Peel
parent 2eb406dcd3
commit f99ba5d716
4 changed files with 50 additions and 0 deletions

View File

@ -462,6 +462,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
static::class,
DataObjectSchema::INCLUDE_CLASS | DataObjectSchema::DB_ONLY
);
foreach ($fields as $field => $fieldSpec) {
$fieldClass = strtok($fieldSpec, ".");
if (!array_key_exists($field, $record)) {
@ -469,6 +470,21 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
}
}
// Extension point to hydrate additional fields into this object during construction.
// Return an array of field names => raw values from your augmentHydrateFields extension method.
$extendedAdditionalFields = $this->extend('augmentHydrateFields');
foreach ($extendedAdditionalFields as $additionalFields) {
foreach ($additionalFields as $field => $value) {
$this->record[$field] = $value;
// If a corresponding lazy-load field exists, remove it as the value has been provided
$lazyName = $field . '_Lazy';
if (array_key_exists($lazyName, $this->record)) {
unset($this->record[$lazyName]);
}
}
}
$this->original = $this->record;
$this->changed = [];
$this->changeForced = false;

View File

@ -19,6 +19,7 @@ use SilverStripe\ORM\FieldType\DBVarchar;
use SilverStripe\ORM\ManyManyList;
use SilverStripe\ORM\Tests\DataObjectTest\Company;
use SilverStripe\ORM\Tests\DataObjectTest\Player;
use SilverStripe\ORM\Tests\DataObjectTest\Team;
use SilverStripe\ORM\Tests\DataObjectTest\TreeNode;
use SilverStripe\Security\Member;
use SilverStripe\View\ViewableData;
@ -211,6 +212,31 @@ class DataObjectTest extends SapphireTest
$this->assertSame(5, $player->ID);
}
/**
* @see SilverStripe\ORM\Tests\DataObjectTest\Team_Extension
*/
public function testConstructHydratesAugmentedValues()
{
// When creating a DataObject from singleton, DataObject::hydrate() isn't called
$team = new Team([], DataObject::CREATE_SINGLETON);
$this->assertNull($team->CustomHydratedField);
// Similarly, when hydrating by creating a DataObject from nothing, hydrate() isn't called
$team2 = new Team([]);
$id = $team2->write();
$this->assertNull($team2->CustomHydratedField);
// However when rebuilding an object from the database, it is and we can expect our extension to execute
/** @var Team $team3 */
$team3 = Team::get()->byID($id);
$this->assertTrue($team3->CustomHydratedField);
// Also when rebuilding an object in memory, hydrate() is called and our extension should execute
/** @var Team $team4 */
$team4 = $team->newClassInstance(Team::class);
$this->assertTrue($team4->CustomHydratedField);
}
public function testValidObjectsForBaseFields()
{
$obj = new DataObjectTest\ValidatedObject();

View File

@ -12,6 +12,7 @@ use SilverStripe\ORM\ManyManyList;
* @property string DatabaseField
* @property array SalaryCap
* @property string FoundationYear
* @property bool CustomHydratedField
* @method Player Captain()
* @method Player Founder()
* @method Player HasOneRelationship()

View File

@ -23,4 +23,11 @@ class Team_Extension extends DataExtension implements TestOnly
{
return "extended dynamic field";
}
public function augmentHydrateFields()
{
return [
'CustomHydratedField' => true,
];
}
}