Issue #2755525 by hchonov: Invoke field methods first on the current entity translation

8.2.x
Alex Pott 2016-07-29 15:20:09 +01:00
parent 28356f4e9f
commit e0af75558c
4 changed files with 176 additions and 0 deletions

View File

@ -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

View File

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

View File

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

View File

@ -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.');
}
}