Pull merge.
[yaffs-website] / web / core / modules / workspaces / src / FormOperations.php
1 <?php
2
3 namespace Drupal\workspaces;
4
5 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
6 use Drupal\Core\Form\FormStateInterface;
7 use Drupal\Core\Render\Element;
8 use Drupal\Core\StringTranslation\TranslatableMarkup;
9 use Drupal\views\Form\ViewsExposedForm;
10 use Drupal\workspaces\Form\WorkspaceFormInterface;
11 use Symfony\Component\DependencyInjection\ContainerInterface;
12
13 /**
14  * Defines a class for reacting to form operations.
15  *
16  * @internal
17  */
18 class FormOperations implements ContainerInjectionInterface {
19
20   /**
21    * The workspace manager service.
22    *
23    * @var \Drupal\workspaces\WorkspaceManagerInterface
24    */
25   protected $workspaceManager;
26
27   /**
28    * Constructs a new FormOperations instance.
29    *
30    * @param \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager
31    *   The workspace manager service.
32    */
33   public function __construct(WorkspaceManagerInterface $workspace_manager) {
34     $this->workspaceManager = $workspace_manager;
35   }
36
37   /**
38    * {@inheritdoc}
39    */
40   public static function create(ContainerInterface $container) {
41     return new static(
42       $container->get('workspaces.manager')
43     );
44   }
45
46   /**
47    * Alters forms to disallow editing in non-default workspaces.
48    *
49    * @param array $form
50    *   An associative array containing the structure of the form.
51    * @param \Drupal\Core\Form\FormStateInterface $form_state
52    *   The current state of the form.
53    * @param string $form_id
54    *   The form ID.
55    *
56    * @see hook_form_alter()
57    */
58   public function formAlter(array &$form, FormStateInterface $form_state, $form_id) {
59     // No alterations are needed in the default workspace.
60     if ($this->workspaceManager->getActiveWorkspace()->isDefaultWorkspace()) {
61       return;
62     }
63
64     // Add an additional validation step for every form if we are in a
65     // non-default workspace.
66     $this->addWorkspaceValidation($form);
67
68     // If a form has already been marked as safe or not to submit in a
69     // non-default workspace, we don't have anything else to do.
70     if ($form_state->has('workspace_safe')) {
71       return;
72     }
73
74     // No forms are safe to submit in a non-default workspace by default, except
75     // for the whitelisted ones defined below.
76     $workspace_safe = FALSE;
77
78     // Whitelist a few forms that we know are safe to submit.
79     $form_object = $form_state->getFormObject();
80     $is_workspace_form = $form_object instanceof WorkspaceFormInterface;
81     $is_search_form = in_array($form_object->getFormId(), ['search_block_form', 'search_form'], TRUE);
82     $is_views_exposed_form = $form_object instanceof ViewsExposedForm;
83     if ($is_workspace_form || $is_search_form || $is_views_exposed_form) {
84       $workspace_safe = TRUE;
85     }
86
87     $form_state->set('workspace_safe', $workspace_safe);
88   }
89
90   /**
91    * Adds our validation handler recursively on each element of a form.
92    *
93    * @param array &$element
94    *   An associative array containing the structure of the form.
95    */
96   protected function addWorkspaceValidation(array &$element) {
97     // Recurse through all children and add our validation handler if needed.
98     foreach (Element::children($element) as $key) {
99       if (isset($element[$key]) && $element[$key]) {
100         $this->addWorkspaceValidation($element[$key]);
101       }
102     }
103
104     if (isset($element['#validate'])) {
105       $element['#validate'][] = [get_called_class(), 'validateDefaultWorkspace'];
106     }
107   }
108
109   /**
110    * Validation handler which sets a validation error for all unsupported forms.
111    */
112   public static function validateDefaultWorkspace(array &$form, FormStateInterface $form_state) {
113     if ($form_state->get('workspace_safe') !== TRUE) {
114       $form_state->setError($form, new TranslatableMarkup('This form can only be submitted in the default workspace.'));
115     }
116   }
117
118 }