mercury_editor-2.0.x-dev/src/Entity/MercuryEditorBlockContentForm.php

src/Entity/MercuryEditorBlockContentForm.php
<?php

namespace Drupal\mercury_editor\Entity;

use Drupal\Core\Render\Element;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Form\FormStateInterface;
use Drupal\block_content\BlockContentForm;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\Core\Block\TitleBlockPluginInterface;
use Drupal\Core\Plugin\ContextAwarePluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Defines the Mercury Editor block content form.
 *
 * Note that this class extends an internal entity form class to provide
 * additional functionality specific to the Mercury Editor context.
 *
 * @phpstan-ignore-next-line
 */
class MercuryEditorBlockContentForm extends BlockContentForm {

  use MercuryEditorEntityFormTrait;

  /**
   * The plugin.manager.block service.
   *
   * @var \Drupal\Component\Plugin\PluginManagerInterface
   */
  protected $pluginManagerBlock;

  /**
   * The context repository service.
   *
   * @var \Drupal\Core\Plugin\Context\ContextRepositoryInterface
   */
  protected $contextRepository;

  /**
   * The plugin context handler.
   *
   * @var \Drupal\Core\Plugin\Context\ContextHandlerInterface
   */
  protected $contextHandler;

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $account;

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * The current route match.
   *
   * @var \Drupal\Core\Routing\RouteMatchInterface
   */
  protected $routeMatch;

  /**
   * The title resolver.
   *
   * @var \Drupal\Core\Controller\TitleResolverInterface
   */
  protected $titleResolver;

  /**
   * Injects dependencies from the container.
   */
  public function injectDependencies(ContainerInterface $container) {
    $this->tempstore = $container->get('mercury_editor.tempstore_repository');
    $this->layoutParagraphsTempstore = $container->get('layout_paragraphs.tempstore_repository');
    $this->iFrameAjaxResponseWrapper = $container->get('mercury_editor.iframe_ajax_response_wrapper');
    $this->entityTypeManager = $container->get('entity_type.manager');
    $this->pluginManagerBlock = $container->get('plugin.manager.block');
    $this->mercuryEditorContextService = $container->get('mercury_editor.context');
    $this->contextRepository = $container->get('context.repository');
    $this->contextHandler = $container->get('context.handler');
    $this->routeMatch = $container->get('current_route_match');
    $this->titleResolver = $container->get('title_resolver');
    $this->account = $container->get('current_user');
  }

  /**
   * {@inheritDoc}
   */
  public function setDefaultEntityValues() {
    $this->entity->name = 'New block';
  }

  /**
   * Ajax callback for rendering the form.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   */
  public function ajaxCallback(array &$form, FormStateInterface $form_state) {
    $form['#updated'] = TRUE;
    $response = new AjaxResponse();

    if (empty($form_state->getErrors())) {
      $selector = '[data-me-edit-screen-key="' . $this->entity->uuid() . '"]';
      $view = $this->buildBlock('block_content:' . $this->entity->uuid());
      $this->iFrameAjaxResponseWrapper->addCommand(new ReplaceCommand($selector, $view));
      $response->addCommand($this->iFrameAjaxResponseWrapper->getWrapperCommand());
    }
    else {
      $form['#attributes']['class'][] = 'unsaved-changes';
    }
    $response->addCommand(new ReplaceCommand('.me-entity-form', $form));

    return $response;
  }

  /**
   * Returns a block render array.
   *
   * @param string $id
   *   The block id.
   * @param array $configuration
   *   The block configuration.
   * @param bool $wrapper
   *   Whether or not use block template for rendering.
   *
   * @return array
   *   The built block.
   */
  protected function buildBlock(string $id, array $configuration = [], bool $wrapper = TRUE) {

    $is_preview = $this->mercuryEditorContextService->isPreview();
    $this->mercuryEditorContextService->setPreview(TRUE);

    $configuration += ['label_display' => BlockPluginInterface::BLOCK_LABEL_VISIBLE];
    /** @var \Drupal\Core\Block\BlockPluginInterface $block_plugin */
    $block_plugin = $this->pluginManagerBlock->createInstance($id, $configuration);

    // Inject runtime contexts.
    if ($block_plugin instanceof ContextAwarePluginInterface) {
      $contexts = $this->contextRepository->getRuntimeContexts($block_plugin->getContextMapping());
      $this->contextHandler->applyContextMapping($block_plugin, $contexts);
    }

    $build = [];
    $access = $block_plugin->access($this->account, TRUE);
    if ($access->isAllowed()) {
      // Title block needs a special treatment.
      if ($block_plugin instanceof TitleBlockPluginInterface) {
        // Account for the scenario that a NullRouteMatch is returned. This, for
        // example, is the case when Search API is indexing the site during
        // Drush cron.
        if ($route = $this->routeMatch->getRouteObject()) {
          $request = $this->requestStack->getCurrentRequest();
          $title = $this->titleResolver->getTitle($request, $route);
          $block_plugin->setTitle($title);
        }
      }

      // Place the content returned by the block plugin into a 'content' child
      // element, as a way to allow the plugin to have complete control of its
      // properties and rendering (for instance, its own #theme) without
      // conflicting with the properties used above.
      $build['content'] = $block_plugin->build();

      if ($block_plugin instanceof TitleBlockPluginInterface) {
        $build['content']['#cache']['contexts'][] = 'url';
      }
      // Some blocks return null instead of array when empty.
      // @see https://www.drupal.org/project/drupal/issues/3212354
      if ($wrapper && is_array($build['content']) && !Element::isEmpty($build['content'])) {
        $build += [
          '#theme' => 'block',
          '#id' => $configuration['id'] ?? NULL,
          '#attributes' => [],
          '#contextual_links' => [],
          '#configuration' => $block_plugin->getConfiguration(),
          '#plugin_id' => $block_plugin->getPluginId(),
          '#base_plugin_id' => $block_plugin->getBaseId(),
          '#derivative_plugin_id' => $block_plugin->getDerivativeId(),
        ];
        // Semantically, the content returned by the plugin is the block, and in
        // particular, #attributes and #contextual_links is information about
        // the *entire* block. Therefore, we must move these properties into the
        // top-level element.
        foreach (['#attributes', '#contextual_links'] as $property) {
          if (isset($build['content'][$property])) {
            $build[$property] = $build['content'][$property];
            unset($build['content'][$property]);
          }
        }
      }
    }

    CacheableMetadata::createFromRenderArray($build)
      ->addCacheableDependency($access)
      ->addCacheableDependency($block_plugin)
      ->applyTo($build);

    if (!isset($build['#cache']['keys'])) {
      $build['#cache']['keys'] = [
        'mercury_editor',
        $id,
        '[configuration]=' . hash('sha256', serialize($configuration)),
        '[wrapper]=' . (int) $wrapper,
      ];
    }

    $this->mercuryEditorContextService->setPreview($is_preview);
    return $build;
  }

}

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

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