Commit 226c9c2f authored by Claudiu Cristea's avatar Claudiu Cristea
Browse files

Issue #3222827 by claudiu.cristea, idebr, Tomefa: Error: Call to a member...

Issue #3222827 by claudiu.cristea, idebr, Tomefa: Error: Call to a member function hasTranslation() on null
parent bf0b1338
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
}
+7 −3
Original line number Diff line number Diff line
@@ -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.'));
@@ -25,7 +25,7 @@ class PreservedChangedItem extends ChangedItem {
  /**
   * {@inheritdoc}
   */
  public function preSave() {
  public function preSave(): void {
    if ($this->preserve) {
      return;
    }
@@ -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();
    }
@@ -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();
+0 −9
Original line number Diff line number Diff line
@@ -41,13 +41,4 @@ class EntityTestChanged extends EntityTest implements EntityChangedInterface {
    return $definitions;
  }

  /**
   * {@inheritdoc}
   */
  public function save() {
    // Ensure a new timestamp.
    sleep(1);
    parent::save();
  }

}
+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;
  }

}
+12 −5
Original line number Diff line number Diff line
@@ -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.
@@ -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();
@@ -52,7 +59,7 @@ class PreservedChangedItemTest extends KernelTestBase {

    $entity->set('name', $this->randomString())->save();

    $this->assertEquals($changed, $entity->getChangedTime());
    $this->assertSame($changed, $entity->getChangedTime());
  }

}