Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NEW Add extension point to DataObject->hydrate() #10047

Merged
merged 1 commit into from
Aug 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/ORM/DataObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -462,13 +462,29 @@ private function hydrate(array $record, bool $mustHaveID)
static::class,
DataObjectSchema::INCLUDE_CLASS | DataObjectSchema::DB_ONLY
);

foreach ($fields as $field => $fieldSpec) {
$fieldClass = strtok($fieldSpec, ".");
if (!array_key_exists($field, $record)) {
$this->record[$field . '_Lazy'] = $fieldClass;
}
}

// 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;
Expand Down
26 changes: 26 additions & 0 deletions tests/php/ORM/DataObjectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
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;
Expand Down Expand Up @@ -211,6 +212,31 @@ public function testConstructAcceptsValues()
$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();
Expand Down
1 change: 1 addition & 0 deletions tests/php/ORM/DataObjectTest/Team.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* @property string DatabaseField
* @property array SalaryCap
* @property string FoundationYear
* @property bool CustomHydratedField
* @method Player Captain()
* @method Player Founder()
* @method Player HasOneRelationship()
Expand Down
7 changes: 7 additions & 0 deletions tests/php/ORM/DataObjectTest/Team_Extension.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,11 @@ public function getExtendedDynamicField()
{
return "extended dynamic field";
}

public function augmentHydrateFields()
{
return [
'CustomHydratedField' => true,
];
}
}