diff --git a/core/modules/block_content/src/BlockContentTranslationHandler.php b/core/modules/block_content/src/BlockContentTranslationHandler.php index 612613b376..8b31b4bcfc 100644 --- a/core/modules/block_content/src/BlockContentTranslationHandler.php +++ b/core/modules/block_content/src/BlockContentTranslationHandler.php @@ -5,12 +5,26 @@ use Drupal\block_content\Entity\BlockContentType; use Drupal\Core\Entity\EntityInterface; use Drupal\content_translation\ContentTranslationHandler; +use Drupal\Core\Form\FormStateInterface; /** * Defines the translation handler for custom blocks. */ class BlockContentTranslationHandler extends ContentTranslationHandler { + /** + * {@inheritdoc} + */ + public function entityFormAlter(array &$form, FormStateInterface $form_state, EntityInterface $entity) { + parent::entityFormAlter($form, $form_state, $entity); + + if (isset($form['content_translation'])) { + // Block content entity does not expose the status field. Make content + // translation status field visible instead. + $form['content_translation']['status']['#access'] = TRUE; + } + } + /** * {@inheritdoc} */ diff --git a/core/modules/block_content/tests/src/Functional/BlockContentTranslationUITest.php b/core/modules/block_content/tests/src/Functional/BlockContentTranslationUITest.php index 6fc5f1af01..ba2ed113db 100644 --- a/core/modules/block_content/tests/src/Functional/BlockContentTranslationUITest.php +++ b/core/modules/block_content/tests/src/Functional/BlockContentTranslationUITest.php @@ -122,6 +122,19 @@ protected function getEditValues($values, $langcode, $new = FALSE) { return $edit; } + /** + * {@inheritdoc} + */ + protected function hasMetadataField($field_name) { + $result = parent::hasMetadataField($field_name); + // Block content entities has status field but it does not expose it. + if ($field_name === 'status') { + return FALSE; + } + + return $result; + } + /** * {@inheritdoc} */ diff --git a/core/modules/comment/src/CommentTranslationHandler.php b/core/modules/comment/src/CommentTranslationHandler.php index a0abe4b710..44ff36cef5 100644 --- a/core/modules/comment/src/CommentTranslationHandler.php +++ b/core/modules/comment/src/CommentTranslationHandler.php @@ -11,21 +11,6 @@ */ class CommentTranslationHandler extends ContentTranslationHandler { - /** - * {@inheritdoc} - */ - public function entityFormAlter(array &$form, FormStateInterface $form_state, EntityInterface $entity) { - parent::entityFormAlter($form, $form_state, $entity); - - if (isset($form['content_translation'])) { - // We do not need to show these values on comment forms: they inherit the - // basic comment property values. - $form['content_translation']['status']['#access'] = FALSE; - $form['content_translation']['name']['#access'] = FALSE; - $form['content_translation']['created']['#access'] = FALSE; - } - } - /** * {@inheritdoc} */ @@ -41,7 +26,6 @@ public function entityFormEntityBuild($entity_type, EntityInterface $entity, arr $translation = &$form_state->getValue('content_translation'); /** @var \Drupal\comment\CommentInterface $entity */ $translation['status'] = $entity->isPublished(); - $translation['name'] = $entity->getAuthorName(); } parent::entityFormEntityBuild($entity_type, $entity, $form, $form_state); } diff --git a/core/modules/content_translation/src/ContentTranslationHandler.php b/core/modules/content_translation/src/ContentTranslationHandler.php index 0fef1bed47..afdd661bc0 100644 --- a/core/modules/content_translation/src/ContentTranslationHandler.php +++ b/core/modules/content_translation/src/ContentTranslationHandler.php @@ -455,6 +455,8 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, En '#default_value' => $status, '#description' => $description, '#disabled' => !$enabled, + // Show status field if it is not natively provided by the entity type. + '#access' => !$this->hasPublishedStatus(), ]; $translate = !$new_translation && $metadata->isOutdated(); @@ -501,6 +503,7 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, En '#validate_reference' => FALSE, '#maxlength' => 60, '#description' => t('Leave blank for %anonymous.', ['%anonymous' => \Drupal::config('user.settings')->get('anonymous')]), + '#access' => !$this->hasAuthor(), ]; $date = $new_translation ? REQUEST_TIME : $metadata->getCreatedTime(); @@ -510,6 +513,7 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, En '#maxlength' => 25, '#description' => t('Format: %time. The date format is YYYY-MM-DD and %timezone is the time zone offset from UTC. Leave blank to use the time of form submission.', ['%time' => format_date(REQUEST_TIME, 'custom', 'Y-m-d H:i:s O'), '%timezone' => format_date(REQUEST_TIME, 'custom', 'O')]), '#default_value' => $new_translation || !$date ? '' : format_date($date, 'custom', 'Y-m-d H:i:s O'), + '#access' => !$this->hasCreatedTime(), ]; $form['#process'][] = [$this, 'entityFormSharedElements']; diff --git a/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php b/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php index ae833955db..b0368b9007 100644 --- a/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php +++ b/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php @@ -11,6 +11,7 @@ use Drupal\language\Entity\ConfigurableLanguage; use Drupal\Component\Render\FormattableMarkup; use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait; +use Drupal\Tests\content_translation\Functional\ContentTranslationMetadataTrait; /** * Tests the Content Translation UI. @@ -21,6 +22,7 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase { use AssertPageCacheContextsAndTagsTrait; + use ContentTranslationMetadataTrait; /** * The id of the entity being translated. @@ -52,6 +54,15 @@ */ protected $defaultCacheContexts = ['languages:language_interface', 'theme', 'url.query_args:_wrapper_format', 'user.permissions']; + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->fieldStorageDefinitions = $this->container->get('entity_field.manager')->getFieldStorageDefinitions($this->entityTypeId); + } + /** * Tests the basic translation UI. */ @@ -291,8 +302,9 @@ protected function doTestPublishedStatus() { foreach ($this->langcodes as $index => $langcode) { if ($index > 0) { $url = $entity->urlInfo('edit-form', ['language' => ConfigurableLanguage::load($langcode)]); - $edit = ['content_translation[status]' => FALSE]; - $this->drupalPostForm($url, $edit, $this->getFormSubmitAction($entity, $langcode)); + $this->drupalGet($url); + $edit = $this->getMetadataValueAndAssertNoField('status', FALSE); + $this->drupalPostForm(NULL, $edit, $this->getFormSubmitAction($entity, $langcode)); $storage = $this->container->get('entity_type.manager') ->getStorage($this->entityTypeId); $storage->resetCache([$this->entityId]); @@ -319,16 +331,15 @@ protected function doTestAuthoringInfo() { // Post different authoring information for each translation. foreach ($this->langcodes as $index => $langcode) { $user = $this->drupalCreateUser(); + $url = $entity->urlInfo('edit-form', ['language' => ConfigurableLanguage::load($langcode)]); + $this->drupalGet($url); $values[$langcode] = [ 'uid' => $user->id(), 'created' => REQUEST_TIME - mt_rand(0, 1000), ]; - $edit = [ - 'content_translation[uid]' => $user->getUsername(), - 'content_translation[created]' => format_date($values[$langcode]['created'], 'custom', 'Y-m-d H:i:s O'), - ]; - $url = $entity->urlInfo('edit-form', ['language' => ConfigurableLanguage::load($langcode)]); - $this->drupalPostForm($url, $edit, $this->getFormSubmitAction($entity, $langcode)); + $edit = $this->getMetadataValueAndAssertNoField('uid', $user->getUsername()); + $edit += $this->getMetadataValueAndAssertNoField('created', format_date($values[$langcode]['created'], 'custom', 'Y-m-d H:i:s O')); + $this->drupalPostForm(NULL, $edit, $this->getFormSubmitAction($entity, $langcode)); } $storage = $this->container->get('entity_type.manager') @@ -343,12 +354,10 @@ protected function doTestAuthoringInfo() { // Try to post non valid values and check that they are rejected. $langcode = 'en'; - $edit = [ - // User names have by default length 8. - 'content_translation[uid]' => $this->randomMachineName(12), - 'content_translation[created]' => '19/11/1978', - ]; - $this->drupalPostForm($entity->urlInfo('edit-form'), $edit, $this->getFormSubmitAction($entity, $langcode)); + $this->drupalGet($entity->urlInfo('edit-form')); + $edit = $this->getMetadataValueAndAssertNoField('uid', $this->randomMachineName(12)); + $edit += $this->getMetadataValueAndAssertNoField('created', '19/11/1978'); + $this->drupalPostForm(NULL, $edit, $this->getFormSubmitAction($entity, $langcode)); $this->assertTrue($this->xpath('//div[contains(@class, "error")]//ul'), 'Invalid values generate a list of form errors.'); $metadata = $this->manager->getTranslationMetadata($entity->getTranslation($langcode)); $this->assertEqual($metadata->getAuthor()->id(), $values[$langcode]['uid'], 'Translation author correctly kept.'); diff --git a/core/modules/content_translation/tests/src/Functional/ContentTranslationMetadataTrait.php b/core/modules/content_translation/tests/src/Functional/ContentTranslationMetadataTrait.php new file mode 100644 index 0000000000..7a6b550355 --- /dev/null +++ b/core/modules/content_translation/tests/src/Functional/ContentTranslationMetadataTrait.php @@ -0,0 +1,74 @@ +hasMetadataField($field_name)) { + $edit["content_translation[$field_name]"] = $field_value; + if ($field_name === 'created') { + $edit['content_translation[created]'] = $field_value; + if (is_numeric($field_value)) { + $edit["content_translation[created]"] = format_date($field_value, 'custom', 'Y-m-d H:i:s O'); + } + // Assert there is no native meta data field. + $this->assertNoField('created[0][value][date]'); + } + else if ($this->entityTypeId !== 'user') { + $this->assertNoField($field_name); + } + } + else { + if ($field_name === 'created') { + $edit['created[0][value][date]'] = $field_value; + if (is_numeric($field_value)) { + $edit['created[0][value][date]'] = format_date($field_value, 'custom', 'Y-m-d'); + $edit['created[0][value][time]'] = format_date($field_value, 'custom', 'H:i:s'); + } + } + else { + $edit[$field_name] = $field_value; + } + + // Assert there is no content translation meta data field. + $this->assertNoField("content_translation[$field_name]"); + } + + return $edit; + } + + /** + * Returns whether a given field name exists in the field storage definitions. + * + * @see \Drupal\content_translation\ContentTranslationHandler::checkFieldStorageDefinitionTranslatability + */ + protected function hasMetadataField($field_name) { + $has_metadata_field = array_key_exists($field_name, $this->fieldStorageDefinitions) && $this->fieldStorageDefinitions[$field_name]->isTranslatable(); + // Check if the entity type implements EntityOwnerInterface for uid field. + if ($field_name === 'uid') { + return $has_metadata_field && $this->container->get('entity_type.manager')->getDefinition($this->entityTypeId)->entityClassImplements(EntityOwnerInterface::class); + } + + return $has_metadata_field; + } + +} diff --git a/core/modules/content_translation/tests/src/Functional/ContentTranslationUITestBase.php b/core/modules/content_translation/tests/src/Functional/ContentTranslationUITestBase.php index 7e7bf1f84b..1864f14ef6 100644 --- a/core/modules/content_translation/tests/src/Functional/ContentTranslationUITestBase.php +++ b/core/modules/content_translation/tests/src/Functional/ContentTranslationUITestBase.php @@ -18,6 +18,7 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase { use AssertPageCacheContextsAndTagsTrait; + use ContentTranslationMetadataTrait; /** * The id of the entity being translated. @@ -49,6 +50,15 @@ */ protected $defaultCacheContexts = ['languages:language_interface', 'theme', 'url.query_args:_wrapper_format', 'user.permissions']; + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->fieldStorageDefinitions = $this->container->get('entity_field.manager')->getFieldStorageDefinitions($this->entityTypeId); + } + /** * Tests the basic translation UI. */ @@ -288,8 +298,9 @@ protected function doTestPublishedStatus() { foreach ($this->langcodes as $index => $langcode) { if ($index > 0) { $url = $entity->urlInfo('edit-form', ['language' => ConfigurableLanguage::load($langcode)]); - $edit = ['content_translation[status]' => FALSE]; - $this->drupalPostForm($url, $edit, $this->getFormSubmitAction($entity, $langcode)); + $this->drupalGet($url); + $edit = $this->getMetadataValueAndAssertNoField('status', FALSE); + $this->drupalPostForm(NULL, $edit, $this->getFormSubmitAction($entity, $langcode)); $storage = $this->container->get('entity_type.manager') ->getStorage($this->entityTypeId); $storage->resetCache([$this->entityId]); @@ -316,16 +327,15 @@ protected function doTestAuthoringInfo() { // Post different authoring information for each translation. foreach ($this->langcodes as $index => $langcode) { $user = $this->drupalCreateUser(); + $url = $entity->urlInfo('edit-form', ['language' => ConfigurableLanguage::load($langcode)]); + $this->drupalGet($url); $values[$langcode] = [ 'uid' => $user->id(), 'created' => REQUEST_TIME - mt_rand(0, 1000), ]; - $edit = [ - 'content_translation[uid]' => $user->getUsername(), - 'content_translation[created]' => format_date($values[$langcode]['created'], 'custom', 'Y-m-d H:i:s O'), - ]; - $url = $entity->urlInfo('edit-form', ['language' => ConfigurableLanguage::load($langcode)]); - $this->drupalPostForm($url, $edit, $this->getFormSubmitAction($entity, $langcode)); + $edit = $this->getMetadataValueAndAssertNoField('uid', $user->getUsername()); + $edit += $this->getMetadataValueAndAssertNoField('created', $values[$langcode]['created']); + $this->drupalPostForm(NULL, $edit, $this->getFormSubmitAction($entity, $langcode)); } $storage = $this->container->get('entity_type.manager') @@ -340,12 +350,10 @@ protected function doTestAuthoringInfo() { // Try to post non valid values and check that they are rejected. $langcode = 'en'; - $edit = [ - // User names have by default length 8. - 'content_translation[uid]' => $this->randomMachineName(12), - 'content_translation[created]' => '19/11/1978', - ]; - $this->drupalPostForm($entity->urlInfo('edit-form'), $edit, $this->getFormSubmitAction($entity, $langcode)); + $this->drupalGet($entity->urlInfo('edit-form')); + $edit = $this->getMetadataValueAndAssertNoField('uid', $this->randomMachineName(12)); + $edit += $this->getMetadataValueAndAssertNoField('created', '19/11/1978'); + $this->drupalPostForm(NULL, $edit, $this->getFormSubmitAction($entity, $langcode)); $this->assertTrue($this->xpath('//div[contains(@class, "error")]//ul'), 'Invalid values generate a list of form errors.'); $metadata = $this->manager->getTranslationMetadata($entity->getTranslation($langcode)); $this->assertEqual($metadata->getAuthor()->id(), $values[$langcode]['uid'], 'Translation author correctly kept.'); diff --git a/core/modules/node/src/NodeTranslationHandler.php b/core/modules/node/src/NodeTranslationHandler.php index 8b69645d1f..ab50e5e550 100644 --- a/core/modules/node/src/NodeTranslationHandler.php +++ b/core/modules/node/src/NodeTranslationHandler.php @@ -17,14 +17,6 @@ class NodeTranslationHandler extends ContentTranslationHandler { public function entityFormAlter(array &$form, FormStateInterface $form_state, EntityInterface $entity) { parent::entityFormAlter($form, $form_state, $entity); - if (isset($form['content_translation'])) { - // We do not need to show these values on node forms: they inherit the - // basic node property values. - $form['content_translation']['status']['#access'] = FALSE; - $form['content_translation']['name']['#access'] = FALSE; - $form['content_translation']['created']['#access'] = FALSE; - } - $form_object = $form_state->getFormObject(); $form_langcode = $form_object->getFormLangcode($form_state); $translations = $entity->getTranslationLanguages(); diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulChanged.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulChanged.php index dd3da09dce..23938dff08 100644 --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulChanged.php +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulChanged.php @@ -23,7 +23,7 @@ * "route_provider" = { * "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider", * }, - * "translation" = "Drupal\content_translation\ContentTranslationHandler", + * "translation" = "Drupal\entity_test\EntityTestTranslationHandler", * "views_data" = "Drupal\views\EntityViewsData" * }, * base_table = "entity_test_mul_changed", @@ -55,6 +55,12 @@ class EntityTestMulChanged extends EntityTestMul implements EntityChangedInterfa public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = parent::baseFieldDefinitions($entity_type); + // Show the created field in the edit form. + $fields['created']->setDisplayOptions('form', [ + 'type' => 'datetime_timestamp', + 'weight' => 10, + ]); + $fields['changed'] = BaseFieldDefinition::create('changed_test') ->setLabel(t('Changed')) ->setDescription(t('The time that the entity was last edited.')) diff --git a/core/modules/system/tests/modules/entity_test/src/EntityTestTranslationHandler.php b/core/modules/system/tests/modules/entity_test/src/EntityTestTranslationHandler.php new file mode 100644 index 0000000000..6d535dc61c --- /dev/null +++ b/core/modules/system/tests/modules/entity_test/src/EntityTestTranslationHandler.php @@ -0,0 +1,25 @@ +hasValue('content_translation')) { + $translation = &$form_state->getValue('content_translation'); + $translation['created'] = format_date($entity->get('created')->value, 'custom', 'Y-m-d H:i:s O'); + } + parent::entityFormEntityBuild($entity_type, $entity, $form, $form_state); + } + +}