monster_menus-9.0.x-dev/modules/mm_media/src/Form/MMMediaLibrary.php

modules/mm_media/src/Form/MMMediaLibrary.php
<?php

namespace Drupal\mm_media\Form;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\AlertCommand;
use Drupal\Core\Ajax\CloseDialogCommand;
use Drupal\Core\Ajax\CloseModalDialogCommand;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Ajax\OpenDialogCommand;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Url;
use Drupal\editor\Ajax\EditorDialogSave;
use Drupal\editor\EditorInterface;
use Drupal\file\Entity\File;
use Drupal\media\Entity\Media;
use Drupal\media_library\MediaLibraryState;
use Drupal\mm_media\Ajax\MediaUpdatedCommand;
use Drupal\mm_media\Plugin\EntityBrowser\Widget\MMTree;
use Drupal\mm_media\TemporaryMediaTrait;
use Drupal\monster_menus\Constants;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;

class MMMediaLibrary extends FormBase {

  use TemporaryMediaTrait;

  /**
   * The entity repository.
   *
   * @var \Drupal\Core\Entity\EntityRepositoryInterface
   */
  protected $entityRepository;

  /**
   * The entity display repository.
   *
   * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
   */
  protected $entityDisplayRepository;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The form builder.
   *
   * @var \Drupal\Core\Form\FormBuilderInterface
   */
  protected $formBuilder;

