diff --git a/core/core.libraries.yml b/core/core.libraries.yml index ce12db5..c4ca44c 100644 --- a/core/core.libraries.yml +++ b/core/core.libraries.yml @@ -203,6 +203,15 @@ drupal.dropbutton: - core/drupalSettings - core/jquery.once +drupal.entity-form: + version: VERSION + js: + misc/entity-form.js: {} + dependencies: + - core/jquery + - core/drupal + - core/drupal.form + drupal.form: version: VERSION js: diff --git a/core/lib/Drupal/Core/Entity/Form/RevisionableContentEntityForm.php b/core/lib/Drupal/Core/Entity/Form/RevisionableContentEntityForm.php new file mode 100644 index 0000000..063e90d --- /dev/null +++ b/core/lib/Drupal/Core/Entity/Form/RevisionableContentEntityForm.php @@ -0,0 +1,219 @@ +entityTypeBundleInfo = $entity_type_bundle_info; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.manager'), + $container->get('entity_type.bundle.info') + ); + } + + /** + * {@inheritdoc} + */ + protected function prepareEntity() { + parent::prepareEntity(); + + // Hide the current revision log message in UI. + if (!$this->entity->isNew()) { + $this->entity->setRevisionLogMessage(NULL); + } + } + + /** + * Returns the bundle entity of the entity, or NULL if there is none. + * + * @return \Drupal\Core\Entity\EntityInterface|null + * The bundle entity. + */ + protected function getBundleEntity() { + if ($bundle_entity_type = $this->entity->getEntityType()->getBundleEntityType()) { + return $this->entityTypeManager->getStorage($bundle_entity_type)->load($this->entity->bundle()); + } + return NULL; + } + + /** + * {@inheritdoc} + */ + public function form(array $form, FormStateInterface $form_state) { + + // Advanced tab must be the first, because other fields rely on that. + $form['advanced'] = [ + '#type' => 'vertical_tabs', + '#weight' => 99, + ]; + + $form = parent::form($form, $form_state); + + $entity_type = $this->entity->getEntityType(); + + if ($this->operation == 'edit') { + + $bundle_info = $this->entityTypeBundleInfo->getBundleInfo($entity_type->id()); + if ($bundle_info[$this->entity->bundle()]) { + $form['#title'] = $this->t('Edit @bundle_label @label', [ + '@bundle_label' => $bundle_info[$this->entity->bundle()]['label'], + '@label' => $this->entity->label(), + ]); + } + else { + $form['#title'] = $this->t('Edit @label', [ + '@label' => $this->entity->label(), + ]); + } + } + + $new_revision_default = FALSE; + $bundle_entity = $this->getBundleEntity(); + if ($bundle_entity instanceof RevisionableEntityBundleInterface) { + // Always use the default revision setting. + $new_revision_default = $bundle_entity->shouldCreateNewRevision(); + } + + // Add a log field if the "Create new revision" option is checked, or if the + // current user has the ability to check that option. + $form['revision_information'] = [ + '#type' => 'details', + '#title' => $this->t('Revision information'), + // Open by default when "Create new revision" is checked. + '#open' => $new_revision_default, + '#group' => 'advanced', + '#weight' => 20, + '#access' => $new_revision_default || $this->entity->get($entity_type->getKey('revision'))->access('update'), + '#optional' => TRUE, + '#attributes' => [ + 'class' => ['entity-content-form-revision-information'], + ], + '#attached' => [ + 'library' => ['core/drupal.entity-form'], + ], + ]; + + $form['revision'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Create new revision'), + '#default_value' => $new_revision_default, + '#access' => !$this->entity->isNew() && $this->entity->get($entity_type->getKey('revision'))->access('update'), + '#group' => 'revision_information', + ]; + + // Check the revision log checkbox when the log textarea is filled in. + // This must not happen if "Create new revision" is enabled by default, + // since the state would auto-disable the checkbox otherwise. + if (!$new_revision_default) { + $form['revision']['#states'] = [ + 'checked' => [ + 'textarea[name="revision_log[0][value]"]' => ['empty' => FALSE], + ], + ]; + } + + if (isset($form['revision_log'])) { + $form['revision_log']['#group'] = 'revision_information'; + } + + return $form; + } + + /** + * {@inheritdoc} + * + * Updates the content object by processing the submitted values. + * + * This function can be called by a "Next" button of a wizard to update the + * form state's entity with the current step's values before proceeding to the + * next step. + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + // Build the entity object from the submitted values. + parent::submitForm($form, $form_state); + $entity = $this->entity; + + // Save as a new revision if requested to do so. + if (!$form_state->isValueEmpty('revision')) { + $entity->setNewRevision(); + // If a new revision is created, save the current user as revision author. + $entity->setRevisionUserId(\Drupal::currentUser()->id()); + $entity->setRevisionCreationTime(REQUEST_TIME); + } + else { + $entity->setNewRevision(FALSE); + } + } + + /** + * {@inheritdoc} + */ + public function save(array $form, FormStateInterface $form_state) { + + $insert = $this->entity->isNew(); + $this->entity->save(); + + $context = ['@type' => $this->entity->bundle(), '%info' => $this->entity->label()]; + $logger = $this->logger($this->entity->getEntityTypeId()); + $bundle_entity = $this->getBundleEntity(); + $t_args = ['@type' => $bundle_entity ? $bundle_entity->label() : $this->entity->getEntityType()->getLabel(), '%label' => $this->entity->label()]; + + if ($insert) { + $logger->notice('@type: added %info.', $context); + drupal_set_message($this->t('@type %label has been created.', $t_args)); + } + else { + $logger->notice('@type: updated %info.', $context); + drupal_set_message($this->t('@type %label has been updated.', $t_args)); + } + + if ($this->entity->getEntityType()->hasLinkTemplate('collection')) { + $form_state->setRedirectUrl($this->entity->toUrl('collection')); + } + else { + $form_state->setRedirectUrl($this->entity->toUrl('canonical')); + } + } + +} diff --git a/core/lib/Drupal/Core/Entity/RevisionableEntityBundleInterface.php b/core/lib/Drupal/Core/Entity/RevisionableEntityBundleInterface.php new file mode 100644 index 0000000..caf44f2 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/RevisionableEntityBundleInterface.php @@ -0,0 +1,20 @@ +blockContentStorage = $block_content_storage; - $this->blockContentTypeStorage = $block_content_type_storage; - $this->languageManager = $language_manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - $entity_manager = $container->get('entity.manager'); - return new static( - $entity_manager, - $entity_manager->getStorage('block_content'), - $entity_manager->getStorage('block_content_type'), - $container->get('language_manager') - ); - } - - /** - * Overrides \Drupal\Core\Entity\EntityForm::prepareEntity(). - * - * Prepares the custom block object. - * - * Fills in a few default values, and then invokes - * hook_block_content_prepare() on all modules. - */ - protected function prepareEntity() { - $block = $this->entity; - // Set up default values, if required. - $block_type = $this->blockContentTypeStorage->load($block->bundle()); - if (!$block->isNew()) { - $block->setRevisionLogMessage(NULL); - } - // Always use the default revision setting. - $block->setNewRevision($block_type->shouldCreateNewRevision()); - } - - /** * {@inheritdoc} */ public function form(array $form, FormStateInterface $form_state) { $block = $this->entity; - $account = $this->currentUser(); + + $form = parent::form($form, $form_state); if ($this->operation == 'edit') { - $form['#title'] = $this->t('Edit custom block %label', array('%label' => $block->label())); + $form['#title'] = $this->t('Edit custom block %label', ['%label' => $block->label()]); } // Override the default CSS class name, since the user-defined custom block // type name in 'TYPE-block-form' potentially clashes with third-party class // names. $form['#attributes']['class'][0] = 'block-' . Html::getClass($block->bundle()) . '-form'; - $form['advanced'] = array( - '#type' => 'vertical_tabs', - '#weight' => 99, - ); - - // Add a log field if the "Create new revision" option is checked, or if the - // current user has the ability to check that option. - $form['revision_information'] = array( - '#type' => 'details', - '#title' => $this->t('Revision information'), - // Open by default when "Create new revision" is checked. - '#open' => $block->isNewRevision(), - '#group' => 'advanced', - '#attributes' => array( - 'class' => array('block-content-form-revision-information'), - ), - '#attached' => array( - 'library' => array('block_content/drupal.block_content'), - ), - '#weight' => 20, - '#access' => $block->isNewRevision() || $account->hasPermission('administer blocks'), - ); - - $form['revision_information']['revision'] = array( - '#type' => 'checkbox', - '#title' => $this->t('Create new revision'), - '#default_value' => $block->isNewRevision(), - '#access' => $account->hasPermission('administer blocks'), - ); - - // Check the revision log checkbox when the log textarea is filled in. - // This must not happen if "Create new revision" is enabled by default, - // since the state would auto-disable the checkbox otherwise. - if (!$block->isNewRevision()) { - $form['revision_information']['revision']['#states'] = array( - 'checked' => array( - 'textarea[name="revision_log"]' => array('empty' => FALSE), - ), - ); - } - - $form['revision_information']['revision_log'] = array( - '#type' => 'textarea', - '#title' => $this->t('Revision log message'), - '#rows' => 4, - '#default_value' => $block->getRevisionLog(), - '#description' => $this->t('Briefly describe the changes you have made.'), - ); - - return parent::form($form, $form_state, $block); + return $form; } /** @@ -166,55 +42,21 @@ public function form(array $form, FormStateInterface $form_state) { */ public function save(array $form, FormStateInterface $form_state) { $block = $this->entity; - - // Save as a new revision if requested to do so. - if (!$form_state->isValueEmpty('revision')) { - $block->setNewRevision(); - // If a new revision is created, save the current user as revision author. - $block->setRevisionCreationTime(REQUEST_TIME); - $block->setRevisionUserId(\Drupal::currentUser()->id()); - } - $insert = $block->isNew(); - $block->save(); - $context = array('@type' => $block->bundle(), '%info' => $block->label()); - $logger = $this->logger('block_content'); - $block_type = $this->blockContentTypeStorage->load($block->bundle()); - $t_args = array('@type' => $block_type->label(), '%info' => $block->label()); - if ($insert) { - $logger->notice('@type: added %info.', $context); - drupal_set_message($this->t('@type %info has been created.', $t_args)); - } - else { - $logger->notice('@type: updated %info.', $context); - drupal_set_message($this->t('@type %info has been updated.', $t_args)); - } + parent::save($form, $form_state); - if ($block->id()) { - $form_state->setValue('id', $block->id()); - $form_state->set('id', $block->id()); - if ($insert) { - if (!$theme = $block->getTheme()) { - $theme = $this->config('system.theme')->get('default'); - } - $form_state->setRedirect( - 'block.admin_add', - array( - 'plugin_id' => 'block_content:' . $block->uuid(), - 'theme' => $theme, - ) - ); - } - else { - $form_state->setRedirectUrl($block->urlInfo('collection')); + if ($insert) { + if (!$theme = $block->getTheme()) { + $theme = $this->config('system.theme')->get('default'); } - } - else { - // In the unlikely case something went wrong on save, the block will be - // rebuilt and block form redisplayed. - drupal_set_message($this->t('The block could not be saved.'), 'error'); - $form_state->setRebuild(); + $form_state->setRedirect( + 'block.admin_add', + [ + 'plugin_id' => 'block_content:' . $block->uuid(), + 'theme' => $theme, + ] + ); } } diff --git a/core/modules/block_content/src/BlockContentTranslationHandler.php b/core/modules/block_content/src/BlockContentTranslationHandler.php index 781ba1b..9a7c46d 100644 --- a/core/modules/block_content/src/BlockContentTranslationHandler.php +++ b/core/modules/block_content/src/BlockContentTranslationHandler.php @@ -15,23 +15,6 @@ class BlockContentTranslationHandler extends ContentTranslationHandler { /** * {@inheritdoc} */ - public function entityFormAlter(array &$form, FormStateInterface $form_state, EntityInterface $entity) { - parent::entityFormAlter($form, $form_state, $entity); - // Move the translation fieldset to a vertical tab. - if (isset($form['translation'])) { - $form['translation'] += array( - '#group' => 'additional_settings', - '#weight' => 100, - '#attributes' => array( - 'class' => array('block-content-translation-options'), - ), - ); - } - } - - /** - * {@inheritdoc} - */ protected function entityFormTitle(EntityInterface $entity) { $block_type = BlockContentType::load($entity->bundle()); return t('Edit @type @title', array('@type' => $block_type->label(), '@title' => $entity->label())); diff --git a/core/modules/block_content/src/BlockContentTypeInterface.php b/core/modules/block_content/src/BlockContentTypeInterface.php index 9229dab..da3864e 100644 --- a/core/modules/block_content/src/BlockContentTypeInterface.php +++ b/core/modules/block_content/src/BlockContentTypeInterface.php @@ -3,11 +3,12 @@ namespace Drupal\block_content; use Drupal\Core\Config\Entity\ConfigEntityInterface; +use Drupal\Core\Entity\RevisionableEntityBundleInterface; /** * Provides an interface defining a custom block type entity. */ -interface BlockContentTypeInterface extends ConfigEntityInterface { +interface BlockContentTypeInterface extends ConfigEntityInterface, RevisionableEntityBundleInterface { /** * Returns the description of the block type. @@ -17,12 +18,4 @@ */ public function getDescription(); - /** - * Returns whether a new revision should be created by default. - * - * @return bool - * TRUE if a new revision should be created by default. - */ - public function shouldCreateNewRevision(); - } diff --git a/core/modules/block_content/src/Entity/BlockContent.php b/core/modules/block_content/src/Entity/BlockContent.php index 13af342..0f50fbc 100644 --- a/core/modules/block_content/src/Entity/BlockContent.php +++ b/core/modules/block_content/src/Entity/BlockContent.php @@ -182,7 +182,14 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields['revision_log'] = BaseFieldDefinition::create('string_long') ->setLabel(t('Revision log message')) ->setDescription(t('The log entry explaining the changes in this revision.')) - ->setRevisionable(TRUE); + ->setRevisionable(TRUE) + ->setDisplayOptions('form', array( + 'type' => 'string_textarea', + 'weight' => 25, + 'settings' => array( + 'rows' => 4, + ), + )); $fields['changed'] = BaseFieldDefinition::create('changed') ->setLabel(t('Changed')) diff --git a/core/modules/content_translation/src/ContentTranslationHandler.php b/core/modules/content_translation/src/ContentTranslationHandler.php index 6fd2254..7995125 100644 --- a/core/modules/content_translation/src/ContentTranslationHandler.php +++ b/core/modules/content_translation/src/ContentTranslationHandler.php @@ -384,6 +384,16 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, En '#multilingual' => TRUE, ); + if (isset($form['advanced'])) { + $form['content_translation'] += array( + '#group' => 'advanced', + '#weight' => 100, + '#attributes' => array( + 'class' => array('entity-translation-options'), + ), + ); + } + // A new translation is enabled by default. $metadata = $this->manager->getTranslationMetadata($entity); $status = $new_translation || $metadata->isPublished(); diff --git a/core/modules/field/src/Tests/FormTest.php b/core/modules/field/src/Tests/FormTest.php index 16625a9..f16886e 100644 --- a/core/modules/field/src/Tests/FormTest.php +++ b/core/modules/field/src/Tests/FormTest.php @@ -609,11 +609,11 @@ function testHiddenField() { $this->drupalPostForm(NULL, array(), t('Save')); preg_match('|' . $entity_type . '/manage/(\d+)|', $this->url, $match); $id = $match[1]; - $this->assertText(t('entity_test_rev @id has been created.', array('@id' => $id)), 'Entity was created'); $storage = $this->container->get('entity_type.manager') ->getStorage($entity_type); $entity = $storage->load($id); + $this->assertRaw(t('@type %label has been created.', ['@type' => 'Test entity - revisions', '%label' => $entity->label()])); $this->assertEqual($entity->{$field_name}->value, 99, 'Default value was saved'); // Update the field to remove the default value, and switch to the default @@ -634,7 +634,7 @@ function testHiddenField() { $value = mt_rand(1, 127); $edit = array("{$field_name}[0][value]" => $value); $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertText(t('entity_test_rev @id has been updated.', array('@id' => $id)), 'Entity was updated'); + $this->assertRaw(t('@type %label has been updated.', ['@type' => 'Test entity - revisions', '%label' => $entity->label()])); $storage->resetCache([$id]); $entity = $storage->load($id); $this->assertEqual($entity->{$field_name}->value, $value, 'Field value was updated'); diff --git a/core/modules/node/node.js b/core/modules/node/node.js index 98af6fd..086263d 100644 --- a/core/modules/node/node.js +++ b/core/modules/node/node.js @@ -18,21 +18,6 @@ Drupal.behaviors.nodeDetailsSummaries = { attach: function (context) { var $context = $(context); - $context.find('.node-form-revision-information').drupalSetSummary(function (context) { - var $revisionContext = $(context); - var revisionCheckbox = $revisionContext.find('.js-form-item-revision input'); - - // Return 'New revision' if the 'Create new revision' checkbox is - // checked, or if the checkbox doesn't exist, but the revision log does. - // For users without the "Administer content" permission the checkbox - // won't appear, but the revision log will if the content type is set to - // auto-revision. - if (revisionCheckbox.is(':checked') || (!revisionCheckbox.length && $revisionContext.find('.js-form-item-revision-log textarea').length)) { - return Drupal.t('New revision'); - } - - return Drupal.t('No revision'); - }); $context.find('.node-form-author').drupalSetSummary(function (context) { var $authorContext = $(context); @@ -64,22 +49,6 @@ return Drupal.t('Not promoted'); } }); - - $context.find('fieldset.node-translation-options').drupalSetSummary(function (context) { - var $translationContext = $(context); - var translate; - var $checkbox = $translationContext.find('.js-form-item-translation-translate input'); - - if ($checkbox.size()) { - translate = $checkbox.is(':checked') ? Drupal.t('Needs to be updated') : Drupal.t('Does not need to be updated'); - } - else { - $checkbox = $translationContext.find('.js-form-item-translation-retranslate input'); - translate = $checkbox.is(':checked') ? Drupal.t('Flag other translations as outdated') : Drupal.t('Do not flag other translations as outdated'); - } - - return translate; - }); } }; diff --git a/core/modules/node/node.libraries.yml b/core/modules/node/node.libraries.yml index 22c93ac..59947a2 100644 --- a/core/modules/node/node.libraries.yml +++ b/core/modules/node/node.libraries.yml @@ -6,10 +6,8 @@ drupal.node: js: node.js: {} dependencies: - - core/jquery - - core/drupal + - core/drupal.entity-form - core/drupalSettings - - core/drupal.form drupal.node.preview: version: VERSION diff --git a/core/modules/node/src/Entity/NodeType.php b/core/modules/node/src/Entity/NodeType.php index 91d8a90..23f24a4 100644 --- a/core/modules/node/src/Entity/NodeType.php +++ b/core/modules/node/src/Entity/NodeType.php @@ -205,4 +205,11 @@ public static function postDelete(EntityStorageInterface $storage, array $entiti $storage->resetCache(array_keys($entities)); } + /** + * {@inheritdoc} + */ + public function shouldCreateNewRevision() { + return $this->isNewRevision(); + } + } diff --git a/core/modules/node/src/NodeForm.php b/core/modules/node/src/NodeForm.php index 2828030..5a8af32 100644 --- a/core/modules/node/src/NodeForm.php +++ b/core/modules/node/src/NodeForm.php @@ -2,8 +2,9 @@ namespace Drupal\node; -use Drupal\Core\Entity\ContentEntityForm; use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Entity\EntityTypeBundleInfoInterface; +use Drupal\Core\Entity\Form\RevisionableContentEntityForm; use Drupal\Core\Form\FormStateInterface; use Drupal\user\PrivateTempStoreFactory; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -11,7 +12,7 @@ /** * Form handler for the node edit forms. */ -class NodeForm extends ContentEntityForm { +class NodeForm extends RevisionableContentEntityForm { /** * The tempstore factory. @@ -26,15 +27,15 @@ class NodeForm extends ContentEntityForm { protected $hasBeenPreviewed = FALSE; /** - * Constructs a ContentEntityForm object. + * Constructs a NodeForm object. * * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * The entity manager. * @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory * The factory for the temp store object. */ - public function __construct(EntityManagerInterface $entity_manager, PrivateTempStoreFactory $temp_store_factory) { - parent::__construct($entity_manager); + public function __construct(EntityManagerInterface $entity_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, PrivateTempStoreFactory $temp_store_factory) { + parent::__construct($entity_manager, $entity_type_bundle_info); $this->tempStoreFactory = $temp_store_factory; } @@ -44,6 +45,7 @@ public function __construct(EntityManagerInterface $entity_manager, PrivateTempS public static function create(ContainerInterface $container) { return new static( $container->get('entity.manager'), + $container->get('entity_type.bundle.info'), $container->get('user.private_tempstore') ); } @@ -51,19 +53,6 @@ public static function create(ContainerInterface $container) { /** * {@inheritdoc} */ - protected function prepareEntity() { - /** @var \Drupal\node\NodeInterface $node */ - $node = $this->entity; - - if (!$node->isNew()) { - // Remove the revision log message from the original node entity. - $node->revision_log = NULL; - } - } - - /** - * {@inheritdoc} - */ public function form(array $form, FormStateInterface $form_state) { // Try to restore from temp store, this must be done before calling // parent::form(). @@ -98,10 +87,6 @@ public function form(array $form, FormStateInterface $form_state) { /** @var \Drupal\node\NodeInterface $node */ $node = $this->entity; - if ($this->operation == 'edit') { - $form['#title'] = $this->t('Edit @type @title', array('@type' => node_get_type_label($node), '@title' => $node->label())); - } - $current_user = $this->currentUser(); // Changed must be sent to the client, for later overwrite error checking. @@ -110,47 +95,22 @@ public function form(array $form, FormStateInterface $form_state) { '#default_value' => $node->getChangedTime(), ); - $form['advanced'] = array( - '#type' => 'vertical_tabs', - '#attributes' => array('class' => array('entity-meta')), - '#weight' => 99, - ); $form = parent::form($form, $form_state); - // Add a revision_log field if the "Create new revision" option is checked, - // or if the current user has the ability to check that option. - $form['revision_information'] = array( - '#type' => 'details', - '#group' => 'advanced', - '#title' => t('Revision information'), - // Open by default when "Create new revision" is checked. - '#open' => $node->isNewRevision(), - '#attributes' => array( - 'class' => array('node-form-revision-information'), - ), - '#attached' => array( - 'library' => array('node/drupal.node'), - ), - '#weight' => 20, - '#optional' => TRUE, - ); + $form['advanced']['#attributes']['class'][] = 'entity-meta'; - $form['revision'] = array( - '#type' => 'checkbox', - '#title' => t('Create new revision'), - '#default_value' => $node->type->entity->isNewRevision(), - '#access' => $current_user->hasPermission('administer nodes') && !$node->isNew(), - '#group' => 'revision_information', - ); + $form['revision']['#access'] = $current_user->hasPermission('administer nodes') && !$node->isNew(); - $form['revision_log'] += array( - '#states' => array( - 'visible' => array( - ':input[name="revision"]' => array('checked' => TRUE), - ), - ), - '#group' => 'revision_information', - ); + // Clear revision states, because it will conflicts with revision_log state. + $form['revision']['#states']['checked'] = []; + + $form['revision_log'] += [ + '#states' => [ + 'visible' => [ + ':input[name="revision"]' => ['checked' => TRUE], + ], + ], + ]; // Node author information for administrators. $form['author'] = array( @@ -304,32 +264,6 @@ protected function actions(array $form, FormStateInterface $form_state) { } /** - * {@inheritdoc} - * - * Updates the node object by processing the submitted values. - * - * This function can be called by a "Next" button of a wizard to update the - * form state's entity with the current step's values before proceeding to the - * next step. - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - // Build the node object from the submitted values. - parent::submitForm($form, $form_state); - $node = $this->entity; - - // Save as a new revision if requested to do so. - if (!$form_state->isValueEmpty('revision') && $form_state->getValue('revision') != FALSE) { - $node->setNewRevision(); - // If a new revision is created, save the current user as revision author. - $node->setRevisionCreationTime(REQUEST_TIME); - $node->setRevisionUserId(\Drupal::currentUser()->id()); - } - else { - $node->setNewRevision(FALSE); - } - } - - /** * Form submission handler for the 'preview' action. * * @param $form diff --git a/core/modules/node/src/NodeTranslationHandler.php b/core/modules/node/src/NodeTranslationHandler.php index 9c9741e..2f6d2ab 100644 --- a/core/modules/node/src/NodeTranslationHandler.php +++ b/core/modules/node/src/NodeTranslationHandler.php @@ -17,17 +17,7 @@ class NodeTranslationHandler extends ContentTranslationHandler { public function entityFormAlter(array &$form, FormStateInterface $form_state, EntityInterface $entity) { parent::entityFormAlter($form, $form_state, $entity); - // Move the translation fieldset to a vertical tab. if (isset($form['content_translation'])) { - $form['content_translation'] += array( - '#group' => 'advanced', - '#attributes' => array( - 'class' => array('node-translation-options'), - ), - ); - - $form['content_translation']['#weight'] = 100; - // We do not need to show these values on node forms: they inherit the // basic node property values. $form['content_translation']['status']['#access'] = FALSE; diff --git a/core/modules/node/src/NodeTypeInterface.php b/core/modules/node/src/NodeTypeInterface.php index c034ffb..1aab64d 100644 --- a/core/modules/node/src/NodeTypeInterface.php +++ b/core/modules/node/src/NodeTypeInterface.php @@ -3,11 +3,12 @@ namespace Drupal\node; use Drupal\Core\Config\Entity\ConfigEntityInterface; +use Drupal\Core\Entity\RevisionableEntityBundleInterface; /** * Provides an interface defining a node type entity. */ -interface NodeTypeInterface extends ConfigEntityInterface { +interface NodeTypeInterface extends ConfigEntityInterface, RevisionableEntityBundleInterface { /** * Determines whether the node type is locked. @@ -28,7 +29,7 @@ public function isNewRevision(); /** * Sets whether a new revision should be created by default. * - * @param bool $new_revision_ + * @param bool $new_revision * TRUE if a new revision should be created by default. */ public function setNewRevision($new_revision); diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestRev.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestRev.php index 47035ea..094f7e9 100644 --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestRev.php +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestRev.php @@ -3,6 +3,8 @@ namespace Drupal\entity_test\Entity; use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Entity\RevisionLogEntityTrait; +use Drupal\Core\Entity\RevisionLogInterface; use Drupal\Core\Field\BaseFieldDefinition; /** @@ -15,7 +17,7 @@ * "access" = "Drupal\entity_test\EntityTestAccessControlHandler", * "view_builder" = "Drupal\entity_test\EntityTestViewBuilder", * "form" = { - * "default" = "Drupal\entity_test\EntityTestForm", + * "default" = "\Drupal\entity_test\EntityTestRevisionForm", * "delete" = "Drupal\entity_test\EntityTestDeleteForm" * }, * "view_builder" = "Drupal\entity_test\EntityTestViewBuilder", @@ -45,7 +47,9 @@ * } * ) */ -class EntityTestRev extends EntityTest { +class EntityTestRev extends EntityTest implements RevisionLogInterface { + + use RevisionLogEntityTrait; /** * {@inheritdoc} @@ -53,13 +57,8 @@ class EntityTestRev extends EntityTest { public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = parent::baseFieldDefinitions($entity_type); - $fields['revision_id'] = BaseFieldDefinition::create('integer') - ->setLabel(t('Revision ID')) - ->setDescription(t('The version id of the test entity.')) - ->setReadOnly(TRUE) - ->setSetting('unsigned', TRUE); + $fields += static::revisionLogBaseFieldDefinitions($entity_type); - $fields['langcode']->setRevisionable(TRUE); $fields['name']->setRevisionable(TRUE); $fields['user_id']->setRevisionable(TRUE); diff --git a/core/modules/system/tests/modules/entity_test/src/EntityTestRevisionForm.php b/core/modules/system/tests/modules/entity_test/src/EntityTestRevisionForm.php new file mode 100644 index 0000000..b0843c1 --- /dev/null +++ b/core/modules/system/tests/modules/entity_test/src/EntityTestRevisionForm.php @@ -0,0 +1,38 @@ +entity->name->value)) { + // Assign a random name to new EntityTest entities, to avoid repetition in + // tests. + $random = new Random(); + $this->entity->name->value = $random->name(); + } + } + + /** + * {@inheritdoc} + */ + public function save(array $form, FormStateInterface $form_state) { + try { + parent::save($form, $form_state); + } + catch (\Exception $e) { + \Drupal::state()->set('entity_test.form.save.exception', get_class($e) . ': ' . $e->getMessage()); + } + } + +} diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php index 23cf034..e49ee7e 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php @@ -102,6 +102,9 @@ public function testEntityTypeUpdateWithoutData() { $expected = array( 'entity_test_update' => array( t('The %entity_type entity type needs to be updated.', ['%entity_type' => $this->entityManager->getDefinition('entity_test_update')->getLabel()]), + // The revision key is now defined, so the revision field needs to be + // created. + t('The %field_name field needs to be installed.', ['%field_name' => 'Revision ID']), ), ); $this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected); //, 'EntityDefinitionUpdateManager reports the expected change summary.'); @@ -797,7 +800,7 @@ public function testBaseFieldEntityKeyUpdateWithExistingData() { /** * Check that field schema is correctly handled with long-named fields. */ - function testLongNameFieldIndexes() { + public function testLongNameFieldIndexes() { $this->addLongNameBaseField(); $entity_type_id = 'entity_test_update'; $entity_type = $this->entityManager->getDefinition($entity_type_id);