4ac3b8438f821cbc55e2a6634b0e4cfdb8ac2240
[yaffs-website] / Form / ManageContext.php
1 <?php
2
3 namespace Drupal\ctools\Form;
4
5 use Drupal\Component\Serialization\Json;
6 use Drupal\Core\Ajax\AjaxResponse;
7 use Drupal\Core\Ajax\OpenModalDialogCommand;
8 use Drupal\Core\Form\FormBase;
9 use Drupal\Core\Form\FormBuilderInterface;
10 use Drupal\Core\Form\FormStateInterface;
11 use Drupal\Core\TypedData\TypedDataManagerInterface;
12 use Drupal\Core\Url;
13 use Symfony\Component\DependencyInjection\ContainerInterface;
14
15 abstract class ManageContext extends FormBase {
16
17   /**
18    * The machine name of the wizard we're working with.
19    *
20    * @var string
21    */
22   protected $machine_name;
23
24   /**
25    * The typed data manager.
26    *
27    * @var \Drupal\Core\TypedData\TypedDataManagerInterface
28    */
29   protected $typedDataManager;
30
31   /**
32    * The form builder.
33    *
34    * @var \Drupal\Core\Form\FormBuilderInterface
35    */
36   protected $formBuilder;
37
38   /**
39    * An array of property types that are eligible as relationships.
40    *
41    * @var array
42    */
43   protected $property_types = [];
44
45   /**
46    * A property for controlling usage of relationships in an implementation.
47    *
48    * @var bool
49    */
50   protected $relationships = TRUE;
51
52   /**
53    * {@inheritdoc}
54    */
55   public static function create(ContainerInterface $container) {
56     return new static($container->get('typed_data_manager'), $container->get('form_builder'));
57   }
58
59   /**
60    * ManageContext constructor.
61    *
62    * @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager
63    *   The typed data manager.
64    * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
65    *   The form builder.
66    */
67   public function __construct(TypedDataManagerInterface $typed_data_manager, FormBuilderInterface $form_builder) {
68     $this->typedDataManager = $typed_data_manager;
69     $this->formBuilder = $form_builder;
70   }
71
72
73   /**
74    * {@inheritdoc}
75    */
76   public function getFormId() {
77     return 'ctools_manage_context_form';
78   }
79
80   /**
81    * {@inheritdoc}
82    */
83   public function buildForm(array $form, FormStateInterface $form_state) {
84     $cached_values = $form_state->getTemporaryValue('wizard');
85     $this->machine_name = $cached_values['id'];
86     $form['items'] = array(
87       '#type' => 'markup',
88       '#prefix' => '<div id="configured-contexts">',
89       '#suffix' => '</div>',
90       '#theme' => 'table',
91       '#header' => array($this->t('Context ID'), $this->t('Label'), $this->t('Data Type'), $this->t('Options')),
92       '#rows' => $this->renderRows($cached_values),
93       '#empty' =>  $this->t('No contexts or relationships have been added.')
94     );
95     foreach ($this->typedDataManager->getDefinitions() as $type => $definition) {
96       $types[$type] = $definition['label'];
97     }
98     if (isset($types['entity'])) {
99       unset($types['entity']);
100     }
101     asort($types);
102     $form['context'] = [
103       '#type' => 'select',
104       '#options' => $types,
105     ];
106     $form['add'] = [
107       '#type' => 'submit',
108       '#name' => 'add',
109       '#value' => $this->t('Add new context'),
110       '#ajax' => [
111         'callback' => [$this, 'addContext'],
112         'event' => 'click',
113       ],
114       '#submit' => [
115         'callback' => [$this, 'submitForm'],
116       ]
117     ];
118
119     $form['relationships'] = [
120       '#type' => 'select',
121       '#title' => $this->t('Add a relationship'),
122       '#options' => $this->getAvailableRelationships($cached_values),
123       '#access' => $this->relationships,
124     ];
125     $form['add_relationship'] = [
126       '#type' => 'submit',
127       '#name' => 'add_relationship',
128       '#value' =>  $this->t('Add Relationship'),
129       '#ajax' => [
130         'callback' => [$this, 'addRelationship'],
131         'event' => 'click',
132       ],
133       '#submit' => [
134         'callback' => [$this, 'submitForm'],
135       ],
136       '#access' => $this->relationships,
137     ];
138     return $form;
139   }
140
141   /**
142    * {@inheritdoc}
143    */
144   public function submitForm(array &$form, FormStateInterface $form_state) {
145     if ($form_state->getTriggeringElement()['#name'] == 'add') {
146       $cached_values = $form_state->getTemporaryValue('wizard');
147       list(, $route_parameters) = $this->getContextOperationsRouteInfo($cached_values, $this->machine_name, $form_state->getValue('context'));
148       $form_state->setRedirect($this->getContextAddRoute($cached_values), $route_parameters);
149     }
150     if ($form_state->getTriggeringElement()['#name'] == 'add_relationship') {
151       $cached_values = $form_state->getTemporaryValue('wizard');
152       list(, $route_parameters) = $this->getRelationshipOperationsRouteInfo($cached_values, $this->machine_name, $form_state->getValue('relationships'));
153       $form_state->setRedirect($this->getRelationshipAddRoute($cached_values), $route_parameters);
154     }
155   }
156
157   public function addContext(array &$form, FormStateInterface $form_state) {
158     $context = $form_state->getValue('context');
159     $content = $this->formBuilder->getForm($this->getContextClass(), $context, $this->getTempstoreId(), $this->machine_name);
160     $content['#attached']['library'][] = 'core/drupal.dialog.ajax';
161     $cached_values = $form_state->getTemporaryValue('wizard');
162     list(, $route_parameters) = $this->getContextOperationsRouteInfo($cached_values, $this->machine_name, $context);
163     $content['submit']['#attached']['drupalSettings']['ajax'][$content['submit']['#id']]['url'] = $this->url($this->getContextAddRoute($cached_values), $route_parameters, ['query' => [FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]]);
164     $response = new AjaxResponse();
165     $response->addCommand(new OpenModalDialogCommand($this->t('Add new context'), $content, array('width' => '700')));
166     return $response;
167   }
168
169   public function addRelationship(array &$form, FormStateInterface $form_state) {
170     $relationship = $form_state->getValue('relationships');
171     $content = $this->formBuilder->getForm($this->getRelationshipClass(), $relationship, $this->getTempstoreId(), $this->machine_name);
172     $content['#attached']['library'][] = 'core/drupal.dialog.ajax';
173     $cached_values = $form_state->getTemporaryValue('wizard');
174     list(, $route_parameters) = $this->getRelationshipOperationsRouteInfo($cached_values, $this->machine_name, $relationship);
175     $content['submit']['#attached']['drupalSettings']['ajax'][$content['submit']['#id']]['url'] = $this->url($this->getRelationshipAddRoute($cached_values), $route_parameters, ['query' => [FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]]);
176     $response = new AjaxResponse();
177     $response->addCommand(new OpenModalDialogCommand($this->t('Configure Relationship'), $content, array('width' => '700')));
178     return $response;
179   }
180
181   protected function getAvailableRelationships($cached_values) {
182     /** @var \Drupal\ctools\TypedDataResolver $resolver */
183     $resolver = \Drupal::service('ctools.typed_data.resolver');
184     return $resolver->getTokensForContexts($this->getContexts($cached_values));
185   }
186
187   /**
188    * @param $cached_values
189    *
190    * @return array
191    */
192   protected function renderRows($cached_values) {
193     $contexts = array();
194     foreach ($this->getContexts($cached_values) as $row => $context) {
195       list($route_name, $route_parameters) = $this->getContextOperationsRouteInfo($cached_values, $this->machine_name, $row);
196       $build = array(
197         '#type' => 'operations',
198         '#links' => $this->getOperations($cached_values, $row, $route_name, $route_parameters),
199       );
200       $contexts[$row] = array(
201         $row,
202         $context->getContextDefinition()->getLabel(),
203         $context->getContextDefinition()->getDataType(),
204         'operations' => [
205           'data' => $build,
206         ],
207       );
208     }
209     return $contexts;
210   }
211
212   /**
213    * @param array $cached_values
214    * @param string $row
215    * @param string $route_name_base
216    * @param array $route_parameters
217    *
218    * @return mixed
219    */
220   protected function getOperations($cached_values, $row, $route_name_base, array $route_parameters = array()) {
221     $operations = [];
222     if ($this->isEditableContext($cached_values, $row)) {
223       $operations['edit'] = array(
224         'title' =>  $this->t('Edit'),
225         'url' => new Url($route_name_base . '.edit', $route_parameters),
226         'weight' => 10,
227         'attributes' => array(
228           'class' => ['use-ajax'],
229           'data-dialog-type' => 'modal',
230           'data-dialog-options' => Json::encode([
231             'width' => 700,
232           ]),
233         ),
234       );
235       $operations['delete'] = array(
236         'title' =>  $this->t('Delete'),
237         'url' => new Url($route_name_base . '.delete', $route_parameters),
238         'weight' => 100,
239         'attributes' => array(
240           'class' => array('use-ajax'),
241           'data-dialog-type' => 'modal',
242           'data-dialog-options' => Json::encode([
243             'width' => 700,
244           ]),
245         ),
246       );
247     }
248     return $operations;
249   }
250
251   /**
252    * Return a subclass of '\Drupal\ctools\Form\ContextConfigure'.
253    *
254    * The ContextConfigure class is designed to be subclassed with custom
255    * route information to control the modal/redirect needs of your use case.
256    *
257    * @return string
258    */
259   abstract protected function getContextClass($cached_values);
260
261   /**
262    * Return a subclass of '\Drupal\ctools\Form\RelationshipConfigure'.
263    *
264    * The RelationshipConfigure class is designed to be subclassed with custom
265    * route information to control the modal/redirect needs of your use case.
266    *
267    * @return string
268    */
269   abstract protected function getRelationshipClass($cached_values);
270
271   /**
272    * The route to which context 'add' actions should submit.
273    *
274    * @return string
275    */
276   abstract protected function getContextAddRoute($cached_values);
277
278   /**
279    * The route to which relationship 'add' actions should submit.
280    *
281    * @return string
282    */
283   abstract protected function getRelationshipAddRoute($cached_values);
284
285   /**
286    * Provide the tempstore id for your specified use case.
287    *
288    * @return string
289    */
290   abstract protected function getTempstoreId();
291
292   /**
293    * Returns the contexts already available in the wizard.
294    *
295    * @param mixed $cached_values
296    *
297    * @return \Drupal\Core\Plugin\Context\ContextInterface[]
298    */
299   abstract protected function getContexts($cached_values);
300
301   /**
302    * @param mixed $cached_values
303    * @param string $machine_name
304    * @param string $row
305    *
306    * @return array
307    */
308   abstract protected function getContextOperationsRouteInfo($cached_values, $machine_name, $row);
309
310   /**
311    * @param mixed $cached_values
312    * @param string $machine_name
313    * @param string $row
314    *
315    * @return array
316    */
317   abstract protected function getRelationshipOperationsRouteInfo($cached_values, $machine_name, $row);
318
319   /**
320    * @param mixed $cached_values
321    * @param string $row
322    *
323    * @return bool
324    */
325   abstract protected function isEditableContext($cached_values, $row);
326
327 }