mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
NEW: Allow DateTime to be immutable (#10125)
* BUG: Datetime modify() returns a new field instance. * PR fixes. * PR fixes.
This commit is contained in:
parent
c6ee8c0b34
commit
3db1435df7
@ -47,6 +47,46 @@ class DBDatetime extends DBDate implements TemplateGlobalProvider
|
||||
*/
|
||||
const ISO_DATETIME_NORMALISED = 'y-MM-dd\'T\'HH:mm:ss';
|
||||
|
||||
/**
|
||||
* Flag idicating if this field is considered immutable
|
||||
* when this is enabled setting the value of this field will return a new field instance
|
||||
* instead updatin the old one
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $immutable = false;
|
||||
|
||||
/**
|
||||
* @param bool $immutable
|
||||
* @return $this
|
||||
*/
|
||||
public function setImmutable(bool $immutable): self
|
||||
{
|
||||
$this->immutable = $immutable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setValue($value, $record = null, $markChanged = true)
|
||||
{
|
||||
if ($this->immutable) {
|
||||
// This field is set as immutable so we have to create a new field instance
|
||||
// instead of just updating the value
|
||||
$field = clone $this;
|
||||
|
||||
return $field
|
||||
// This field will inherit the immutable status but we have to disable it before setting the value
|
||||
// to avoid recursion
|
||||
->setImmutable(false)
|
||||
// Update the value so the new field contains the desired value
|
||||
->setValue($value, $record, $markChanged)
|
||||
// Return the immutable flag to the correct state
|
||||
->setImmutable(true);
|
||||
}
|
||||
|
||||
return parent::setValue($value, $record, $markChanged);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the standard localised date
|
||||
*
|
||||
@ -170,13 +210,11 @@ class DBDatetime extends DBDate implements TemplateGlobalProvider
|
||||
*/
|
||||
public static function now()
|
||||
{
|
||||
$time = self::$mock_now ? self::$mock_now->Value : time();
|
||||
|
||||
/** @var DBDatetime $now */
|
||||
$now = null;
|
||||
if (self::$mock_now) {
|
||||
$now = DBField::create_field('Datetime', self::$mock_now->Value);
|
||||
} else {
|
||||
$now = DBField::create_field('Datetime', time());
|
||||
}
|
||||
$now = DBField::create_field('Datetime', $time);
|
||||
|
||||
return $now;
|
||||
}
|
||||
|
||||
|
@ -499,6 +499,24 @@ class DatetimeFieldTest extends SapphireTest
|
||||
$field->setTimezone('Pacific/Auckland');
|
||||
}
|
||||
|
||||
public function testModifyReturnNewField(): void
|
||||
{
|
||||
$globalStateNow = '2020-01-01 00:00:00';
|
||||
DBDatetime::set_mock_now($globalStateNow);
|
||||
|
||||
// Suppose we need to know the current time in our feature, we store it in a variable
|
||||
// Make this field immutable, so future modifications don't apply to any other object references
|
||||
$now = DBDatetime::now()->setImmutable(true);
|
||||
|
||||
// Later in the code we want to know the time value for 10 days later, we can reuse our $now variable
|
||||
$later = $now->modify('+ 10 days')->Rfc2822();
|
||||
|
||||
// Our expectation is that this code should not apply the change to our
|
||||
// $now variable declared earlier in the code
|
||||
$this->assertSame('2020-01-11 00:00:00', $later, 'We expect to get a future datetime');
|
||||
$this->assertSame($globalStateNow, $now->Rfc2822(), 'We expect to get the current datetime');
|
||||
}
|
||||
|
||||
protected function getMockForm()
|
||||
{
|
||||
/** @skipUpgrade */
|
||||
|
Loading…
Reference in New Issue
Block a user