Commit 8635f1e3 authored by john.oltman's avatar john.oltman
Browse files

Issue #3318986: Add operations for workflow transitions.

parent 01b96cea
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
name: Registration Workflow
type: module
description: 'Provides permissions and operations for registration workflow transitions.'
package: Registration
core_version_requirement: ^9.3 || ^10
php: 8.0
dependencies:
  - registration:registration
+117 −0
Original line number Diff line number Diff line
<?php

/**
 * @file
 * Provides permissions and operations for workflow transitions.
 */

use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Url;
use Drupal\registration\Entity\RegistrationInterface;
use Drupal\workflows\WorkflowInterface;

/**
 * Implements hook_entity_operation().
 */
function registration_workflow_entity_operation(EntityInterface $entity): array {
  $operations = [];

  // Add a cancel operation for registrations. The route has a custom access
  // checker that will ensure the operation is only displayed if the user has
  // permission to cancel registrations and the registration is not already
  // canceled.
  if ($entity instanceof RegistrationInterface) {
    $url = Url::fromRoute('registration_workflow.transition', [
      'registration' => $entity->id(),
      'transition' => 'cancel',
    ]);
    if ($url->access()) {
      $operations['cancel'] = [
        'title' => t('Cancel'),
        'url' => $url->mergeOptions([
          'query' => \Drupal::destination()->getAsArray(),
        ]),
        'weight' => 10,
      ];
    }
  }

  return $operations;
}

/**
 * Implements hook_entity_update().
 */
function registration_workflow_entity_update(EntityInterface $entity) {
  // Flush the render cache when workflows are updated, as the list of
  // available registration entity operations could change.
  if ($entity instanceof WorkflowInterface) {
    foreach (Cache::getBins() as $service_id => $cache_backend) {
      if ($service_id == 'render') {
        $cache_backend->deleteAll();
      }
    }
  }
}

/**
 * Prepares variables for a registration.
 *
 * Default template: registration.html.twig.
 *
 * @param array $variables
 *   An associative array containing:
 *   - elements: An associative array containing rendered fields.
 *   - attributes: HTML attributes for the containing element.
 */
function registration_workflow_preprocess_registration(array &$variables) {
  // Add operations buttons when the registration is displayed on its own page.
  if ($variables['elements']['#view_mode'] == 'full') {
    /** @var Drupal\registration\Entity\RegistrationInterface $registration */
    $registration = $variables['elements']['#registration'];
    $transitions = \Drupal::service('registration_workflow.validation')->getValidTransitions($registration);

    // Render a button for each transition. Exclude cancel since it is already
    // rendered as an entity operation in registration listings.
    unset($transitions['cancel']);
    foreach ($transitions as $transition) {
      $url = Url::fromRoute('registration_workflow.transition', [
        'registration' => $registration->id(),
        'transition' => $transition->id(),
      ]);
      // Ensure the user has access to perform the transition.
      if ($url->access()) {
        $url->mergeOptions([
          'query' => \Drupal::destination()->getAsArray(),
        ]);
        // Append to the bottom of the registration template.
        if (empty($variables['registration']['transition'])) {
          $variables['registration']['transition'] = [
            '#prefix' => '<p>',
            '#type' => 'container',
            '#weight' => 50,
            // Rebuild if user permissions change.
            '#cache' => [
              'contexts' => [
                'user.permissions',
              ],
            ],
          ];
        }
        $variables['registration']['transition'][$transition->id()] = [
          '#type' => 'link',
          '#url' => $url,
          '#title' => t('@transition registration', [
            '@transition' => $transition->label(),
          ]),
          '#attributes' => [
            'class' => [
              'button',
            ],
          ],
        ];
      }
    }
  }
}
+2 −0
Original line number Diff line number Diff line
permission_callbacks:
  - \Drupal\registration_workflow\RegistrationWorkflowPermissionProvider::buildPermissions
+11 −0
Original line number Diff line number Diff line
registration_workflow.transition:
  path: '/registration/{registration}/transition/{transition}'
  defaults:
    _form: '\Drupal\registration_workflow\Form\StateTransitionForm'
  requirements:
    _state_transition_access_check: 'TRUE'
  options:
    _admin_route: TRUE
    parameters:
      registration:
        type: entity:registration
+14 −0
Original line number Diff line number Diff line
services:
  registration_workflow.state_transition_access_checker:
    class: Drupal\registration_workflow\Access\StateTransitionAccessCheck
    arguments: [
      '@registration_workflow.validation',
    ]
    tags:
      - { name: access_check, applies_to: _state_transition_access_check }

  registration_workflow.validation:
    class: Drupal\registration_workflow\StateTransitionValidation
    arguments: [
      '@current_user',
    ]
Loading