Issue #2755525 by hchonov: Invoke field methods first on the current entity translation
parent
28356f4e9f
commit
e0af75558c
|
@ -436,6 +436,13 @@ abstract class ContentEntityStorageBase extends EntityStorageBase implements Con
|
|||
$result = [];
|
||||
$args = array_slice(func_get_args(), 2);
|
||||
$langcodes = array_keys($entity->getTranslationLanguages());
|
||||
// Ensure that the field method is invoked as first on the current entity
|
||||
// translation and then on all other translations.
|
||||
$current_entity_langcode = $entity->language()->getId();
|
||||
if (reset($langcodes) != $current_entity_langcode) {
|
||||
$langcodes = array_diff($langcodes, [$current_entity_langcode]);
|
||||
array_unshift($langcodes, $current_entity_langcode);
|
||||
}
|
||||
foreach ($langcodes as $langcode) {
|
||||
$translation = $entity->getTranslation($langcode);
|
||||
// For non translatable fields, there is only one field object instance
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\entity_test\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
|
||||
/**
|
||||
* Defines the test entity class.
|
||||
*
|
||||
* @ContentEntityType(
|
||||
* id = "entity_test_field_methods",
|
||||
* label = @Translation("Test entity - data table"),
|
||||
* handlers = {
|
||||
* "view_builder" = "Drupal\entity_test\EntityTestViewBuilder",
|
||||
* "access" = "Drupal\entity_test\EntityTestAccessControlHandler",
|
||||
* "form" = {
|
||||
* "default" = "Drupal\entity_test\EntityTestForm",
|
||||
* "delete" = "Drupal\entity_test\EntityTestDeleteForm"
|
||||
* },
|
||||
* "translation" = "Drupal\content_translation\ContentTranslationHandler",
|
||||
* "views_data" = "Drupal\views\EntityViewsData",
|
||||
* "route_provider" = {
|
||||
* "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
|
||||
* },
|
||||
* },
|
||||
* base_table = "entity_test_field_methods",
|
||||
* data_table = "entity_test_field_methods_property",
|
||||
* admin_permission = "administer entity_test content",
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
* "bundle" = "type",
|
||||
* "label" = "name",
|
||||
* "langcode" = "langcode",
|
||||
* },
|
||||
* )
|
||||
*/
|
||||
class EntityTestFieldMethods extends EntityTestMul {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
|
||||
$fields = parent::baseFieldDefinitions($entity_type);
|
||||
|
||||
$fields['test_invocation_order'] = BaseFieldDefinition::create('auto_incrementing_test')
|
||||
->setLabel(t('Test field method invocation order.'))
|
||||
->setTranslatable(TRUE);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\entity_test\Plugin\Field\FieldType;
|
||||
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\IntegerItem;
|
||||
|
||||
/**
|
||||
* Defines the 'field_method_invocation_order_test' entity field type.
|
||||
*
|
||||
* @FieldType(
|
||||
* id = "auto_incrementing_test",
|
||||
* label = @Translation("Auto incrementing test field item"),
|
||||
* description = @Translation("An entity field designed to test the field method invocation order."),
|
||||
* category = @Translation("Number"),
|
||||
* no_ui = TRUE,
|
||||
* )
|
||||
*/
|
||||
class AutoIncrementingTestItem extends IntegerItem {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preSave() {
|
||||
parent::preSave();
|
||||
$this->value = static::getIncrementedFieldValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an incremented field value.
|
||||
*
|
||||
* @return int
|
||||
* The incremented field value.
|
||||
*/
|
||||
private static function getIncrementedFieldValue() {
|
||||
$current_value = &drupal_static(__METHOD__, 0);
|
||||
return ++$current_value;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
/**
|
||||
* Tests correct field method invocation order.
|
||||
*
|
||||
* @group Entity
|
||||
*/
|
||||
class ContentEntityFieldMethodInvocationOrderTest extends EntityKernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['language', 'system', 'entity_test'];
|
||||
|
||||
/**
|
||||
* The EntityTest entity type storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\ContentEntityStorageInterface
|
||||
*/
|
||||
protected $entityTestFieldMethodsStorage;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Enable an additional language.
|
||||
ConfigurableLanguage::createFromLangcode('de')->save();
|
||||
ConfigurableLanguage::createFromLangcode('fr')->save();
|
||||
|
||||
$this->installEntitySchema('entity_test_field_methods');
|
||||
|
||||
$this->entityTestFieldMethodsStorage = $this->entityManager->getStorage('entity_test_field_methods');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests correct field method invocation order.
|
||||
*/
|
||||
public function testFieldMethodInvocationOrder() {
|
||||
|
||||
// Create a test entity.
|
||||
$entity = $this->entityTestFieldMethodsStorage->create([
|
||||
'name' => $this->randomString(),
|
||||
'langcode' => 'de',
|
||||
]);
|
||||
$entity->save();
|
||||
|
||||
$entity->addTranslation('fr')
|
||||
->save();
|
||||
|
||||
// Reset the current value of the test field.
|
||||
foreach (['de', 'fr'] as $langcode) {
|
||||
$entity->getTranslation($langcode)->test_invocation_order->value = 0;
|
||||
}
|
||||
$entity->getTranslation('de')
|
||||
->save();
|
||||
$this->assertTrue($entity->getTranslation('fr')->test_invocation_order->value > $entity->getTranslation('de')->test_invocation_order->value, 'The field presave method has been invoked in the correct entity translation order.');
|
||||
|
||||
// Reset the current value of the test field.
|
||||
foreach (['de', 'fr'] as $langcode) {
|
||||
$entity->getTranslation($langcode)->test_invocation_order->value = 0;
|
||||
}
|
||||
$entity->getTranslation('fr')
|
||||
->save();
|
||||
$this->assertTrue($entity->getTranslation('de')->test_invocation_order->value > $entity->getTranslation('fr')->test_invocation_order->value, 'The field presave method has been invoked in the correct entity translation order.');
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue