View source
<?php
namespace Drupal\media_directories_ui\Plugin\Field\FieldWidget;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\OpenModalDialogCommand;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\media\Entity\Media;
use Drupal\media_directories_ui\MediaDirectoriesLibraryState;
use Drupal\media_directories_ui\MediaDirectoriesLibraryUiBuilder;
use Drupal\media_library\Plugin\Field\FieldWidget\MediaLibraryWidget;
class MediaDirectoriesLibraryWidget extends MediaLibraryWidget {
public static function defaultSettings() {
return [
'media_types' => [],
] + parent::defaultSettings();
}
protected function getAllowedMediaTypeIdsSorted() {
$sorted_media_type_ids = $this
->getSetting('media_types');
$handler_settings = $this
->getFieldSetting('handler_settings');
$allowed_media_type_ids = isset($handler_settings['target_bundles']) ? $handler_settings['target_bundles'] : NULL;
if ($allowed_media_type_ids === []) {
return $allowed_media_type_ids;
}
if ($allowed_media_type_ids === NULL) {
$allowed_media_type_ids = $this->entityTypeManager
->getStorage('media_type')
->getQuery()
->execute();
}
if (empty($sorted_media_type_ids)) {
return $allowed_media_type_ids;
}
$new_media_type_ids = array_diff($allowed_media_type_ids, $sorted_media_type_ids);
$sorted_media_type_ids = array_merge($sorted_media_type_ids, array_values($new_media_type_ids));
$sorted_media_type_ids = array_intersect($sorted_media_type_ids, $allowed_media_type_ids);
return array_values($sorted_media_type_ids);
}
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$referenced_entities = $items
->referencedEntities();
$view_builder = $this->entityTypeManager
->getViewBuilder('media');
$field_name = $this->fieldDefinition
->getName();
$parents = $form['#parents'];
$id_suffix = $parents ? '-' . implode('-', $parents) : '';
$field_widget_id = implode(':', array_filter([
$field_name,
$id_suffix,
]));
$wrapper_id = $field_name . '-media-library-wrapper' . $id_suffix;
$limit_validation_errors = [
array_merge($parents, [
$field_name,
]),
];
$settings = $this
->getFieldSetting('handler_settings');
$element += [
'#type' => 'fieldset',
'#cardinality' => $this->fieldDefinition
->getFieldStorageDefinition()
->getCardinality(),
'#target_bundles' => isset($settings['target_bundles']) ? $settings['target_bundles'] : FALSE,
'#attributes' => [
'id' => $wrapper_id,
'class' => [
'media-library-widget',
],
],
'#attached' => [
'library' => [
'media_library/widget',
],
],
];
$allowed_media_type_ids = $this
->getAllowedMediaTypeIdsSorted();
if (!$allowed_media_type_ids) {
$element['no_types_message'] = [
'#markup' => $this
->getNoMediaTypesAvailableMessage(),
];
return $element;
}
if (empty($referenced_entities)) {
$element['empty_selection'] = [
'#type' => 'html_tag',
'#tag' => 'p',
'#value' => $this
->t('No media items are selected.'),
'#attributes' => [
'class' => [
'media-library-widget-empty-text',
],
],
];
}
else {
$element['weight_toggle'] = [
'#type' => 'html_tag',
'#tag' => 'button',
'#value' => $this
->t('Show media item weights'),
'#attributes' => [
'class' => [
'link',
'media-library-widget__toggle-weight',
'js-media-library-widget-toggle-weight',
],
],
];
}
$element['selection'] = [
'#type' => 'container',
'#attributes' => [
'class' => [
'js-media-library-selection',
'media-library-selection',
],
],
];
foreach ($referenced_entities as $delta => $media_item) {
$element['selection'][$delta] = [
'#type' => 'container',
'#attributes' => [
'class' => [
'media-library-item',
'media-library-item--grid',
'js-media-library-item',
],
'tabindex' => '-1',
'data-media-library-item-delta' => $delta,
],
'preview' => [
'#type' => 'container',
'remove_button' => [
'#type' => 'submit',
'#name' => $field_name . '-' . $delta . '-media-library-remove-button' . $id_suffix,
'#value' => $this
->t('Remove'),
'#media_id' => $media_item
->id(),
'#attributes' => [
'class' => [
'media-library-item__remove',
],
'aria-label' => $this
->t('Remove @label', [
'@label' => $media_item
->label(),
]),
],
'#ajax' => [
'callback' => [
static::class,
'updateWidget',
],
'wrapper' => $wrapper_id,
'progress' => [
'type' => 'throbber',
'message' => $this
->t('Removing @label.', [
'@label' => $media_item
->label(),
]),
],
],
'#submit' => [
[
static::class,
'removeItem',
],
],
'#limit_validation_errors' => $limit_validation_errors,
],
'rendered_entity' => $view_builder
->view($media_item, 'media_library'),
],
'target_id' => [
'#type' => 'hidden',
'#value' => $media_item
->id(),
],
'weight' => [
'#type' => 'number',
'#title' => $this
->t('Weight'),
'#default_value' => $delta,
'#attributes' => [
'class' => [
'js-media-library-item-weight',
'media-library-item__weight',
],
],
],
];
}
$cardinality_unlimited = $element['#cardinality'] === FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED;
$remaining = $element['#cardinality'] - count($referenced_entities);
if (!$cardinality_unlimited) {
if ($remaining) {
$cardinality_message = $this
->formatPlural($remaining, 'One media item remaining.', '@count media items remaining.');
}
else {
$cardinality_message = $this
->t('The maximum number of media items have been selected.');
}
if (!empty($element['#description'])) {
$element['#description'] .= '<br />';
}
$element['#description'] .= $cardinality_message;
}
$selected_type_id = reset($allowed_media_type_ids);
$remaining = $cardinality_unlimited ? FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED : $remaining;
$entity = $items
->getEntity();
$opener_parameters = [
'field_widget_id' => $field_widget_id,
'entity_type_id' => $entity
->getEntityTypeId(),
'bundle' => $entity
->bundle(),
'field_name' => $field_name,
];
if (!$entity
->isNew()) {
$opener_parameters['entity_id'] = (string) $entity
->id();
}
$state = MediaDirectoriesLibraryState::create('media_library.opener.field_widget', $allowed_media_type_ids, $selected_type_id, $remaining, $opener_parameters, MEDIA_DIRECTORY_ROOT);
$element['media_library_open_button'] = [
'#type' => 'submit',
'#value' => $this
->t('Add media'),
'#name' => $field_name . '-media-library-open-button' . $id_suffix,
'#attributes' => [
'class' => [
'media-library-open-button',
'js-media-library-open-button',
],
'data-disable-refocus' => 'true',
],
'#media_library_state' => $state,
'#ajax' => [
'callback' => [
static::class,
'openMediaLibrary',
],
'progress' => [
'type' => 'throbber',
'message' => $this
->t('Opening media library.'),
],
],
'#submit' => [],
'#limit_validation_errors' => [],
];
if (!$cardinality_unlimited && $remaining === 0) {
$element['media_library_open_button']['#attributes']['data-disabled-focus'] = 'true';
$element['media_library_open_button']['#attributes']['class'][] = 'visually-hidden';
}
$element['media_library_selection'] = [
'#type' => 'hidden',
'#attributes' => [
'data-media-library-widget-value' => $field_widget_id,
],
];
$element['media_library_update_widget'] = [
'#type' => 'submit',
'#value' => $this
->t('Update widget'),
'#name' => $field_name . '-media-library-update' . $id_suffix,
'#ajax' => [
'callback' => [
static::class,
'updateWidget',
],
'wrapper' => $wrapper_id,
'progress' => [
'type' => 'throbber',
'message' => $this
->t('Adding selection.'),
],
],
'#attributes' => [
'data-media-library-widget-update' => $field_widget_id,
'class' => [
'js-hide',
],
],
'#validate' => [
[
static::class,
'validateItems',
],
],
'#submit' => [
[
static::class,
'addItems',
],
],
'#limit_validation_errors' => $limit_validation_errors,
];
return $element;
}
public static function openMediaLibrary(array $form, FormStateInterface $form_state) {
$triggering_element = $form_state
->getTriggeringElement();
$library_ui = \Drupal::service('media_directories_ui.ui_builder')
->buildUi($triggering_element['#media_library_state']);
$dialog_options = MediaDirectoriesLibraryUiBuilder::dialogOptions();
return (new AjaxResponse())
->addCommand(new OpenModalDialogCommand($dialog_options['title'], $library_ui, $dialog_options));
}
protected static function getNewMediaItems(array $element, FormStateInterface $form_state) {
$values = $form_state
->getValues();
$path = $element['#parents'];
$value = NestedArray::getValue($values, $path);
if (!empty($value['media_library_selection'])) {
$ids = explode(',', $value['media_library_selection']);
$ids = array_filter($ids, 'is_numeric');
if (!empty($ids)) {
return Media::loadMultiple($ids);
}
}
return [];
}
}