lb_plus-1.0.x-dev/src/NewMedia.php

src/NewMedia.php
<?php

declare(strict_types=1);

namespace Drupal\lb_plus;

use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Component\Uuid\UuidInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Block\BlockManagerInterface;
use Drupal\navigation_plus\ModePluginManager;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\navigation_plus\Controller\MediaDropzoneJs;
use Drupal\Core\DependencyInjection\ClassResolverInterface;

/**
 * New media.
 *
 * Common functionality shared by NavigationPlusNewMedia and
 * MediaBlockFileAssociationForm.
 */
final class NewMedia {

  use LbPlusRebuildTrait;

  public function __construct(
    protected UuidInterface $uuid,
    protected Dropzones $dropzones,
    protected RequestStack $requestStack,
    protected FormBuilderInterface $formBuilder,
    protected BlockManagerInterface $blockManager,
    protected ClassResolverInterface $classResolver,
    protected SectionStorageHandler $sectionStorageHandler,
    protected EntityTypeManagerInterface $entityTypeManager,
    protected EntityFieldManagerInterface $entityFieldManager,
  ) {}

  /**
   * Create media block.
   *
   * @param string $association
   *   The Block Content bundle.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return \Drupal\Core\Ajax\AjaxResponse|void
   *
   * @throws \Drupal\Component\Plugin\Exception\ContextException
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function createMediaBlock(string $association, FormStateInterface $form_state) {
    $file = $this->requestStack->getCurrentRequest()->getSession()->get('uploaded_file');
    [
      $section_storage,
      $nested_storage_path,
      $parameters,
      $current_section_storage,
    ] = $this->getSectionStorageDetails($form_state);
    [$media_bundle, $field_name] = $this->getMediaReferenceInfo($association, $form_state);

    assert(!empty($field_name));
    assert(!empty($media_bundle));

    $media_dropzone_js = $this->classResolver->getInstanceFromDefinition(MediaDropzoneJs::class);
    $media = $media_dropzone_js->createMedia($file, array_key_first($media_bundle));

    $plugin_id = "inline_block:$association";
    $block_plugin = $this->dropzones->createBlockPlugin($plugin_id, $current_section_storage);
    $block_content = $this->dropzones->createBlockContent($block_plugin);
    $block_content->set($field_name, [
      'target_id' => $media->id(),
    ]);
    $configuration = $block_plugin->getConfiguration();
    $configuration['block_serialized'] = serialize($block_content);
    $configuration['label_display'] = 0;
    $block_plugin->setConfiguration($configuration);

    $destination = [
      'type' => $parameters['dropzoneType'],
    ];
    if ($parameters['dropzoneType'] === 'region') {
      $destination['section'] = $parameters['section'];
      $destination['preceding_block_uuid'] = $parameters['precedingBlock'];
      $destination['region'] = $parameters['region'];
    }
    if ($parameters['dropzoneType'] === 'section') {
      $destination['section'] = $parameters['precedingSection'];
    }

    [$section, $section_delta] = $this->dropzones->getSection($destination, $current_section_storage);
    if ($parameters['dropzoneType'] === 'section') {
      $destination['region'] = $section->getDefaultRegion();
    }
    $component = $this->dropzones->insertBlock($destination, $block_plugin, $section);
    $section_storage = $this->sectionStorageHandler->updateSectionStorage($section_storage, $nested_storage_path, $current_section_storage);

    $response = $this->rebuildLayout($section_storage, $nested_storage_path);

    if ($form_state->get('update_settings_sidebar')) {
      // Update and reveal the preferred association in the settings sidebar.
      $sidebars = [];
      $edit_mode = $this->modeManager()->createInstance('edit');
      $edit_mode->buildSidebars($sidebars, $edit_mode);
      if (!empty($sidebars['navigation_plus_right_sidebar']['right_sidebars']['edit_mode_settings'])) {
        $response->addCommand(new ReplaceCommand('#edit-mode-settings', $sidebars['navigation_plus_right_sidebar']['right_sidebars']['edit_mode_settings']));
        $response->addCommand(new InvokeCommand(NULL, 'NavigationPlusOpenFileAssociationSettings'));
      }
    }

    $form_state->set('rebuild_layout_response', $response);
    return $response;
  }

  /**
   * Get Section Storage Details.
   *
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return array
   *   An array of section storage details.
   * @throws \Exception
   */
  public function getSectionStorageDetails(FormStateInterface $form_state): array {
    $entity = $form_state->get('entity');
    $section_storage = $this->sectionStorageHandler->getSectionStorage($entity);
    $nested_storage_path = NULL;
    $parameters = $form_state->get('query_parameters');
    if ($parameters['nestedStoragePath']) {
      $nested_storage_path = $parameters['nestedStoragePath'];
    }
    $current_section_storage = $this->sectionStorageHandler->getCurrentSectionStorage($section_storage, $nested_storage_path);
    return [
      $section_storage,
      $nested_storage_path,
      $parameters,
      $current_section_storage,
    ];
  }

  /**
   * Get media reference info.
   *
   * @param string $association
   *   The Block Content bundle.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *
   * @return array
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function getMediaReferenceInfo(string $association, FormStateInterface $form_state): array {
    $block_content_type = $this->entityTypeManager->getStorage('block_content_type')->load($association);
    $file_extension = $form_state->get('file_extension');
    $file_extension = strtolower($file_extension);
    $compatible_media_types = $this->getCompatibleMediaTypes($file_extension);
    $compatible_media_type_ids = array_map(function($media_type) {
      return $media_type->id();
    }, $compatible_media_types);
    $fields = $this->entityFieldManager->getFieldDefinitions('block_content', $block_content_type->id());
    foreach ($fields as $field) {
      if ($field->getType() === 'entity_reference' && $field->getSetting('target_type') === 'media') {
        $handler_settings = $field->getSetting('handler_settings');
        $allowed_media_types = $handler_settings['target_bundles'] ?? [];

        // If no specific bundles are set (empty array), all media types are allowed.
        // Or if there's an overlap with compatible media types, include this block content type.
        if (empty($allowed_media_types) || $media_bundle = array_intersect($allowed_media_types, $compatible_media_type_ids)) {
          $field_name = $field->getName();
          break;
        }
      }
    }
    return [$media_bundle, $field_name];
  }

  /**
   * Get compatible media types.
   *
   * @param string $file_extension
   *   A file extension e.g. jpg
   *
   * @return array
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function getCompatibleMediaTypes(string $file_extension): array {
    $media_types = $this->entityTypeManager->getStorage('media_type')->loadMultiple();
    $compatible_media_types = [];
    foreach ($media_types as $media_type) {
      $source_config = $media_type->getSource()->getConfiguration();
      $source_field = $source_config['source_field'] ?? NULL;

      if ($source_field) {
        $field_config = $this->entityTypeManager->getStorage('field_config')->load('media.' . $media_type->id() . '.' . $source_field);

        if ($field_config && in_array($field_config->getType(), [
            'file',
            'image',
          ])) {
          $allowed_extensions = $field_config->getSetting('file_extensions');

          if (empty($allowed_extensions)) {
            $compatible_media_types[] = $media_type->label();
          }
          else {
            $extensions_array = explode(' ', strtolower($allowed_extensions));
            if (in_array($file_extension, $extensions_array)) {
              $compatible_media_types[] = $media_type;
            }
          }
        }
      }
    }
    return $compatible_media_types;
  }

  public function modeManager() {
    return \Drupal::service('plugin.manager.modes');
  }

}

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

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