This commit is contained in:
Maxime Rainville 2021-08-27 12:06:05 +12:00
commit 89a6d9825e
5 changed files with 61 additions and 0 deletions

View File

@ -5,6 +5,7 @@
- [Features and enhancements](#features-and-enhancements) - [Features and enhancements](#features-and-enhancements)
- [Image lazy loading](#image-lazy-loading) - [Image lazy loading](#image-lazy-loading)
- [Manage your CMS sessions across devices](#session-manager) - [Manage your CMS sessions across devices](#session-manager)
- [Default mail transport upgraded to sendmail](#sendmail)
- [Other new features](#other-features) - [Other new features](#other-features)
- [Bugfixes](#bugfixes) - [Bugfixes](#bugfixes)
@ -68,6 +69,16 @@ If your site has the [symbiote/silverstripe-queuedjobs](https://github.com/symbi
CMS users can review the [Session Manager user help](https://userhelp.silverstripe.org/en/4/managing_your_website/session_manager/) for more information on managing their sessions. CMS users can review the [Session Manager user help](https://userhelp.silverstripe.org/en/4/managing_your_website/session_manager/) for more information on managing their sessions.
### Default mail transport upgraded to sendmail {#sendmail}
Silverstripe CMS provides an API over the top of the [SwiftMailer](http://swiftmailer.org/) PHP library which comes with an extensive list of "transports" for sending mail via different services.
Prior to 4.9.0, Silverstripe CMS 4 defaulted to using the built-in PHP `mail()` command via a deprecated class `Swift_MailTransport`. However, using this layer is less secure and is strongly discouraged.
Installations of Silverstripe CMS setup using silverstripe/installer 4.9.0 or greater default to using the more secure class `Swift_SendmailTransport` which uses a `sendmail` binary.
It's highly recommended that existing Silverstripe CMS installation still using `Swift_MailTransport` upgrade to using `Swift_SendmailTransport` or another available transport, such as `Swift_SmtpTransport`. Details on how to use these classes are available in the [email section](https://docs.silverstripe.org/en/4/developer_guides/email/) of the developer docs.
### Other new features ### Other new features
* [Dot notation support in form fields](https://github.com/silverstripe/silverstripe-framework/pull/9192): Save directly into nested has_one relationships (see [docs](/developer_guides/forms/how_tos/handle_nested_data)). * [Dot notation support in form fields](https://github.com/silverstripe/silverstripe-framework/pull/9192): Save directly into nested has_one relationships (see [docs](/developer_guides/forms/how_tos/handle_nested_data)).

View File

@ -462,6 +462,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
static::class, static::class,
DataObjectSchema::INCLUDE_CLASS | DataObjectSchema::DB_ONLY DataObjectSchema::INCLUDE_CLASS | DataObjectSchema::DB_ONLY
); );
foreach ($fields as $field => $fieldSpec) { foreach ($fields as $field => $fieldSpec) {
$fieldClass = strtok($fieldSpec, "."); $fieldClass = strtok($fieldSpec, ".");
if (!array_key_exists($field, $record)) { 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->original = $this->record;
$this->changed = []; $this->changed = [];
$this->changeForced = false; $this->changeForced = false;

View File

@ -19,6 +19,7 @@ use SilverStripe\ORM\FieldType\DBVarchar;
use SilverStripe\ORM\ManyManyList; use SilverStripe\ORM\ManyManyList;
use SilverStripe\ORM\Tests\DataObjectTest\Company; use SilverStripe\ORM\Tests\DataObjectTest\Company;
use SilverStripe\ORM\Tests\DataObjectTest\Player; use SilverStripe\ORM\Tests\DataObjectTest\Player;
use SilverStripe\ORM\Tests\DataObjectTest\Team;
use SilverStripe\ORM\Tests\DataObjectTest\TreeNode; use SilverStripe\ORM\Tests\DataObjectTest\TreeNode;
use SilverStripe\Security\Member; use SilverStripe\Security\Member;
use SilverStripe\View\ViewableData; use SilverStripe\View\ViewableData;
@ -211,6 +212,31 @@ class DataObjectTest extends SapphireTest
$this->assertSame(5, $player->ID); $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() public function testValidObjectsForBaseFields()
{ {
$obj = new DataObjectTest\ValidatedObject(); $obj = new DataObjectTest\ValidatedObject();

View File

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

View File

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