3 namespace Drupal\media_library\Plugin\views\field;
5 use Drupal\Core\Ajax\AjaxResponse;
6 use Drupal\Core\Ajax\CloseDialogCommand;
7 use Drupal\Core\Ajax\InvokeCommand;
8 use Drupal\Core\Form\FormBuilderInterface;
9 use Drupal\Core\Form\FormStateInterface;
11 use Drupal\views\Plugin\views\field\FieldPluginBase;
12 use Drupal\views\Render\ViewsRenderPipelineMarkup;
13 use Drupal\views\ResultRow;
14 use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
17 * Defines a field that outputs a checkbox and form for selecting media.
19 * @ViewsField("media_library_select_form")
23 class MediaLibrarySelectForm extends FieldPluginBase {
28 public function getValue(ResultRow $row, $field = NULL) {
29 return '<!--form-item-' . $this->options['id'] . '--' . $row->index . '-->';
35 public function render(ResultRow $values) {
36 return ViewsRenderPipelineMarkup::create($this->getValue($values));
40 * Form constructor for the media library select form.
43 * An associative array containing the structure of the form.
44 * @param \Drupal\Core\Form\FormStateInterface $form_state
45 * The current state of the form.
47 public function viewsForm(array &$form, FormStateInterface $form_state) {
48 // Only add the bulk form options and buttons if there are results.
49 if (empty($this->view->result)) {
53 // Render checkboxes for all rows.
54 $form[$this->options['id']]['#tree'] = TRUE;
55 foreach ($this->view->result as $row_index => $row) {
56 $entity = $this->getEntity($row);
57 $form[$this->options['id']][$row_index] = [
58 '#type' => 'checkbox',
59 '#title' => $this->t('Select @label', [
60 '@label' => $entity->label(),
62 '#title_display' => 'invisible',
63 '#return_value' => $entity->id(),
67 // @todo Remove in https://www.drupal.org/project/drupal/issues/2504115
68 // Currently the default URL for all AJAX form elements is the current URL,
69 // not the form action. This causes bugs when this form is rendered from an
70 // AJAX path like /views/ajax, which cannot process AJAX form submits.
71 $url = parse_url($form['#action'], PHP_URL_PATH);
72 $query = \Drupal::request()->query->all();
73 $query[FormBuilderInterface::AJAX_FORM_REQUEST] = TRUE;
74 $form['actions']['submit']['#ajax'] = [
75 'url' => Url::fromUserInput($url),
79 'callback' => [static::class, 'updateWidget'],
82 $form['actions']['submit']['#value'] = $this->t('Select media');
83 $form['actions']['submit']['#field_id'] = $this->options['id'];
87 * Submit handler for the media library select form.
90 * An associative array containing the structure of the form.
91 * @param \Drupal\Core\Form\FormStateInterface $form_state
92 * The current state of the form.
94 * @return \Drupal\Core\Ajax\AjaxResponse
95 * A command to send the selection to the current field widget.
97 public static function updateWidget(array &$form, FormStateInterface $form_state) {
98 $widget_id = \Drupal::request()->query->get('media_library_widget_id');
99 if (!$widget_id || !is_string($widget_id)) {
100 throw new BadRequestHttpException('The "media_library_widget_id" query parameter is required and must be a string.');
102 $field_id = $form_state->getTriggeringElement()['#field_id'];
103 $selected = array_values(array_filter($form_state->getValue($field_id, [])));
104 // Pass the selection to the field widget based on the current widget ID.
105 return (new AjaxResponse())
106 ->addCommand(new InvokeCommand("[data-media-library-widget-value=\"$widget_id\"]", 'val', [implode(',', $selected)]))
107 ->addCommand(new InvokeCommand("[data-media-library-widget-update=\"$widget_id\"]", 'trigger', ['mousedown']))
108 ->addCommand(new CloseDialogCommand());
114 public function viewsFormValidate(array &$form, FormStateInterface $form_state) {
115 $selected = array_filter($form_state->getValue($this->options['id']));
116 if (empty($selected)) {
117 $form_state->setErrorByName('', $this->t('No items selected.'));
124 public function clickSortable() {