Commit 01b96cea authored by john.oltman's avatar john.oltman
Browse files

Issue #3321661: Add a Cancel operation for registrations.

parent a9b293ee
Loading
Loading
Loading
Loading
+18 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ use Drupal\registration\Entity\RegistrationInterface;
use Drupal\registration\RegistrationHelper;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\workflows\WorkflowInterface;

/**
 * Implements hook_help().
@@ -142,7 +143,6 @@ function registration_entity_operation(EntityInterface $entity): array {
  if (($entity instanceof RegistrationInterface) && $entity->access('view')) {
    // Add a View operation for registrations. This will be first, followed
    // by the Edit and Delete operations (if the user has those permissions).
    // @todo Add a Cancel operation.
    $operations['view'] = [
      'title' => t('View'),
      'url' => Url::fromRoute('entity.registration.canonical', [
@@ -151,6 +151,18 @@ function registration_entity_operation(EntityInterface $entity): array {
      'weight' => -1,
    ];
  }
  if (($entity instanceof RegistrationInterface) && $entity->access('cancel')) {
    // Add a Cancel operation for registrations. The entity access check
    // ensures there is a corresponding workflow state and that the entity is
    // not already canceled.
    $operations['cancel'] = [
      'title' => t('Cancel'),
      'url' => Url::fromRoute('entity.registration.cancel', [
        'registration' => $entity->id(),
      ])->mergeOptions(['query' => \Drupal::destination()->getAsArray()]),
      'weight' => 10,
    ];
  }
  return $operations;
}

@@ -240,6 +252,11 @@ function registration_entity_update(EntityInterface $entity) {
      \Drupal::service('plugin.manager.menu.local_task')->clearCachedDefinitions();
    }
  }
  // Rebuild registration listings when workflows are updated, as the list of
  // available entity operations could change.
  if ($entity instanceof WorkflowInterface) {
    Cache::invalidateTags(['registration_list']);
  }
}

/**
+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ services:
  registration.route_subscriber:
    class: Drupal\registration\Routing\RouteSubscriber
    arguments: [
      '@entity_type.manager',
      '@registration.manager',
    ]
    tags:
+2 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ use Drupal\workflows\WorkflowInterface;
 *     "views_data" = "Drupal\views\EntityViewsData",
 *     "form" = {
 *       "default" = "Drupal\registration\Form\RegisterForm",
 *       "cancel" = "Drupal\registration\Form\RegistrationCancelForm",
 *       "edit" = "Drupal\registration\Form\RegisterForm",
 *       "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",
 *       "register" = "Drupal\registration\Form\RegisterForm",
@@ -57,6 +58,7 @@ use Drupal\workflows\WorkflowInterface;
 *   },
 *   links = {
 *     "canonical" = "/registration/{registration}",
 *     "cancel-form" = "/registration/{registration}/cancel",
 *     "edit-form" = "/registration/{registration}/edit",
 *     "delete-form" = "/registration/{registration}/delete",
 *     "collection" = "/admin/people/registrations"
+0 −3
Original line number Diff line number Diff line
@@ -176,9 +176,6 @@ interface RegistrationInterface extends ContentEntityInterface, EntityChangedInt
  /**
   * Determines whether a registration is in a canceled state.
   *
   * Although canceled is not a direct state, it is assumed if the state is
   * neither active nor held.
   *
   * @return bool
   *   TRUE if the registration is in a canceled state, FALSE otherwise.
   */
+99 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\registration\Form;

use Drupal\Core\Entity\ContentEntityConfirmFormBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Define the RegistrationCancelForm class.
 */
class RegistrationCancelForm extends ContentEntityConfirmFormBase {

  /**
   * {@inheritdoc}
   */
  public function getQuestion() {
    return $this->t('Are you sure you want to cancel registration @id?', [
      '@id' => $this->entity->id(),
    ]);
  }

  /**
   * {@inheritdoc}
   */
  public function getDescription() {
    return $this->t('This action cannot be undone.');
  }

  /**
   * {@inheritdoc}
   */
  public function getCancelUrl() {
    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
    $entity = $this->getEntity();
    return $entity->toUrl('canonical');
  }

  /**
   * {@inheritdoc}
   */
  public function getConfirmText() {
    return $this->t('Yes, I want to cancel the registration');
  }

  /**
   * {@inheritdoc}
   */
  public function getCancelText() {
    return $this->t('No, I do not want to cancel the registration');
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    $violations = $this->entity->validate();
    $violations->filterByFieldAccess($this->currentUser());
    foreach ($violations as $violation) {
      $field_name[] = explode('.', $violation->getPropertyPath(), 2);
      $form_state->setErrorByName($field_name, $violation->getMessage());
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    parent::submitForm($form, $form_state);

    if ($state = $this->getCanceledState()) {
      /** @var \Drupal\registration\Entity\RegistrationInterface $this->entity */
      $this->entity->set('state', $state);
      $this->entity->save();
      $this->messenger()->addMessage($this->t('The registration has been canceled.'));
    }
  }

  /**
   * Gets the ID of the canceled state in the registration workflow.
   *
   * @return string|null
   *   The ID of the canceled state, if available.
   */
  protected function getCanceledState(): ?string {
    /** @var \Drupal\registration\Entity\RegistrationInterface $this->entity */
    if ($workflow = $this->entity->getWorkflow()) {
      $all_states = $workflow->getTypePlugin()->getStates();
      foreach ($all_states as $state) {
        /** @var \Drupal\registration\RegistrationState $state */
        if ($state->isCanceled()) {
          return $state->id();
        }
      }
    }

    return NULL;
  }

}
Loading