You are here

protected function AjaxCommentsForm::actions in AJAX Comments 8

Returns an array of supported actions for the current entity form.

This function generates a list of Form API elements which represent actions supported by the current entity form.

@todo Consider introducing a 'preview' action here, since it is used by many entity types.

Parameters

array $form: An associative array containing the structure of the form.

\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.

Return value

array An array of supported Form API action elements keyed by name.

Overrides CommentForm::actions

File

src/Form/AjaxCommentsForm.php, line 207

Class

AjaxCommentsForm
Provides ajax enhancements to core default Comment form.

Namespace

Drupal\ajax_comments\Form

Code

protected function actions(array $form, FormStateInterface $form_state) {
  $element = parent::actions($form, $form_state);

  // Populate the comment-specific variables.

  /** @var \Drupal\comment\CommentInterface $comment */
  $comment = $form_state
    ->getFormObject()
    ->getEntity();
  $comment_formatter = $this->fieldSettingsHelper
    ->getFieldFormatterFromComment($comment, 'full');
  if (empty($comment_formatter) || !$this->fieldSettingsHelper
    ->isEnabled($comment_formatter)) {

    // If not using Ajax Comments, return the unmodified element.
    return $element;
  }

  /** @var \Drupal\Core\Entity\EntityInterface $commented_entity */
  $commented_entity = $comment
    ->getCommentedEntity();
  $field_name = $comment
    ->getFieldName();
  $cid = $comment
    ->id() ? $comment
    ->id() : 0;
  $pid = $comment
    ->get('pid')->target_id ? $comment
    ->get('pid')->target_id : NULL;

  // Build the #ajax array.
  $ajax = [
    // Due to D8 core comments' use of #lazy_builder, setting a 'callback'
    // here won't work. The Drupal 8 form ajax callback functionality
    // relies on FormBuilder::buildForm() throwing an FormAjaxException()
    // during processing. The exception would be caught in Symfony's
    // HttpKernel::handle() method, which handles the exception and gets
    // responses from event subscribers, in this case FormAjaxSubscriber.
    // However, #lazy_builder causes the comment form to be built on a
    // separate, subsequent request, which causes HttpKernel::handle()
    // to be unable to catch the FormAjaxException. Using an ajax 'url'
    // instead of a callback avoids this issue.
    // The ajax URL varies based on context, so set a placeholder and
    // override below.
    'url' => NULL,
    // We need to wait for ajax_comments_entity_display_build_alter() to run
    // so that we can populate the $form['wrapper_html_id'] in
    // $this->buildForm(), so we need to set this to a NULL placeholder and
    // update the value in $this->buildForm() as well.
    'wrapper' => NULL,
    'method' => 'replace',
    'effect' => 'fade',
  ];

  // Build the ajax submit URLs.
  $ajax_new_comment_url = Url::fromRoute('ajax_comments.add', [
    'entity_type' => $commented_entity
      ->getEntityTypeId(),
    'entity' => $commented_entity
      ->id(),
    'field_name' => $field_name,
    'pid' => $pid,
  ]);
  $ajax_edit_comment_url = Url::fromRoute('ajax_comments.save', [
    'comment' => $cid,
  ]);
  $ajax_comment_reply_url = Url::fromRoute('ajax_comments.save_reply', [
    'entity_type' => $commented_entity
      ->getEntityTypeId(),
    'entity' => $commented_entity
      ->id(),
    'field_name' => $field_name,
    'pid' => $pid,
  ]);

  // Build the cancel button render array.
  $cancel = [
    '#type' => 'button',
    '#value' => t('Cancel'),
    '#access' => TRUE,
    '#ajax' => [
      'url' => Url::fromRoute('ajax_comments.cancel', [
        'cid' => $cid,
      ]),
      // We need to wait for ajax_comments_entity_display_build_alter() to run
      // so that we can populate the $form['wrapper_html_id'] in
      // $this->buildForm(), so we need to set this to a NULL placeholder and
      // update the value in $this->buildForm() as well.
      'wrapper' => NULL,
      'method' => 'replace',
      'effect' => 'fade',
    ],
  ];

  // The form actions will vary based on the route
  // that is requesting this form.
  $request = $this->requestStack
    ->getCurrentRequest();
  $route_name = RouteMatch::createFromRequest($request)
    ->getRouteName();
  $editing = !empty($form_state
    ->get('editing'));
  switch ($route_name) {
    case 'entity.comment.edit_form':

      // If we're on the standalone comment edit page (/comment/{cid}/edit),
      // don't add the ajax behavior.
      break;
    case 'ajax_comments.edit':
      $element['submit']['#ajax'] = $ajax;
      $element['submit']['#ajax']['url'] = $ajax_edit_comment_url;
      $element['cancel'] = $cancel;
      break;
    case 'ajax_comments.save':
      $element['submit']['#ajax'] = $ajax;

      // If the user attempted to submit the form but there were errors,
      // rebuild the form used at the 'ajax_comments.edit' route.
      if ($editing) {
        $element['submit']['#ajax']['url'] = $ajax_edit_comment_url;
        $element['cancel'] = $cancel;
      }
      else {
        $element['submit']['#ajax']['url'] = $ajax_new_comment_url;
      }
      break;
    case 'ajax_comments.reply':
      $element['submit']['#ajax'] = $ajax;
      $element['submit']['#ajax']['url'] = $ajax_comment_reply_url;
      $element['cancel'] = $cancel;
      break;
    case 'ajax_comments.save_reply':
      $element['submit']['#ajax'] = $ajax;

      // If the user attempted to submit the form but there were errors,
      // rebuild the form used at the 'ajax_comments.reply' route.
      if ($editing) {
        $element['submit']['#ajax']['url'] = $ajax_comment_reply_url;
        $element['cancel'] = $cancel;
      }
      else {
        $element['submit']['#ajax']['url'] = $ajax_new_comment_url;
      }
      break;
    default:
      $element['submit']['#ajax'] = $ajax;
      $element['submit']['#ajax']['url'] = $ajax_new_comment_url;
      break;
  }
  return $element;
}