tempStoreFactory = $temp_store_factory; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('entity.manager'), $container->get('user.private_tempstore') ); } /** * {@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(). $uuid = $this->entity->uuid(); $store = $this->tempStoreFactory->get('node_preview'); // If the user is creating a new node, the UUID is passed in the request. if ($request_uuid = \Drupal::request()->query->get('uuid')) { $uuid = $request_uuid; } if ($preview = $store->get($uuid)) { /** @var $preview \Drupal\Core\Form\FormStateInterface */ foreach ($preview->getValues() as $name => $value) { $form_state->setValue($name, $value); } // Rebuild the form. $form_state->setRebuild(); $this->entity = $preview->getFormObject()->getEntity(); $this->entity->in_preview = NULL; // Remove the stale temp store entry for existing nodes. if (!$this->entity->isNew()) { $store->delete($uuid); } $this->hasBeenPreviewed = TRUE; } /** @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. $form['changed'] = array( '#type' => 'hidden', '#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['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_log'] += array( '#states' => array( 'visible' => array( ':input[name="revision"]' => array('checked' => TRUE), ), ), '#group' => 'revision_information', ); // Node author information for administrators. $form['author'] = array( '#type' => 'details', '#title' => t('Authoring information'), '#group' => 'advanced', '#attributes' => array( 'class' => array('node-form-author'), ), '#attached' => array( 'library' => array('node/drupal.node'), ), '#weight' => 90, '#optional' => TRUE, ); if (isset($form['uid'])) { $form['uid']['#group'] = 'author'; } if (isset($form['created'])) { $form['created']['#group'] = 'author'; } // Node options for administrators. $form['options'] = array( '#type' => 'details', '#title' => t('Promotion options'), '#group' => 'advanced', '#attributes' => array( 'class' => array('node-form-options'), ), '#attached' => array( 'library' => array('node/drupal.node'), ), '#weight' => 95, '#optional' => TRUE, ); if (isset($form['promote'])) { $form['promote']['#group'] = 'options'; } if (isset($form['sticky'])) { $form['sticky']['#group'] = 'options'; } $form['#attached']['library'][] = 'node/form'; $form['#entity_builders']['update_status'] = [$this, 'updateStatus']; return $form; } /** * Entity builder updating the node status with the submitted value. * * @param string $entity_type_id * The entity type identifier. * @param \Drupal\node\NodeInterface $node * The node updated with the submitted values. * @param array $form * The complete form array. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * * @see \Drupal\node\NodeForm::form() */ function updateStatus($entity_type_id, NodeInterface $node, array $form, FormStateInterface $form_state) { $element = $form_state->getTriggeringElement(); if (isset($element['#published_status'])) { $node->setPublished($element['#published_status']); } } /** * {@inheritdoc} */ protected function actions(array $form, FormStateInterface $form_state) { $element = parent::actions($form, $form_state); $node = $this->entity; $preview_mode = $node->type->entity->getPreviewMode(); $element['submit']['#access'] = $preview_mode != DRUPAL_REQUIRED || $this->hasBeenPreviewed; // If saving is an option, privileged users get dedicated form submit // buttons to adjust the publishing status while saving in one go. // @todo This adjustment makes it close to impossible for contributed // modules to integrate with "the Save operation" of this form. Modules // need a way to plug themselves into 1) the ::submit() step, and // 2) the ::save() step, both decoupled from the pressed form button. if ($element['submit']['#access'] && \Drupal::currentUser()->hasPermission('administer nodes')) { // isNew | prev status » default & publish label & unpublish label // 1 | 1 » publish & Save and publish & Save as unpublished // 1 | 0 » unpublish & Save and publish & Save as unpublished // 0 | 1 » publish & Save and keep published & Save and unpublish // 0 | 0 » unpublish & Save and keep unpublished & Save and publish // Add a "Publish" button. $element['publish'] = $element['submit']; // If the "Publish" button is clicked, we want to update the status to "published". $element['publish']['#published_status'] = TRUE; $element['publish']['#dropbutton'] = 'save'; if ($node->isNew()) { $element['publish']['#value'] = t('Save and publish'); } else { $element['publish']['#value'] = $node->isPublished() ? t('Save and keep published') : t('Save and publish'); } $element['publish']['#weight'] = 0; // Add a "Unpublish" button. $element['unpublish'] = $element['submit']; // If the "Unpublish" button is clicked, we want to update the status to "unpublished". $element['unpublish']['#published_status'] = FALSE; $element['unpublish']['#dropbutton'] = 'save'; if ($node->isNew()) { $element['unpublish']['#value'] = t('Save as unpublished'); } else { $element['unpublish']['#value'] = !$node->isPublished() ? t('Save and keep unpublished') : t('Save and unpublish'); } $element['unpublish']['#weight'] = 10; // If already published, the 'publish' button is primary. if ($node->isPublished()) { unset($element['unpublish']['#button_type']); } // Otherwise, the 'unpublish' button is primary and should come first. else { unset($element['publish']['#button_type']); $element['unpublish']['#weight'] = -10; } // Remove the "Save" button. $element['submit']['#access'] = FALSE; } $element['preview'] = array( '#type' => 'submit', '#access' => $preview_mode != DRUPAL_DISABLED && ($node->access('create') || $node->access('update')), '#value' => t('Preview'), '#weight' => 20, '#submit' => array('::submitForm', '::preview'), ); $element['delete']['#access'] = $node->access('delete'); $element['delete']['#weight'] = 100; return $element; } /** * {@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 * An associative array containing the structure of the form. * @param $form_state * The current state of the form. */ public function preview(array $form, FormStateInterface $form_state) { $store = $this->tempStoreFactory->get('node_preview'); $this->entity->in_preview = TRUE; $store->set($this->entity->uuid(), $form_state); $form_state->setRedirect('entity.node.preview', array( 'node_preview' => $this->entity->uuid(), 'view_mode_id' => 'default', )); } /** * {@inheritdoc} */ public function save(array $form, FormStateInterface $form_state) { $node = $this->entity; $insert = $node->isNew(); $node->save(); $node_link = $node->link($this->t('View')); $context = array('@type' => $node->getType(), '%title' => $node->label(), 'link' => $node_link); $t_args = array('@type' => node_get_type_label($node), '%title' => $node->link($node->label())); if ($insert) { $this->logger('content')->notice('@type: added %title.', $context); drupal_set_message(t('@type %title has been created.', $t_args)); } else { $this->logger('content')->notice('@type: updated %title.', $context); drupal_set_message(t('@type %title has been updated.', $t_args)); } if ($node->id()) { $form_state->setValue('nid', $node->id()); $form_state->set('nid', $node->id()); if ($node->access('view')) { $form_state->setRedirect( 'entity.node.canonical', array('node' => $node->id()) ); } else { $form_state->setRedirect(''); } // Remove the preview entry from the temp store, if any. $store = $this->tempStoreFactory->get('node_preview'); $store->delete($node->uuid()); } else { // In the unlikely case something went wrong on save, the node will be // rebuilt and node form redisplayed the same way as in preview. drupal_set_message(t('The post could not be saved.'), 'error'); $form_state->setRebuild(); } } }