public static function MediaLibrary::processMediaLibrary in Media Library Form API Element 2.x
Same name and namespace in other branches
- 8 src/Element/MediaLibrary.php \Drupal\media_library_form_element\Element\MediaLibrary::processMediaLibrary()
Expand the media_library_element into it's required sub-elements.
Parameters
array $element: The base form element render array.
\Drupal\Core\Form\FormStateInterface $form_state: The form state object.
array $complete_form: The complete form render array.
Return value
array The form element render array.
Throws
\Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
\Drupal\Component\Plugin\Exception\PluginNotFoundException
File
- src/
Element/ MediaLibrary.php, line 51
Class
- MediaLibrary
- Provides a Media library form element.
Namespace
Drupal\media_library_form_element\ElementCode
public static function processMediaLibrary(array &$element, FormStateInterface $form_state, array &$complete_form) : array {
$default_value = NULL;
$referenced_entities = [];
if (!empty($element['#value'])) {
$default_value = $element['#value'];
}
if (!empty($default_value['media_selection_id'])) {
$entity_ids = [
$default_value['media_selection_id'],
];
}
else {
$entity_ids = array_filter(explode(',', $default_value));
}
if (!empty($entity_ids)) {
foreach ($entity_ids as $entity_id) {
$referenced_entities[] = \Drupal::entityTypeManager()
->getStorage('media')
->load($entity_id);
}
}
$view_builder = \Drupal::entityTypeManager()
->getViewBuilder('media');
$allowed_media_type_ids = $element['#allowed_bundles'];
$parents = $element['#parents'];
$field_name = array_pop($parents);
$attributes = $element['#attributes'] ?? [];
// Create an ID suffix from the parents to make sure each widget is unique.
$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,
]),
];
$element = array_merge($element, [
'#target_bundles' => !empty($allowed_media_type_ids) ? $allowed_media_type_ids : FALSE,
'#cardinality' => $element['#cardinality'] ?? 1,
'#attributes' => [
'id' => $wrapper_id,
'class' => [
'media-library-form-element',
],
],
'#modal_selector' => '#modal-media-library',
'#attached' => [
'library' => [
'media_library_form_element/media_library_form_element',
'media_library/view',
],
],
]);
if (empty($referenced_entities)) {
$element['empty_selection'] = [
'#type' => 'html_tag',
'#tag' => 'p',
'#value' => t('No media item selected.'),
'#attributes' => [
'class' => [
'media-library-form-element-empty-text',
],
],
];
}
$element['selection'] = [
'#type' => 'container',
'#attributes' => [
'class' => [
'js-media-library-selection',
'media-library-selection',
],
],
];
foreach ($referenced_entities as $delta => $referenced_entity) {
$element['selection'][$delta] = [
'#type' => 'container',
'#attributes' => [
'class' => [
'media-library-item',
'media-library-item--grid',
'js-media-library-item',
],
// Add the tabindex '-1' to allow the focus to be shifted to the next
// media item when an item is removed. We set focus to the container
// because we do not want to set focus to the remove button
// automatically.
// @see ::updateFormElement()
'tabindex' => '-1',
// Add a data attribute containing the delta to allow us to easily
// shift the focus to a specific media item.
// @see ::updateFormElement()
'data-media-library-item-delta' => $delta,
],
'preview' => [
'#type' => 'container',
'remove_button' => [
'#type' => 'submit',
'#name' => $field_name . '-' . $delta . '-media-library-remove-button' . $id_suffix,
'#value' => t('Remove'),
'#media_id' => $referenced_entity
->id(),
'#attributes' => [
'class' => [
'media-library-item__remove',
],
'aria-label' => t('Remove @label', [
'@label' => $referenced_entity
->label(),
]),
],
'#ajax' => [
'callback' => [
static::class,
'updateFormElement',
],
'wrapper' => $wrapper_id,
'progress' => [
'type' => 'throbber',
'message' => t('Removing @label.', [
'@label' => $referenced_entity
->label(),
]),
],
],
'#submit' => [
[
static::class,
'removeItem',
],
],
// Prevent errors in other widgets from preventing removal.
'#limit_validation_errors' => $limit_validation_errors,
],
// @todo Make the view mode configurable in https://www.drupal.org/project/drupal/issues/2971209
'rendered_entity' => $view_builder
->view($referenced_entity, 'media_library'),
'target_id' => [
'#type' => 'hidden',
'#value' => $referenced_entity
->id(),
],
],
'weight' => [
'#type' => 'number',
'#theme' => 'input__number__media_library_item_weight',
'#title' => \Drupal::translation()
->translate('Weight'),
'#default_value' => $delta,
'#attributes' => [
'class' => [
'js-media-library-item-weight',
],
],
],
];
}
$cardinality_unlimited = $element['#cardinality'] === FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED;
$remaining = $element['#cardinality'] - count($referenced_entities);
// Inform the user of how many items are remaining.
if (!$cardinality_unlimited) {
if ($remaining) {
$cardinality_message = \Drupal::translation()
->formatPlural($remaining, 'One media item remaining.', '@count media items remaining.');
}
else {
$cardinality_message = \Drupal::translation()
->translate('The maximum number of media items have been selected.');
}
// Add a line break between the field message and the cardinality message.
if (!empty($element['#description'])) {
$element['#description'] .= '<br />' . $cardinality_message;
}
else {
$element['#description'] = $cardinality_message;
}
}
// Create a new media library URL with the correct state parameters.
$selected_type_id = reset($allowed_media_type_ids);
$remaining = $cardinality_unlimited ? FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED : $remaining;
// This particular media library opener needs some extra metadata for its
// \Drupal\media_library\MediaLibraryOpenerInterface::getSelectionResponse()
// to be able to target the element
// whose 'data-media-library-form-element-value'
// attribute is the same as $field_widget_id. The entity ID, entity type ID,
// bundle, field name are used for access checking.
$opener_parameters = [
'field_widget_id' => $field_widget_id,
'field_name' => $field_name,
];
$state = MediaLibraryState::create('media_library.opener.form_element', $allowed_media_type_ids, $selected_type_id, $remaining, $opener_parameters);
// Add a button that will load the Media library in a modal using AJAX.
$element['media_library_open_button'] = [
'#type' => 'button',
'#value' => t('Add media'),
'#name' => $field_name . '-media-library-open-button' . $id_suffix,
'#attributes' => [
'class' => [
'media-library-open-button',
'js-media-library-open-button',
],
// The jQuery UI dialog automatically moves focus to the first :tabbable
// element of the modal, so we need to disable refocus on the button.
'data-disable-refocus' => 'true',
],
'#media_library_state' => $state,
'#ajax' => [
'callback' => [
static::class,
'openMediaLibrary',
],
'progress' => [
'type' => 'throbber',
'message' => t('Opening media library.'),
],
],
// Allow the media library to be opened even if there are form errors.
'#limit_validation_errors' => [],
];
// When the user returns from the modal to the widget, we want to shift the
// focus back to the open button. If the user is not allowed to add more
// items, the button needs to be disabled. Since we can't shift the focus to
// disabled elements, the focus is set back to the open button via
// JavaScript by adding the 'data-disabled-focus' attribute.
// @see Drupal.behaviors.MediaLibraryWidgetDisableButton
if (!$cardinality_unlimited && $remaining === 0) {
$element['media_library_open_button']['#attributes']['data-disabled-focus'] = 'true';
$element['media_library_open_button']['#attributes']['class'][] = 'visually-hidden';
}
// This hidden field and button are used to add new items to the widget.
$element['media_library_selection'] = [
'#type' => 'hidden',
'#attributes' => array_merge([
'data-media-library-form-element-value' => $field_widget_id,
], $attributes),
'#default_value' => $element['#value'],
];
// When a selection is made this hidden button is pressed to add new media
// items based on the "media_library_selection" value.
$element['media_library_update_widget'] = [
'#type' => 'submit',
'#value' => t('Update widget'),
'#name' => $field_name . '-media-library-update' . $id_suffix,
'#ajax' => [
'callback' => [
static::class,
'updateFormElement',
],
'wrapper' => $wrapper_id,
'progress' => [
'type' => 'throbber',
'message' => t('Adding selection.'),
],
],
'#attributes' => [
'data-media-library-form-element-update' => $field_widget_id,
'class' => [
'js-hide',
],
],
'#validate' => [
[
static::class,
'validateItem',
],
],
'#submit' => [
[
static::class,
'updateItem',
],
],
// Prevent errors in other widgets from preventing updates.
// Exclude other validations in case there is no data yet.
'#limit_validation_errors' => !empty($referenced_entities) ? $limit_validation_errors : [],
];
return $element;
}