Loading preserve_changed.module +1 −1 Original line number Diff line number Diff line Loading @@ -10,6 +10,6 @@ use Drupal\preserve_changed\PreservedChangedItem; /** * Implements hook_field_info_alter(). */ function preserve_changed_field_info_alter(&$info) { function preserve_changed_field_info_alter(array &$info): void { $info['changed']['class'] = PreservedChangedItem::class; } src/PreservedChangedItem.php +7 −3 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ class PreservedChangedItem extends ChangedItem { /** * {@inheritdoc} */ public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) { public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition): array { $properties = parent::propertyDefinitions($field_definition); $properties['preserve'] = DataDefinition::create('boolean') ->setLabel(new TranslatableMarkup('Determines if the changed timestamp should be preserved.')); Loading @@ -25,7 +25,7 @@ class PreservedChangedItem extends ChangedItem { /** * {@inheritdoc} */ public function preSave() { public function preSave(): void { if ($this->preserve) { return; } Loading @@ -34,6 +34,10 @@ class PreservedChangedItem extends ChangedItem { // which is immutable during the tests making it hard to be tested. From // this point forward, we're just copying the content of parent::preSave() // and we're replacing REQUEST_TIME with \Drupal::time()->getRequestTime(). // By doing so, we are able to mock the 'datetime.time' service in tests. // @see \Drupal\preserve_changed_test\TimeMock::getRequestTime() // @todo Replace with a call to parent's method once REQUEST_TIME is removed // from Drupal core. if (!$this->value) { $this->value = \Drupal::time()->getRequestTime(); } Loading @@ -43,7 +47,7 @@ class PreservedChangedItem extends ChangedItem { /** @var \Drupal\Core\Entity\ContentEntityInterface $original */ $original = $entity->original; $langcode = $entity->language()->getId(); if (!$entity->isNew() && $original->hasTranslation($langcode)) { if (!$entity->isNew() && $original && $original->hasTranslation($langcode)) { $original_value = $original->getTranslation($langcode)->get($this->getFieldDefinition()->getName())->value; if ($this->value == $original_value && $entity->hasTranslationChanges()) { $this->value = \Drupal::time()->getRequestTime(); Loading tests/modules/preserve_changed_test/src/Entity/EntityTestChanged.php +0 −9 Original line number Diff line number Diff line Loading @@ -41,13 +41,4 @@ class EntityTestChanged extends EntityTest implements EntityChangedInterface { return $definitions; } /** * {@inheritdoc} */ public function save() { // Ensure a new timestamp. sleep(1); parent::save(); } } tests/modules/preserve_changed_test/src/TimeMock.php 0 → 100644 +37 −0 Original line number Diff line number Diff line <?php namespace Drupal\preserve_changed_test; use Drupal\Component\Datetime\Time; /** * Mocks the original `datetime.time` service class. * * The original \Drupal::time()->getRequestTime() returned value is immutable * during the tests making it hard to be tested. Mocking the ::getRequestTime() * in order to get time deltas as in real life. */ class TimeMock extends Time { /** * Keep track about the last returned time. * * @var int */ protected int $lastTimestamp; /** * {@inheritdoc} */ public function getRequestTime(): int { if (!isset($this->lastTimestamp)) { $this->lastTimestamp = parent::getRequestTime(); } // Increment before returning the value, in order to guarantee different // timestamps each time \Drupal::time()->getRequestTime() is called as, in // tests, the request time is immutable, but we want to simulate different // changed times. return ++$this->lastTimestamp; } } tests/src/Kernel/PreservedChangedItemTest.php +12 −5 Original line number Diff line number Diff line Loading @@ -2,8 +2,10 @@ namespace Drupal\Tests\preserve_changed\Kernel; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\KernelTests\KernelTestBase; use Drupal\preserve_changed_test\Entity\EntityTestChanged; use Drupal\preserve_changed_test\TimeMock; /** * Tests the PreservedChangedItem field item class. Loading @@ -23,18 +25,23 @@ class PreservedChangedItemTest extends KernelTestBase { 'user', ]; /** * {@inheritdoc} */ public function register(ContainerBuilder $container): void { parent::register($container); $container->getDefinition('datetime.time')->setClass(TimeMock::class); } /** * @covers ::preSave */ public function testPreservedChangedItem() { public function testPreservedChangedItem(): void { $this->installEntitySchema('entity_test_changed'); $entity = EntityTestChanged::create([ 'type' => 'page', 'name' => $this->randomString(), // When tests run too fast the first assert will fail so make sure the // initial changed time is somewhere in the past. 'changed' => time() - 100, ]); $entity->save(); $changed = $entity->getChangedTime(); Loading @@ -52,7 +59,7 @@ class PreservedChangedItemTest extends KernelTestBase { $entity->set('name', $this->randomString())->save(); $this->assertEquals($changed, $entity->getChangedTime()); $this->assertSame($changed, $entity->getChangedTime()); } } Loading
preserve_changed.module +1 −1 Original line number Diff line number Diff line Loading @@ -10,6 +10,6 @@ use Drupal\preserve_changed\PreservedChangedItem; /** * Implements hook_field_info_alter(). */ function preserve_changed_field_info_alter(&$info) { function preserve_changed_field_info_alter(array &$info): void { $info['changed']['class'] = PreservedChangedItem::class; }
src/PreservedChangedItem.php +7 −3 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ class PreservedChangedItem extends ChangedItem { /** * {@inheritdoc} */ public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) { public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition): array { $properties = parent::propertyDefinitions($field_definition); $properties['preserve'] = DataDefinition::create('boolean') ->setLabel(new TranslatableMarkup('Determines if the changed timestamp should be preserved.')); Loading @@ -25,7 +25,7 @@ class PreservedChangedItem extends ChangedItem { /** * {@inheritdoc} */ public function preSave() { public function preSave(): void { if ($this->preserve) { return; } Loading @@ -34,6 +34,10 @@ class PreservedChangedItem extends ChangedItem { // which is immutable during the tests making it hard to be tested. From // this point forward, we're just copying the content of parent::preSave() // and we're replacing REQUEST_TIME with \Drupal::time()->getRequestTime(). // By doing so, we are able to mock the 'datetime.time' service in tests. // @see \Drupal\preserve_changed_test\TimeMock::getRequestTime() // @todo Replace with a call to parent's method once REQUEST_TIME is removed // from Drupal core. if (!$this->value) { $this->value = \Drupal::time()->getRequestTime(); } Loading @@ -43,7 +47,7 @@ class PreservedChangedItem extends ChangedItem { /** @var \Drupal\Core\Entity\ContentEntityInterface $original */ $original = $entity->original; $langcode = $entity->language()->getId(); if (!$entity->isNew() && $original->hasTranslation($langcode)) { if (!$entity->isNew() && $original && $original->hasTranslation($langcode)) { $original_value = $original->getTranslation($langcode)->get($this->getFieldDefinition()->getName())->value; if ($this->value == $original_value && $entity->hasTranslationChanges()) { $this->value = \Drupal::time()->getRequestTime(); Loading
tests/modules/preserve_changed_test/src/Entity/EntityTestChanged.php +0 −9 Original line number Diff line number Diff line Loading @@ -41,13 +41,4 @@ class EntityTestChanged extends EntityTest implements EntityChangedInterface { return $definitions; } /** * {@inheritdoc} */ public function save() { // Ensure a new timestamp. sleep(1); parent::save(); } }
tests/modules/preserve_changed_test/src/TimeMock.php 0 → 100644 +37 −0 Original line number Diff line number Diff line <?php namespace Drupal\preserve_changed_test; use Drupal\Component\Datetime\Time; /** * Mocks the original `datetime.time` service class. * * The original \Drupal::time()->getRequestTime() returned value is immutable * during the tests making it hard to be tested. Mocking the ::getRequestTime() * in order to get time deltas as in real life. */ class TimeMock extends Time { /** * Keep track about the last returned time. * * @var int */ protected int $lastTimestamp; /** * {@inheritdoc} */ public function getRequestTime(): int { if (!isset($this->lastTimestamp)) { $this->lastTimestamp = parent::getRequestTime(); } // Increment before returning the value, in order to guarantee different // timestamps each time \Drupal::time()->getRequestTime() is called as, in // tests, the request time is immutable, but we want to simulate different // changed times. return ++$this->lastTimestamp; } }
tests/src/Kernel/PreservedChangedItemTest.php +12 −5 Original line number Diff line number Diff line Loading @@ -2,8 +2,10 @@ namespace Drupal\Tests\preserve_changed\Kernel; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\KernelTests\KernelTestBase; use Drupal\preserve_changed_test\Entity\EntityTestChanged; use Drupal\preserve_changed_test\TimeMock; /** * Tests the PreservedChangedItem field item class. Loading @@ -23,18 +25,23 @@ class PreservedChangedItemTest extends KernelTestBase { 'user', ]; /** * {@inheritdoc} */ public function register(ContainerBuilder $container): void { parent::register($container); $container->getDefinition('datetime.time')->setClass(TimeMock::class); } /** * @covers ::preSave */ public function testPreservedChangedItem() { public function testPreservedChangedItem(): void { $this->installEntitySchema('entity_test_changed'); $entity = EntityTestChanged::create([ 'type' => 'page', 'name' => $this->randomString(), // When tests run too fast the first assert will fail so make sure the // initial changed time is somewhere in the past. 'changed' => time() - 100, ]); $entity->save(); $changed = $entity->getChangedTime(); Loading @@ -52,7 +59,7 @@ class PreservedChangedItemTest extends KernelTestBase { $entity->set('name', $this->randomString())->save(); $this->assertEquals($changed, $entity->getChangedTime()); $this->assertSame($changed, $entity->getChangedTime()); } }