44db509c3b14a0d4fba2c2a8d253afef2b5680fc
[yaffs-website] / web / modules / contrib / entityqueue / src / Form / EntityQueueForm.php
1 <?php
2
3 namespace Drupal\entityqueue\Form;
4
5 use Drupal\Component\Plugin\PluginManagerInterface;
6 use Drupal\Component\Utility\Html;
7 use Drupal\Core\Entity\BundleEntityFormBase;
8 use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface;
9 use Drupal\Core\Entity\EntityTypeRepositoryInterface;
10 use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
11 use Drupal\Core\Form\FormStateInterface;
12 use Psr\Log\LoggerInterface;
13 use Symfony\Component\DependencyInjection\ContainerInterface;
14
15 /**
16  * Base form for entity queue edit forms.
17  */
18 class EntityQueueForm extends BundleEntityFormBase {
19
20   /**
21    * The entity being used by this form.
22    *
23    * @var \Drupal\entityqueue\EntityQueueInterface
24    */
25   protected $entity;
26
27   /**
28    * The entity type repository.
29    *
30    * @var \Drupal\Core\Entity\EntityTypeRepositoryInterface
31    */
32   protected $entityTypeRepository;
33
34   /**
35    * The entity queue handler plugin manager.
36    *
37    * @var \Drupal\Component\Plugin\PluginManagerInterface
38    */
39   protected $entityQueueHandlerManager;
40
41   /**
42    * Selection manager service.
43    *
44    * @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface
45    */
46   protected $selectionManager;
47
48   /**
49    * A logger instance.
50    *
51    * @var \Psr\Log\LoggerInterface
52    */
53   protected $logger;
54
55   /**
56    * {@inheritdoc}
57    */
58   public static function create(ContainerInterface $container) {
59     return new static(
60       $container->get('entity_type.repository'),
61       $container->get('plugin.manager.entityqueue.handler'),
62       $container->get('plugin.manager.entity_reference_selection'),
63       $container->get('logger.factory')->get('entityqueue')
64     );
65   }
66
67   /**
68    * Constructs a EntityQueueForm.
69    *
70    * @param \Drupal\Core\Entity\EntityTypeRepositoryInterface
71    *   The entity type repository.
72    * @param \Drupal\Component\Plugin\PluginManagerInterface
73    *   The entity queue handler plugin manager.
74    * @param \Psr\Log\LoggerInterface $logger
75    *   A logger instance.
76    */
77   public function __construct(EntityTypeRepositoryInterface $entity_type_repository, PluginManagerInterface $entity_queue_handler_manager, SelectionPluginManagerInterface $selection_manager, LoggerInterface $logger) {
78     $this->entityTypeRepository = $entity_type_repository;
79     $this->entityQueueHandlerManager = $entity_queue_handler_manager;
80     $this->selectionManager = $selection_manager;
81     $this->logger = $logger;
82   }
83
84   /**
85    * {@inheritdoc}
86    */
87   public function form(array $form, FormStateInterface $form_state) {
88     $form = parent::form($form, $form_state);
89     $queue = $this->entity;
90
91     // Default to nodes as the queue target entity type.
92     $target_entity_type_id = $queue->getTargetEntityTypeId() ?: 'node';
93
94     $form['label'] = [
95       '#type' => 'textfield',
96       '#title' => $this->t('Name'),
97       '#maxlength' => 32,
98       '#size' => 32,
99       '#default_value' => $queue->label(),
100       '#description' => $this->t('The human-readable name of this entity queue. This name must be unique.'),
101       '#required' => TRUE,
102     ];
103
104     $form['id'] = [
105       '#type' => 'machine_name',
106       '#default_value' => $queue->id(),
107       '#machine_name' => [
108         'exists' => '\Drupal\entityqueue\Entity\EntityQueue::load',
109       ],
110       '#disabled' => !$queue->isNew(),
111     ];
112
113     $handlers = $this->entityQueueHandlerManager->getAllEntityQueueHandlers();
114     $form['handler'] = [
115       '#type' => 'radios',
116       '#title' => $this->t('Type'),
117       '#options' => $handlers,
118       '#default_value' => $queue->getHandler(),
119       '#required' => TRUE,
120       '#disabled' => !$queue->isNew(),
121     ];
122
123     $form['settings'] = [
124       '#type' => 'vertical_tabs',
125     ];
126
127     $form['queue_settings'] = [
128       '#type' => 'details',
129       '#title' => $this->t('Queue settings'),
130       '#open' => TRUE,
131       '#tree' => TRUE,
132       '#group' => 'settings',
133     ];
134     $form['queue_settings']['size'] = [
135       '#type' => 'container',
136       '#attributes' => ['class' => ['form--inline', 'clearfix']],
137       '#process' => [
138         [EntityReferenceItem::class, 'formProcessMergeParent']
139       ],
140     ];
141     $form['queue_settings']['size']['min_size'] = [
142       '#type' => 'number',
143       '#size' => 2,
144       '#default_value' => $queue->getMinimumSize(),
145       '#field_prefix' => $this->t('Restrict this queue to a minimum of'),
146     ];
147     $form['queue_settings']['size']['max_size'] = [
148       '#type' => 'number',
149       '#default_value' => $queue->getMaximumSize(),
150       '#field_prefix' => $this->t('and a maximum of'),
151       '#field_suffix' => $this->t('items.'),
152     ];
153     $form['queue_settings']['act_as_queue'] = [
154       '#type' => 'checkbox',
155       '#title' => $this->t('Act as queue'),
156       '#default_value' => $queue->getActAsQueue(),
157       '#description' => $this->t('When enabled, adding more than the maximum number of items will remove extra items from the top of the queue.'),
158       '#states' => [
159         'invisible' => [
160           ':input[name="queue_settings[max_size]"]' => ['value' => 0],
161         ],
162       ],
163     ];
164     $form['queue_settings']['reverse_in_admin'] = [
165       '#type' => 'checkbox',
166       '#title' => $this->t('Reverse order in admin view'),
167       '#default_value' => $queue->getReverseInAdmin(),
168       '#description' => $this->t('Ordinarily queues are arranged with the front of the queue (where items will be removed) on top and the back (where items will be added) on the bottom. If checked, this will display the queue such that items will be added to the top and removed from the bottom.'),
169     ];
170
171     // We have to duplicate all the code from
172     // \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::fieldSettingsForm()
173     // because field settings forms are not easily embeddable.
174     $form['entity_settings'] = [
175       '#type' => 'details',
176       '#title' => $this->t('Entity settings'),
177       '#open' => TRUE,
178       '#tree' => TRUE,
179       '#group' => 'settings',
180       '#weight' => -1,
181     ];
182
183     // Get all selection plugins for this entity type.
184     $selection_plugins = $this->selectionManager->getSelectionGroups($target_entity_type_id);
185     $selection_handlers_options = [];
186     foreach (array_keys($selection_plugins) as $selection_group_id) {
187       // We only display base plugins (e.g. 'default', 'views', ...) and not
188       // entity type specific plugins (e.g. 'default:node', 'default:user',
189       // ...).
190       if (array_key_exists($selection_group_id, $selection_plugins[$selection_group_id])) {
191         $selection_handlers_options[$selection_group_id] = Html::escape($selection_plugins[$selection_group_id][$selection_group_id]['label']);
192       }
193       elseif (array_key_exists($selection_group_id . ':' . $target_entity_type_id, $selection_plugins[$selection_group_id])) {
194         $selection_group_plugin = $selection_group_id . ':' . $target_entity_type_id;
195         $selection_handlers_options[$selection_group_plugin] = Html::escape($selection_plugins[$selection_group_id][$selection_group_plugin]['base_plugin_label']);
196       }
197     }
198     ksort($selection_handlers_options);
199
200     $form['entity_settings']['settings'] = [
201       '#type' => 'container',
202       '#process' => [
203         [EntityReferenceItem::class, 'fieldSettingsAjaxProcess'],
204         [EntityReferenceItem::class, 'formProcessMergeParent']
205       ],
206       '#element_validate' => [[get_class($this), 'entityReferenceSelectionSettingsValidate']],
207     ];
208
209     // @todo It should be up to the queue handler to determine what entity types
210     // are queue-able.
211     $form['entity_settings']['settings']['target_type'] = [
212       '#type' => 'select',
213       '#title' => $this->t('Type of items to queue'),
214       '#options' => $this->entityTypeRepository->getEntityTypeLabels(TRUE),
215       '#default_value' => $target_entity_type_id,
216       '#required' => TRUE,
217       '#disabled' => !$queue->isNew(),
218       '#size' => 1,
219       '#ajax' => TRUE,
220       '#limit_validation_errors' => [],
221     ];
222
223     $form['entity_settings']['settings']['handler'] = [
224       '#type' => 'select',
225       '#title' => $this->t('Reference method'),
226       '#options' => $selection_handlers_options,
227       '#default_value' => $queue->getEntitySettings()['handler'],
228       '#required' => TRUE,
229       '#ajax' => TRUE,
230       '#limit_validation_errors' => [],
231     ];
232     $form['entity_settings']['settings']['handler_submit'] = [
233       '#type' => 'submit',
234       '#value' => $this->t('Change handler'),
235       '#limit_validation_errors' => [],
236       '#attributes' => [
237         'class' => ['js-hide'],
238       ],
239       '#submit' => [[EntityReferenceItem::class, 'settingsAjaxSubmit']],
240     ];
241
242     $form['entity_settings']['settings']['handler_settings'] = [
243       '#type' => 'container',
244     ];
245
246     $selection_handler = $this->selectionManager->getInstance($queue->getEntitySettings());
247     $form['entity_settings']['settings']['handler_settings'] += $selection_handler->buildConfigurationForm([], $form_state);
248
249     // For entityqueue's purposes, the 'target_bundles' setting of the 'default'
250     // selection handler does not have to be required.
251     if (isset($form['entity_settings']['settings']['handler_settings']['target_bundles'])) {
252       $form['entity_settings']['settings']['handler_settings']['target_bundles']['#required'] = FALSE;
253     }
254
255     return $form;
256   }
257
258   /**
259    * Form element validation handler; Invokes selection plugin's validation.
260    *
261    * @param array $form
262    *   The form where the settings form is being included in.
263    * @param \Drupal\Core\Form\FormStateInterface $form_state
264    *   The form state of the (entire) configuration form.
265    */
266   public static function entityReferenceSelectionSettingsValidate(array $form, FormStateInterface $form_state) {
267     /** @var \Drupal\entityqueue\EntityQueueInterface $queue */
268     $queue = $form_state->getFormObject()->getEntity();
269
270     $selection_handler = \Drupal::service('plugin.manager.entity_reference_selection')->getInstance($queue->getEntitySettings());
271
272     // @todo Take care of passing the right $form and $form_state structures to
273     // the selection validation method. For now, we just have to duplicate the
274     // validation of the 'default' selection plugin.
275     $selection_handler->validateConfigurationForm($form, $form_state);
276
277     // If no checkboxes were checked for 'target_bundles', store NULL ("all
278     // bundles are referenceable") rather than empty array ("no bundle is
279     // referenceable".
280     if ($form_state->getValue(['entity_settings', 'handler_settings', 'target_bundles']) === []) {
281       $form_state->setValue(['entity_settings', 'handler_settings', 'target_bundles'], NULL);
282     }
283   }
284
285   /**
286    * {@inheritdoc}
287    */
288   public function buildEntity(array $form, FormStateInterface $form_state) {
289     $entity = parent::buildEntity($form, $form_state);
290     if ($handler = $entity->get('handler')) {
291       $entity->setHandler($handler);
292     }
293     return $entity;
294   }
295
296   /**
297    * {@inheritdoc}
298    */
299   public function save(array $form, FormStateInterface $form_state) {
300     $queue = $this->entity;
301     $status = $queue->save();
302
303     $edit_link = $queue->toLink($this->t('Edit'), 'edit-form')->toString();
304     if ($status == SAVED_UPDATED) {
305       drupal_set_message($this->t('The entity queue %label has been updated.', ['%label' => $queue->label()]));
306       $this->logger->notice('The entity queue %label has been updated.', ['%label' => $queue->label(), 'link' => $edit_link]);
307     }
308     else {
309       drupal_set_message($this->t('The entity queue %label has been added.', ['%label' => $queue->label()]));
310       $this->logger->notice('The entity queue %label has been added.', ['%label' => $queue->label(), 'link' =>  $edit_link]);
311     }
312
313     $form_state->setRedirectUrl($queue->toUrl('collection'));
314   }
315
316 }