  /**
   * Constructs a EditorMediaDialog object.
   *
   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
   *   The entity repository.
   * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
   *   The entity display repository.
   */
  public function __construct(EntityRepositoryInterface $entity_repository, EntityDisplayRepositoryInterface $entity_display_repository, EntityTypeManagerInterface $entity_type_manager, FormBuilderInterface $form_builder) {
    $this->entityRepository = $entity_repository;
    $this->entityDisplayRepository = $entity_display_repository;
    $this->entityTypeManager = $entity_type_manager;
    $this->formBuilder = $form_builder;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity.repository'),
      $container->get('entity_display.repository'),
      $container->get('entity_type.manager'),
      $container->get('form_builder')
    );
  }

  /**
   * @inheritDoc
   */
  public function getFormId() {
    return 'mm_media_library';
  }

  /**
   * @param array $form
   *   A nested array form elements comprising the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   * @param \Drupal\editor\EditorInterface|null $editor
   *   The text editor to which this dialog corresponds.
   */
  public function buildForm(array $form, FormStateInterface $form_state, EditorInterface $editor = NULL) {
    $this_mmtid = $this->getRouteMatch()->getParameter('mm_tree') ?: mm_home_mmtid();
    $pop_start = implode('/', mm_content_get_parents_with_self($this_mmtid));

    $form['#attached']['library'][] = 'mm_media/mmmedialibrary_editing';
    $form['#attached']['library'][] = 'editor/drupal.editor.dialog';

    $state = MediaLibraryState::fromRequest($this->getRequest());
    $allowed_types = implode(',', $state->getAllowedTypeIds()) . ',' . MMTree::FILE2MEDIA_TYPE;

    $form['errors'] = [
      '#prefix' => '<div id="mm-media-library-errors">',
      '#suffix' => '</div>',
    ];
    $form['browser'] = [
      '#title' => $this->t('Media'),
      '#type' => 'mm_medialist',
      '#default_value' => ['' => $this->t('(choose a media item)')],
      '#mm_list_popup_start' => $pop_start,
      '#mm_list_selectable' => Constants::MM_PERMS_READ,
      '#mm_list_file_types' => $allowed_types,
      '#mm_list_min' => 1,
      '#mm_list_max' => 1,
      '#mm_list_auto_choose' => TRUE,
      '#mm_list_instance_start' => 100,
      '#mm_list_hide_left_pane' => TRUE,
      '#ajax' => [
        'callback' => [static::class, 'updatePreview'],
        'event' => 'change',
        'wrapper' => 'mmmedialibrary-preview',
      ]
    ];
    $form['actions'] = [
      '#type' => 'actions',
    ];
    $form['actions']['insert'] = [
      '#type' => 'button',
      '#value' => t('Insert'),
      '#button_type' => 'button',
      '#ajax' => [
        'callback' => '::submitForm',
        'event' => 'click',
      ],
    ];
    $form['actions']['cancel'] = [
      '#type' => 'button',
      '#value' => t('Cancel'),
      '#button_type' => 'button',
    ];

    $media_embed_filter = $editor->getFilterFormat()->filters()->get('media_embed');
    $current_view_mode = $form_state->getValue(['attributes', 'data-view-mode']) ?: $media_embed_filter->settings['default_view_mode'];

    // Store the default from the MediaEmbed filter, so that if the selected
    // view mode matches the default, we can drop the 'data-view-mode'
    // attribute.
    $form_state->set('filter_default_view_mode', $media_embed_filter->settings['default_view_mode']);

    $attributes = [
      '#tree' => TRUE,
      'data-view-mode' => [
        '#type' => 'hidden',
        '#value' => $current_view_mode,
      ],
    ];
    $preview = [];
    $settings = [
      '#type' => 'submit',
      '#access' => FALSE,
    ];
    if ($media = $this->getMedia($form_state)) {
      $form_state->set('mm_media', $media);
      [$mid, $fid] = $this->getMediaIDs($form_state);
      $settings = [
        '#type' => 'submit',
        '#value' => $this->t('Edit Properties'),
        '#name' => 'mm_media_library_edit_media',
        '#ajax' => [
          'url' => Url::fromRoute('mm_media_library.edit_media', ['media_id' => $mid, 'file_id' => $fid]),
          'disable-refocus' => TRUE,
        ],
        '#attributes' => [
          'class' => ['edit-button'],
        ],
        '#access' => $media->access('update'),
      ];
      $view_mode_options = array_intersect_key($this->entityDisplayRepository->getViewModeOptionsByBundle($media->getEntityTypeId(), $media->bundle()), $editor->getFilterFormat()->filters()->get('media_embed')->settings['allowed_view_modes']);
      $attributes['data-view-mode'] = [
        '#title' => $this->t('Display'),
        '#type' => 'select',
        '#options' => $view_mode_options,
        '#default_value' => $current_view_mode,
        '#access' => count($view_mode_options) >= 2,
        '#ajax' => [
          'callback' => '::updatePreview',
          'event' => 'change',
          'wrapper' => 'mmmedialibrary-preview',
        ]
      ];
      $preview = $this->entityTypeManager
        ->getViewBuilder($media->getEntityTypeId())
        ->view($media, $current_view_mode);
      $preview['#weight'] = 10;
    }
    $form['media'] = [
      '#prefix' => '<div id="mmmedialibrary-preview" style="clear: both">',
      'settings' => $settings,
      'attributes' => $attributes,
      'preview' => $preview,
      '#suffix' => '</div>',
    ];

    return $form;
  }

  /**
   * @inheritDoc
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $response = new AjaxResponse();

    // When the `alt` attribute is set to two double quotes, transform it to the
    // empty string: two double quotes signify "empty alt attribute". See above.
    if (trim($form_state->getValue(['attributes', 'alt'], '')) === '""') {
      $form_state->setValue(['attributes', 'alt'], '""');
    }

    // The `alt` attribute is optional: if it isn't set, the default value
    // simply will not be overridden. It's important to set it to FALSE
    // instead of unsetting the value.  This way we explicitly inform
    // the client side about the new value.
    if ($form_state->hasValue(['attributes', 'alt']) && trim($form_state->getValue(['attributes', 'alt'])) === '') {
      $form_state->setValue(['attributes', 'alt'], FALSE);
    }

    // If the selected view mode matches the default on the filter, remove the
    // attribute.
    if (!empty($form_state->get('filter_default_view_mode')) && $form_state->getValue(['attributes', 'data-view-mode']) === $form_state->get('filter_default_view_mode')) {
      $form_state->setValue(['attributes', 'data-view-mode'], FALSE);
    }

    if ($form_state->hasAnyErrors()) {
      $form['status_messages'] = [
        '#type' => 'status_messages',
        '#weight' => -1000,
      ];
      $response->addCommand(new HtmlCommand('#mm-media-library-errors', $form['status_messages']));
    }
    else {
      if ($media = $this->getMedia($form_state)) {
        if ($media->isNew()) {
          // ::getMedia() created a temporary Media item, so save it now.
          $media->save();
        }
        // Only send back the relevant values.
        $values = [
          'hasCaption' => $form_state->getValue('hasCaption'),
          'attributes' => $form_state->getValue('attributes') + [
              'data-entity-type' => $media->getEntityTypeId(),
              'data-entity-uuid' => $media->uuid(),
              'data-align' => 'left',
            ],
        ];
        $response->addCommand(new EditorDialogSave($values));
      }
      $response->addCommand(new CloseModalDialogCommand());
    }

    return $response;
  }

  public static function updatePreview(array $form, FormStateInterface $form_state) {
    return $form['media'];
  }

  public function editMedia($media_id, $file_id, Request $request) {
    $trigger_name = $request->request->get('_triggering_element_name');
    $edit_button = $trigger_name && str_contains($trigger_name, 'edit_button');

    if ($edit_button) {
      // Remove posted values from original form to prevent
      // data leakage into this form when the form is of the same bundle.
      $original_request = $request->request;
      $request->request = new ParameterBag();
    }

    if ($media_id) {
      $entity = Media::load($media_id);
    }
    else {
      $entity = $this->createTemporaryMedia(File::load($file_id));
      // Copy mapped fields from the File to the Media.
      $media_source = $entity->getSource();
      foreach (array_keys($entity->getTranslationLanguages()) as $langcode) {
        if ($entity->hasTranslation($langcode)) {
          $translation = $entity->getTranslation($langcode);
          // Try to set fields provided by the media source and mapped in
          // media type config.
          foreach ($translation->get('bundle')->entity->getFieldMap() as $metadata_attribute_name => $entity_field_name) {
            // Only save value in the entity if the field is empty or if the
            // source field changed.
            if ($translation->hasField($entity_field_name) && $translation->get($entity_field_name)->isEmpty()) {
              $translation->set($entity_field_name, $media_source->getMetadata($translation, $metadata_attribute_name));
            }
          }

          // Try to set a default name for this media item if no name is provided.
          if ($translation->get('name')->isEmpty()) {
            $translation->setName($translation->getName());
          }
        }
      }
    }
    if (empty($entity)) {
      return;
    }

    // Use edit form class if it exists, otherwise use default form class.
    $entity_type = $entity->getEntityType();
    if ($entity_type->getFormClass('edit')) {
      $operation = 'edit';
    }
    elseif ($entity_type->getFormClass('default')) {
      $operation = 'default';
    }

    if (!empty($operation)) {
      // Build the entity edit form.
      $form_object = $this->entityTypeManager->getFormObject($entity->getEntityTypeId(), $operation);
      $form_object->setEntity($entity);
      $form_state = (new FormState())
        ->setFormObject($form_object)
        ->disableRedirect();
      // Building the form also submits.
      $form = $this->formBuilder->buildForm($form_object, $form_state);
    }

    // Restore original request now that the edit form is built.
    // This fixes a bug where closing modal and re-opening it would
    // cause two modals to open.
    if ($edit_button) {
      $request->request = $original_request;
    }

    // Return a response, depending on whether it's successfully submitted.
    if (!empty($operation) && $form_state && !$form_state->isExecuted()) {
      // Return the form as a modal dialog.
      $form['#id'] = 'mm-media-edit-form';
      $form['#attached']['library'][] = 'core/drupal.dialog.ajax';
      $title = $this->t('Edit @entity', ['@entity' => $entity->label()]);
      return (new AjaxResponse())->addCommand(new OpenDialogCommand('#mm-media-edit-form', $title, $form, ['modal' => TRUE, 'width' => 800]));
    }
    // Return command for closing the modal.
    $response = (new AjaxResponse())->addCommand(new CloseDialogCommand('#mm-media-edit-form'));
    // Also refresh the preview.
    $response->addCommand(new MediaUpdatedCommand($form_object->getEntity()->id()));
    // Remove previous status messages.
    if (!empty($form_state) && $form_state->getFormObject()) {
      $form_state->getFormObject()->messenger()->deleteByType(MessengerInterface::TYPE_STATUS);
    }
    // Show error messages.
    $form['status_messages'] = [
      '#type' => 'status_messages',
      '#weight' => -1000,
    ];
    $response->addCommand(new HtmlCommand('#mm-media-library-errors', $form['status_messages']));

    if (empty($operation)) {
      $response->addCommand(new AlertCommand($this->t("An edit form couldn't be found.")));
    }

    return $response;
  }

  public function accessEditMedia($media_id, $file_id) {
    if ($media_id) {
      return ($media = Media::load($media_id)) ? $media->access('update', NULL, TRUE) : AccessResult::forbidden();
    }
    return ($file = File::load($file_id)) ? $file->access('view', NULL, TRUE) : AccessResult::forbidden();
  }

  private function getMediaIDs(FormStateInterface $form_state) {
    if ($item = mm_ui_mmlist_key0($form_state->getValue('browser'))) {
      [, $fid, $mid] = explode('/', $item);
      return $mid > 0 ? [$mid, 0] : [0, $fid];
    }
  }

  private function getMedia(FormStateInterface $form_state) {
    if ([$mid, $fid] = $this->getMediaIDs($form_state)) {
      if ($mid) {
        return Media::load($mid);
      }
      if ($file = File::load($fid)) {
        return $this->createTemporaryMedia($file);
      }
    }
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc