142f18abb224c656f39fa5767d490a24e5965781
[yaffs-website] / web / modules / contrib / ctools / src / Form / ContextConfigure.php
1 <?php
2
3 namespace Drupal\ctools\Form;
4
5
6 use Drupal\Core\Ajax\AjaxResponse;
7 use Drupal\Core\Ajax\CloseModalDialogCommand;
8 use Drupal\Core\Ajax\RedirectCommand;
9 use Drupal\Core\Entity\Entity;
10 use Drupal\Core\Entity\Plugin\DataType\EntityAdapter;
11 use Drupal\Core\Form\FormBase;
12 use Drupal\Core\Form\FormStateInterface;
13 use Drupal\Core\Plugin\Context\Context;
14 use Drupal\Core\Plugin\Context\ContextDefinition;
15 use Drupal\Core\Plugin\Context\ContextInterface;
16 use Drupal\Core\Url;
17 use Drupal\user\SharedTempStoreFactory;
18 use Symfony\Component\DependencyInjection\ContainerInterface;
19
20 abstract class ContextConfigure extends FormBase {
21
22   /**
23    * @var \Drupal\user\SharedTempStoreFactory
24    */
25   protected $tempstore;
26
27   /**
28    * @var string
29    */
30   protected $tempstore_id;
31
32   /**
33    * @var string;
34    */
35   protected $machine_name;
36
37   /**
38    * {@inheritdoc}
39    */
40   public static function create(ContainerInterface $container) {
41     return new static($container->get('user.shared_tempstore'));
42   }
43
44   function __construct(SharedTempStoreFactory $tempstore) {
45     $this->tempstore = $tempstore;
46   }
47
48   /**
49    * {@inheritdoc}
50    */
51   public function getFormId() {
52     return 'ctools_context_configure';
53   }
54
55   /**
56    * {@inheritdoc}
57    */
58   public function buildForm(array $form, FormStateInterface $form_state, $context_id = NULL, $tempstore_id = NULL, $machine_name = NULL) {
59     $this->tempstore_id = $tempstore_id;
60     $this->machine_name = $machine_name;
61     $cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
62     $contexts = $this->getContexts($cached_values);
63     $edit = FALSE;
64     if (!empty($contexts[$context_id])) {
65       $context = $contexts[$context_id];
66       $machine_name = $context_id;
67       $edit = TRUE;
68     }
69     else {
70       $context_definition = new ContextDefinition($context_id);
71       $context = new Context($context_definition);
72       $machine_name = '';
73     }
74     $label = $context->getContextDefinition()->getLabel();
75     $description = $context->getContextDefinition()->getDescription();
76     $data_type = $context->getContextDefinition()->getDataType();
77     $form['#attached']['library'][] = 'core/drupal.dialog.ajax';
78     $form['context_id'] = [
79       '#type' => 'value',
80       '#value' => $context_id
81     ];
82     $form['label'] = [
83       '#type' => 'textfield',
84       '#title' => $this->t('Label'),
85       '#default_value' => $label,
86       '#required' => TRUE,
87     ];
88     $form['machine_name'] = [
89       '#type' => 'machine_name',
90       '#title' => $this->t('Machine Name'),
91       '#default_value' => $machine_name,
92       '#required' => TRUE,
93       '#maxlength' => 128,
94       '#machine_name' => [
95         'source' => ['label'],
96         'exists' => [$this, 'contextExists'],
97       ],
98       '#disabled' => $this->disableMachineName($cached_values, $machine_name),
99     ];
100     $form['description'] = [
101       '#type' => 'textarea',
102       '#title' => $this->t('Description'),
103       '#default_value' => $description,
104     ];
105     if (strpos($data_type, 'entity:') === 0) {
106       list(, $entity_type) = explode(':', $data_type);
107       /** @var EntityAdapter $entity */
108       $entity = $edit ? $context->getContextValue() : NULL;
109       $form['context_value'] = [
110         '#type' => 'entity_autocomplete',
111         '#required' => TRUE,
112         '#target_type' => $entity_type,
113         '#default_value' => $entity,
114         '#title' => $this->t('Select entity'),
115       ];
116     }
117     else {
118       $value = $context->getContextData()->getValue();
119       $form['context_value'] = [
120         '#title' => $this->t('Set a context value'),
121         '#type' => 'textfield',
122         '#required' => TRUE,
123         '#default_value' => $value,
124       ];
125     }
126     $form['submit'] = [
127       '#type' => 'submit',
128       '#value' => $this->t('Save'),
129       '#ajax' => [
130         'callback' => [$this, 'ajaxSave'],
131       ]
132     ];
133     return $form;
134   }
135
136   /**
137    * {@inheritdoc}
138    */
139   public function validateForm(array &$form, FormStateInterface $form_state) {
140     // If these are not equal, then we're adding a new context and should not override an existing context.
141     if ($form_state->getValue('machine_name') != $form_state->getValue('context_id')) {
142       $machine_name = $form_state->getValue('machine_name');
143       $cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
144       if (!empty($this->getContexts($cached_values)[$machine_name])) {
145         $form_state->setError($form['machine_name'], $this->t('That machine name is in use by another context definition.'));
146       }
147     }
148   }
149
150   /**
151    * {@inheritdoc}
152    */
153   public function submitForm(array &$form, FormStateInterface $form_state) {
154     $cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
155     $contexts = $this->getContexts($cached_values);
156     if ($form_state->getValue('machine_name') != $form_state->getValue('context_id')) {
157       $data_type = $form_state->getValue('context_id');
158       $context_definition = new ContextDefinition($data_type, $form_state->getValue('label'), TRUE, FALSE, $form_state->getValue('description'));
159     }
160     else {
161       $context = $contexts[$form_state->getValue('machine_name')];
162       $context_definition = $context->getContextDefinition();
163       $context_definition->setLabel($form_state->getValue('label'));
164       $context_definition->setDescription($form_state->getValue('description'));
165     }
166     // We're dealing with an entity and should make sure it's loaded.
167     if (strpos($context_definition->getDataType(), 'entity:') === 0) {
168       list(, $entity_type) = explode(':', $context_definition->getDataType());
169       if (is_numeric($form_state->getValue('context_value'))) {
170         $value = \Drupal::entityTypeManager()->getStorage($entity_type)->load($form_state->getValue('context_value'));
171       }
172     }
173     // No loading required for non-entity values.
174     else {
175       $value = $form_state->getValue('context_value');
176     }
177     $context = new Context($context_definition, $value);
178
179     $cached_values = $this->addContext($cached_values, $form_state->getValue('machine_name'), $context);
180     $this->tempstore->get($this->tempstore_id)->set($this->machine_name, $cached_values);
181     list($route_name, $route_parameters) = $this->getParentRouteInfo($cached_values);
182     $form_state->setRedirect($route_name, $route_parameters);
183   }
184
185   public function ajaxSave(array &$form, FormStateInterface $form_state) {
186     $response = new AjaxResponse();
187     $cached_values = $this->tempstore->get($this->tempstore_id)->get($this->machine_name);
188     list($route_name, $route_parameters) = $this->getParentRouteInfo($cached_values);
189     $url = new Url($route_name, $route_parameters);
190     $response->addCommand(new RedirectCommand($url->toString()));
191     $response->addCommand(new CloseModalDialogCommand());
192     return $response;
193   }
194
195   /**
196    * Document the route name and parameters for redirect after submission.
197    *
198    * @param $cached_values
199    *
200    * @return array
201    *   In the format of
202    *   return ['route.name', ['machine_name' => $this->machine_name, 'step' => 'step_name]];
203    */
204   abstract protected function getParentRouteInfo($cached_values);
205
206   /**
207    * Custom logic for retrieving the contexts array from cached_values.
208    *
209    * @param $cached_values
210    *
211    * @return \Drupal\Core\Plugin\Context\ContextInterface[]
212    */
213   abstract protected function getContexts($cached_values);
214
215   /**
216    * Custom logic for adding a context to the cached_values contexts array.
217    *
218    * @param array $cached_values
219    *   The cached_values currently in use.
220    * @param string $context_id
221    *   The context identifier.
222    * @param \Drupal\Core\Plugin\Context\ContextInterface $context
223    *   The context to add or update within the cached values.
224    *
225    * @return mixed
226    *   Return the $cached_values
227    */
228   abstract protected function addContext($cached_values, $context_id, ContextInterface $context);
229
230   /**
231    * Custom "exists" logic for the context to be created.
232    *
233    * @param string $value
234    *   The name of the context.
235    * @param $element
236    *   The machine_name element
237    * @param \Drupal\Core\Form\FormStateInterface $form_state
238    *   The form state.
239    *
240    * @return bool
241    *   Return true if a context of this name exists.
242    */
243   abstract public function contextExists($value, $element, $form_state);
244
245   /**
246    * Determines if the machine_name should be disabled.
247    *
248    * @param $cached_values
249    *
250    * @return bool
251    */
252   abstract protected function disableMachineName($cached_values, $machine_name);
253
254 }