wse-1.0.x-dev/src/WseFormOperations.php

src/WseFormOperations.php
<?php

namespace Drupal\wse;

use Drupal\Component\Utility\Html;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\workspaces\WorkspaceManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Defines a class for reacting to form operations.
 *
 * @internal
 */
class WseFormOperations implements ContainerInjectionInterface {

  /**
   * The workspace manager.
   *
   * @var \Drupal\workspaces\WorkspaceManagerInterface
   */
  protected $workspaceManager;

  /**
   * The configuration factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * Collects altered form ids to pass them down to the form submit dialog JS.
   *
   * @var array
   */
  protected static array $alteredFormIds = [];

  /**
   * Constructs a new WseFormOperations instance.
   *
   * @param \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager
   *   The workspace manager service.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The configuration factory.
   */
  public function __construct(WorkspaceManagerInterface $workspace_manager, ConfigFactoryInterface $config_factory) {
    $this->workspaceManager = $workspace_manager;
    $this->configFactory = $config_factory;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('workspaces.manager'),
      $container->get('config.factory')
    );
  }

  /**
   * Alters forms to add confirm modal for submission in non-default workspaces.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   * @param string $form_id
   *   The form ID.
   *
   * @see wse_form_alter()
   */
  public function formAlter(array &$form, FormStateInterface $form_state, $form_id) {
    // No alterations are needed if we're not in a workspace context.
    if (!$this->workspaceManager->hasActiveWorkspace() || $form_state->get('workspace_safe')) {
      return;
    }

    // @todo Fix in core.
    $safe_form_ids = [
      'node_revision_revert_confirm',
      'node_revision_delete_confirm',
    ];
    // Allow a few forms that we know are safe to submit.
    if (in_array($form_id, $safe_form_ids, TRUE)) {
      $form_state->set('workspace_safe', TRUE);
      return;
    }

    $ignored_forms = $this->configFactory->get('wse.settings')->get('safe_forms') ?? [];
    if (!in_array($form_id, $ignored_forms)) {
      // The alterations here make core's validation obsolete, so remove it.
      $this->removeWorkspaceValidation($form);

      // Add a form element that will be used by WseWorkspaceManager to disable
      // any active workspace for the duration of the form submission request.
      $form['wse_bypass_workspace'] = [
        '#type' => 'hidden',
        '#value' => 1,
        '#name' => 'wse_bypass_workspace',
        // Form processing and validation require this value. Ensure the
        // submitted form value appears literally, regardless of custom #tree
        // and #parents being set elsewhere.
        '#parents' => ['wse_bypass_workspace'],
      ];

      // The confirm submission dialog is implemented on the client side.
      $form['#attached']['library'][] = 'wse/form-submit-dialog';
      static::$alteredFormIds[] = Html::getId($form_id);
      $form['#attached']['drupalSettings']['wseSubmitDialog']['formSelectors'] = static::$alteredFormIds;
    }
  }

  /**
   * Removes workspaces core's validation handler recursively on each element.
   *
   * @param array &$element
   *   An associative array containing the structure of the form.
   */
  protected function removeWorkspaceValidation(array &$element) {
    // Recurse through all children and add our validation handler if needed.
    foreach (Element::children($element) as $key) {
      if (isset($element[$key]) && $element[$key]) {
        $this->removeWorkspaceValidation($element[$key]);
      }
    }

    if (isset($element['#validate'])) {
      foreach ($element['#validate'] as $key => $validation_callback) {
        if (is_array($validation_callback) && in_array('validateDefaultWorkspace', $validation_callback)) {
          unset($element['#validate'][$key]);
          return;
        }
      }
    }
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc