NEW: Allow DateTime to be immutable (#10125)

* BUG: Datetime modify() returns a new field instance.
* PR fixes.
* PR fixes.
This commit is contained in:
Mojmir Fendek 2022-01-18 09:41:11 +13:00 committed by GitHub
parent c6ee8c0b34
commit 3db1435df7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 6 deletions

View File

@ -47,6 +47,46 @@ class DBDatetime extends DBDate implements TemplateGlobalProvider
*/ */
const ISO_DATETIME_NORMALISED = 'y-MM-dd\'T\'HH:mm:ss'; 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 * Returns the standard localised date
* *
@ -170,13 +210,11 @@ class DBDatetime extends DBDate implements TemplateGlobalProvider
*/ */
public static function now() public static function now()
{ {
$time = self::$mock_now ? self::$mock_now->Value : time();
/** @var DBDatetime $now */ /** @var DBDatetime $now */
$now = null; $now = DBField::create_field('Datetime', $time);
if (self::$mock_now) {
$now = DBField::create_field('Datetime', self::$mock_now->Value);
} else {
$now = DBField::create_field('Datetime', time());
}
return $now; return $now;
} }

View File

@ -499,6 +499,24 @@ class DatetimeFieldTest extends SapphireTest
$field->setTimezone('Pacific/Auckland'); $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() protected function getMockForm()
{ {
/** @skipUpgrade */ /** @skipUpgrade */