Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
219 / 219
100.00% covered (success)
100.00%
18 / 18
CRAP
100.00% covered (success)
100.00%
1 / 1
AuthorizationProfileEditForm
100.00% covered (success)
100.00%
219 / 219
100.00% covered (success)
100.00%
18 / 18
53
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 create
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 getFormId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 form
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
1
 buildEntityForm
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 buildProviderConfigForm
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
3
 buildConsumerConfigForm
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
3
 buildAjaxProviderRowForm
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 buildAjaxConsumerRowForm
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 buildConditionsForm
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
1 / 1
8
 getProvider
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 getConsumer
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 buildMappingForm
100.00% covered (success)
100.00%
55 / 55
100.00% covered (success)
100.00%
1 / 1
8
 validateForm
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
4
 submitForm
100.00% covered (success)
100.00%
28 / 28
100.00% covered (success)
100.00%
1 / 1
9
 extractArrayByName
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 mappingsAjaxCallback
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 mappingsAddAnother
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\authorization\Form;
6
7use Drupal\Core\Entity\EntityTypeManagerInterface;
8use Drupal\Core\Form\FormStateInterface;
9use Drupal\authorization\Consumer\ConsumerPluginManager;
10use Drupal\authorization\Provider\ProviderPluginManager;
11use Symfony\Component\DependencyInjection\ContainerInterface;
12
13/**
14 * Authorization profile form.
15 *
16 * @package Drupal\authorization\Form
17 */
18final class AuthorizationProfileEditForm extends AuthorizationProfileForm {
19
20  /**
21   * Constructs a AuthorizationProfileForm.
22   *
23   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
24   *   The entity manager.
25   * @param \Drupal\authorization\Provider\ProviderPluginManager $provider_plugin_manager
26   *   The Provider plugin manager.
27   * @param \Drupal\authorization\Consumer\ConsumerPluginManager $consumer_plugin_manager
28   *   The Consumer plugin manager.
29   */
30  public function __construct(
31    EntityTypeManagerInterface $entity_type_manager,
32    ProviderPluginManager $provider_plugin_manager,
33    ConsumerPluginManager $consumer_plugin_manager,
34  ) {
35    $this->storage = $entity_type_manager->getStorage('authorization_profile');
36    $this->providerPluginManager = $provider_plugin_manager;
37    $this->consumerPluginManager = $consumer_plugin_manager;
38  }
39
40  /**
41   * {@inheritdoc}
42   */
43  public static function create(ContainerInterface $container) {
44    return new static(
45      $container->get('entity_type.manager'),
46      $container->get('plugin.manager.authorization.provider'),
47      $container->get('plugin.manager.authorization.consumer')
48    );
49  }
50
51  /**
52   * {@inheritdoc}
53   */
54  public function getFormId(): string {
55    return 'authorization_profile_edit_form';
56  }
57
58  /**
59   * {@inheritdoc}
60   */
61  public function form(array $form, FormStateInterface $form_state): array {
62    $form = parent::form($form, $form_state);
63    $form['#attached']['library'][] = 'authorization/profile';
64    $form['#prefix'] = "<div id='authorization-profile-form'>";
65    $this->buildEntityForm($form, $form_state, FALSE);
66    $form['configuration'] = [
67      '#type' => 'vertical_tabs',
68      '#weight' => 10,
69      '#default_tab' => 'conditions',
70    ];
71    $this->buildProviderConfigForm($form, $form_state);
72    $this->buildConsumerConfigForm($form, $form_state);
73    $this->buildConditionsForm($form, $form_state);
74    $this->buildMappingForm($form, $form_state);
75
76    $form['#suffix'] = "</div>";
77
78    return $form;
79  }
80
81  /**
82   * {@inheritdoc}
83   */
84  protected function buildEntityForm(array &$form, FormStateInterface $form_state, $is_new): void {
85    parent::buildEntityForm($form, $form_state, $is_new);
86    unset($form['provider']);
87    unset($form['consumer']);
88  }
89
90  /**
91   * Builds the provider-specific configuration form.
92   *
93   * @param array $form
94   *   An associative array containing the structure of the form.
95   * @param \Drupal\Core\Form\FormStateInterface $form_state
96   *   The current state of the form.
97   */
98  protected function buildProviderConfigForm(array &$form, FormStateInterface $form_state): void {
99    /** @var \Drupal\authorization\AuthorizationProfileInterface $authorization_profile */
100    $authorization_profile = $this->getEntity();
101
102    $form['provider_config'] = [
103      '#type' => 'details',
104      '#attributes' => [
105        'id' => 'authorization-provider-config-form',
106      ],
107      '#tree' => TRUE,
108      '#weight' => 0,
109      '#group' => 'configuration',
110    ];
111
112    if (!$authorization_profile->hasValidProvider()) {
113      return;
114    }
115    $provider = $authorization_profile->getProvider();
116    $provider_form = $provider->buildConfigurationForm([], $form_state);
117    if (empty($provider_form)) {
118      return;
119    }
120    // Modify the provider plugin configuration container element.
121    $form['provider_config']['#title'] = $this->t('Provider %plugin', ['%plugin' => $provider->label()]);
122    $form['provider_config']['#description'] = $provider->getDescription();
123    $form['provider_config']['#open'] = TRUE;
124    // Attach the provider plugin configuration form.
125    $form['provider_config'] += $provider_form;
126
127  }
128
129  /**
130   * Builds the consumer-specific configuration form.
131   *
132   * @param array $form
133   *   An associative array containing the structure of the form.
134   * @param \Drupal\Core\Form\FormStateInterface $form_state
135   *   The current state of the form.
136   */
137  protected function buildConsumerConfigForm(array &$form, FormStateInterface $form_state): void {
138    /** @var \Drupal\authorization\AuthorizationProfileInterface $authorization_profile */
139    $authorization_profile = $this->getEntity();
140
141    $form['consumer_config'] = [
142      '#type' => 'details',
143      '#attributes' => [
144        'id' => 'authorization-consumer-config-form',
145      ],
146      '#tree' => TRUE,
147      '#weight' => 50,
148      '#group' => 'configuration',
149    ];
150
151    if (!$authorization_profile->hasValidConsumer()) {
152      return;
153    }
154
155    $consumer = $authorization_profile->getConsumer();
156    $consumer_form = $consumer->buildConfigurationForm([], $form_state);
157    if (empty($consumer_form)) {
158      return;
159    }
160
161    $form['consumer_config']['#title'] = $this->t('Consumer %plugin', ['%plugin' => $consumer->label()]);
162    $form['consumer_config']['#description'] = $consumer->getDescription();
163    $form['consumer_config']['#open'] = TRUE;
164    // Attach the consumer plugin configuration form.
165    $form['consumer_config'] += $consumer_form;
166  }
167
168  /**
169   * Handles switching the selected provider plugin.
170   *
171   * @param array $form
172   *   An associative array containing the structure of the form.
173   * @param \Drupal\Core\Form\FormStateInterface $form_state
174   *   The current state of the form.
175   *
176   * @return array
177   *   Returns the provider mappings.
178   */
179  public static function buildAjaxProviderRowForm(array $form, FormStateInterface $form_state): array {
180    return $form['provider_mappings'];
181  }
182
183  /**
184   * Handles switching the selected consumer plugin.
185   *
186   * @param array $form
187   *   An associative array containing the structure of the form.
188   * @param \Drupal\Core\Form\FormStateInterface $form_state
189   *   The current state of the form.
190   *
191   * @return array
192   *   Returns the consumer mappings in the form.
193   */
194  public static function buildAjaxConsumerRowForm(array $form, FormStateInterface $form_state): array {
195    return $form['consumer_mappings'];
196  }
197
198  /**
199   * Build the conditions form.
200   *
201   * @param array $form
202   *   An associative array containing the structure of the form.
203   * @param \Drupal\Core\Form\FormStateInterface $form_state
204   *   The current state of the form.
205   */
206  protected function buildConditionsForm(array &$form, FormStateInterface $form_state): void {
207    /** @var \Drupal\authorization\AuthorizationProfileInterface $authorization_profile */
208    $authorization_profile = $this->getEntity();
209
210    $profile_is_invalid = !$authorization_profile->hasValidProvider() || !$authorization_profile->hasValidConsumer();
211    if ($profile_is_invalid) {
212      return;
213    }
214
215    $this->getProvider($authorization_profile);
216    $this->getConsumer($authorization_profile);
217
218    $tokens = [];
219
220    $tokens += $authorization_profile->getProvider()->getTokens();
221    $tokens += $authorization_profile->getConsumer()->getTokens();
222
223    $form['conditions'] = [
224      '#type' => 'details',
225      '#title' => $this->t('Conditions'),
226      '#open' => TRUE,
227      '#weight' => -50,
228      '#group' => 'configuration',
229    ];
230
231    $synchronization_modes = [];
232    if ($this->provider->isSyncOnLogonSupported()) {
233      $synchronization_modes['user_logon'] = $this->t('When a user logs on via <em>@provider_name</em>.', $tokens);
234    }
235
236    $form['conditions']['synchronization_modes'] = [
237      '#type' => 'checkboxes',
238      '#title' => $this->t('When should <em>@consumer_name</em> be granted/revoked from a user?', $tokens),
239      '#options' => $synchronization_modes,
240      '#default_value' => $authorization_profile->get('synchronization_modes') ? $authorization_profile->get('synchronization_modes') : [],
241      '#description' => '',
242    ];
243
244    $synchronization_actions = [];
245
246    if ($this->provider->revocationSupported()) {
247      $synchronization_actions['revoke_provider_provisioned'] = $this->t('Revoke <em>@consumer_name</em> grants previously granted by <em>@provider_name</em> in this profile.', $tokens);
248    }
249
250    if ($this->consumer->consumerTargetCreationAllowed()) {
251      $synchronization_actions['create_consumers'] = $this->t('Create <em>@consumer_name</em> targets if they do not exist.', $tokens);
252    }
253
254    $form['conditions']['synchronization_actions'] = [
255      '#type' => 'checkboxes',
256      '#title' => $this->t('What actions would you like performed when <em>@consumer_name</em> are granted/revoked from a user?', $tokens),
257      '#options' => $synchronization_actions,
258      '#default_value' => $authorization_profile->get('synchronization_actions') ? $authorization_profile->get('synchronization_actions') : [],
259    ];
260  }
261
262  /**
263   * Get the provider.
264   *
265   * @param \Drupal\authorization\AuthorizationProfileInterface $authorization_profile
266   *   The authorization profile.
267   */
268  protected function getProvider($authorization_profile): void {
269    $get_provider = !property_exists($this, 'provider') || !$this->provider;
270    if ($get_provider) {
271      $this->provider = $authorization_profile->getProvider();
272    }
273  }
274
275  /**
276   * Get the consumer.
277   *
278   * @param \Drupal\authorization\AuthorizationProfileInterface $authorization_profile
279   *   The authorization profile.
280   */
281  protected function getConsumer($authorization_profile): void {
282    $get_consumer = !property_exists($this, 'consumer') || !$this->consumer;
283    if ($get_consumer) {
284      $this->consumer = $authorization_profile->getConsumer();
285    }
286  }
287
288  /**
289   * Build the mapping form.
290   *
291   * @param array $form
292   *   An associative array containing the structure of the form.
293   * @param \Drupal\Core\Form\FormStateInterface $form_state
294   *   The current state of the form.
295   */
296  protected function buildMappingForm(array &$form, FormStateInterface $form_state): void {
297    /** @var \Drupal\authorization\AuthorizationProfileInterface $authorization_profile */
298    $authorization_profile = $this->getEntity();
299
300    if (($authorization_profile->hasValidProvider() || $form_state->getValue('provider')) &&
301      ($authorization_profile->hasValidConsumer()  || $form_state->getValue('consumer'))) {
302
303      $provider = $authorization_profile->getProvider();
304      $consumer = $authorization_profile->getConsumer();
305
306      $tokens = [];
307      $tokens += $provider->getTokens();
308      $tokens += $consumer->getTokens();
309
310      $form['mappings'] = [
311        '#type' => 'table',
312        '#responsive' => TRUE,
313        '#weight' => 0,
314        '#title' => $this->t('Configure mapping from @provider_name to @consumer_name', $tokens),
315        '#header' => [
316          $provider->label(),
317          $consumer->label(),
318          $this->t('Delete'),
319        ],
320        '#prefix' => '<div id="authorization-mappings-wrapper" class="authorization-mappings">',
321        '#suffix' => '</div>',
322      ];
323
324      $mappings_fields = $form_state->get('mappings_fields');
325      if (empty($mappings_fields)) {
326        $count_current_mappings = max(count($authorization_profile->getProviderMappings()), count($authorization_profile->getConsumerMappings()));
327        $mappings_fields = ($count_current_mappings > 0) ? $count_current_mappings - 1 : 1;
328        $form_state->set('mappings_fields', $mappings_fields);
329      }
330
331      for ($row_key = 0; $row_key <= $mappings_fields; $row_key++) {
332        $form['mappings'][$row_key]['provider_mappings'] = $provider->buildRowForm($form, $form_state, $row_key);
333        $form['mappings'][$row_key]['consumer_mappings'] = $consumer->buildRowForm($form, $form_state, $row_key);
334        $form['mappings'][$row_key]['delete'] = [
335          '#type' => 'checkbox',
336          '#default_value' => 0,
337        ];
338      }
339
340      $form['mappings'][]['mappings_add_another'] = [
341        '#type' => 'submit',
342        '#value' => $this->t('Add Another'),
343        '#submit' => ['::mappingsAddAnother'],
344        '#limit_validation_errors' => [],
345        '#ajax' => [
346          'callback' => '::mappingsAjaxCallback',
347          'wrapper' => 'authorization-mappings-wrapper',
348        ],
349        '#weight' => 103,
350        '#wrapper_attributes' => ['colspan' => 3],
351      ];
352
353      $form['mappings_provider_help'] = [
354        '#type' => 'markup',
355        '#markup' => $provider->buildRowDescription($form, $form_state),
356        '#weight' => 101,
357      ];
358
359      $form['mappings_consumer_help'] = [
360        '#type' => 'markup',
361        '#markup' => $consumer->buildRowDescription($form, $form_state),
362        '#weight' => 102,
363      ];
364    }
365  }
366
367  /**
368   * {@inheritdoc}
369   */
370  public function validateForm(array &$form, FormStateInterface $form_state): void {
371    parent::validateForm($form, $form_state);
372    /** @var \Drupal\authorization\AuthorizationProfileInterface $authorization_profile */
373    $authorization_profile = $this->getEntity();
374
375    if ($authorization_profile->hasValidProvider()) {
376      $provider_form_state = new SubFormState($form_state, ['provider_config']);
377      $authorization_profile->getProvider()
378        ->validateConfigurationForm($form['provider_config'], $provider_form_state);
379    }
380
381    if ($authorization_profile->hasValidConsumer()) {
382      $consumer_form_state = new SubFormState($form_state, ['consumer_config']);
383      $authorization_profile->getConsumer()
384        ->validateConfigurationForm($form['consumer_config'], $consumer_form_state);
385    }
386
387    if ($form_state->getValue('mappings')) {
388      $mappings_form_state = new SubFormState($form_state, ['mappings']);
389      $authorization_profile->getConsumer()
390        ->validateRowForm($form['mappings'], $mappings_form_state);
391      $authorization_profile->getProvider()
392        ->validateRowForm($form['mappings'], $mappings_form_state);
393    }
394
395  }
396
397  /**
398   * {@inheritdoc}
399   */
400  public function submitForm(array &$form, FormStateInterface $form_state) {
401    parent::submitForm($form, $form_state);
402    /** @var \Drupal\authorization\AuthorizationProfileInterface */
403    $authorization_profile = $this->getEntity();
404
405    // Check before loading the provider plugin so we don't throw an exception.
406    if ($authorization_profile->hasValidProvider()) {
407      $provider_form_state = new SubFormState($form_state, ['provider_config']);
408      $authorization_profile->getProvider()
409        ->submitConfigurationForm($form['provider_config'], $provider_form_state);
410    }
411    // Check before loading the consumer plugin so we don't throw an exception.
412    if ($authorization_profile->hasValidConsumer()) {
413      $consumer_form_state = new SubFormState($form_state, ['consumer_config']);
414      $authorization_profile->getConsumer()
415        ->submitConfigurationForm($form['consumer_config'], $consumer_form_state);
416    }
417
418    if ($form['mappings']) {
419      $mappings_form_state = new SubFormState($form_state, ['mappings']);
420      $authorization_profile->getConsumer()
421        ->submitRowForm($form['mappings'], $mappings_form_state);
422      $authorization_profile->getProvider()
423        ->submitRowForm($form['mappings'], $mappings_form_state);
424
425      $values = $form_state->getValues();
426
427      $provider_mappings = $this->extractArrayByName($values['mappings'], 'provider_mappings');
428      $consumer_mappings = $this->extractArrayByName($values['mappings'], 'consumer_mappings');
429
430      foreach ($values['mappings'] as $key => $value) {
431        if (empty($value) || $value['delete'] == 1) {
432          unset($provider_mappings[$key]);
433          unset($consumer_mappings[$key]);
434        }
435      }
436      $set_mappings = $provider_mappings && $consumer_mappings;
437      if ($set_mappings) {
438        $authorization_profile->setProviderMappings(array_values($provider_mappings));
439        $authorization_profile->setConsumerMappings(array_values($consumer_mappings));
440      }
441    }
442
443    return $authorization_profile;
444  }
445
446  /**
447   * Transform the array keyed by row to a separate array for each consumer.
448   *
449   * @param array $data
450   *   Source data from form.
451   * @param string $name
452   *   Which provisioner to filter by.
453   *
454   * @return array
455   *   Transformed array.
456   */
457  private function extractArrayByName(array $data, $name): array {
458    $mapping = [];
459    foreach ($data as $value) {
460      if (isset($value[$name])) {
461        $mapping[] = $value[$name];
462      }
463    }
464    return $mapping;
465  }
466
467  /**
468   * Ajax Callback for the form.
469   *
470   * @param array $form
471   *   The form being passed in.
472   * @param \Drupal\Core\Form\FormStateInterface $form_state
473   *   The form state.
474   *
475   * @return array
476   *   The form element we are changing via ajax
477   */
478  public function mappingsAjaxCallback(array &$form, FormStateInterface $form_state): array {
479    return $form['mappings'];
480  }
481
482  /**
483   * Functionality for our ajax callback.
484   *
485   * @param array $form
486   *   The form being passed in.
487   * @param \Drupal\Core\Form\FormStateInterface $form_state
488   *   The form state, passed by reference so we can modify.
489   */
490  public function mappingsAddAnother(array &$form, FormStateInterface $form_state): void {
491    $form_state->set('mappings_fields', ($form_state->get('mappings_fields') + 1));
492    $form_state->setRebuild();
493  }
494
495}