You are here

class PanelsIPEPageController in Panels 8.3

Same name and namespace in other branches
  1. 8.4 panels_ipe/src/Controller/PanelsIPEPageController.php \Drupal\panels_ipe\Controller\PanelsIPEPageController

Contains all JSON endpoints required for Panels IPE + Page Manager.

Hierarchy

Expanded class hierarchy of PanelsIPEPageController

File

panels_ipe/src/Controller/PanelsIPEPageController.php, line 32

Namespace

Drupal\panels_ipe\Controller
View source
class PanelsIPEPageController extends ControllerBase {
  use PanelsIPEBlockRendererTrait;

  /**
   * @var \Drupal\Core\Block\BlockManagerInterface
   */
  protected $blockManager;

  /**
   * @var \Drupal\Core\Render\RendererInterface
   */
  protected $renderer;

  /**
   * @var \Drupal\layout_plugin\Plugin\Layout\LayoutPluginManagerInterface
   */
  protected $layoutPluginManager;

  /**
   * The Panels storage manager.
   *
   * @var \Drupal\panels\Storage\PanelsStorageManagerInterface
   */
  protected $panelsStorage;

  /**
   * @var \Drupal\user\SharedTempStore
   */
  protected $tempStore;

  /**
   * @var \Drupal\panels_ipe\Helpers\UpdateLayoutRequestHandler
   */
  private $updateLayoutRequestHandler;

  /**
   * @var \Drupal\panels_ipe\Helpers\RemoveBlockRequestHandler
   */
  private $removeBlockRequestHandler;

  /**
   * Constructs a new PanelsIPEController.
   *
   * @param \Drupal\Core\Block\BlockManagerInterface $block_manager
   * @param \Drupal\Core\Render\RendererInterface $renderer
   * @param \Drupal\layout_plugin\Plugin\Layout\LayoutPluginManagerInterface $layout_plugin_manager
   * @param \Drupal\panels\Storage\PanelsStorageManagerInterface $panels_storage_manager
   * @param \Drupal\user\SharedTempStoreFactory $temp_store_factory
   * @param \Drupal\Core\Plugin\Context\ContextHandlerInterface $context_handler
   */
  public function __construct(BlockManagerInterface $block_manager, RendererInterface $renderer, LayoutPluginManagerInterface $layout_plugin_manager, PanelsStorageManagerInterface $panels_storage_manager, SharedTempStoreFactory $temp_store_factory, ContextHandlerInterface $context_handler) {
    $this->blockManager = $block_manager;
    $this->renderer = $renderer;
    $this->layoutPluginManager = $layout_plugin_manager;
    $this->panelsStorage = $panels_storage_manager;
    $this->tempStore = $temp_store_factory
      ->get('panels_ipe');
    $this->contextHandler = $context_handler;
    $this->updateLayoutRequestHandler = new UpdateLayoutRequestHandler($this
      ->moduleHandler(), $this->panelsStorage, $this->tempStore);
    $this->removeBlockRequestHandler = new RemoveBlockRequestHandler($this
      ->moduleHandler(), $this->panelsStorage, $this->tempStore);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static($container
      ->get('plugin.manager.block'), $container
      ->get('renderer'), $container
      ->get('plugin.manager.layout_plugin'), $container
      ->get('panels.storage_manager'), $container
      ->get('user.shared_tempstore'), $container
      ->get('context.handler'));
  }

  /**
   * Takes the current Page Variant and returns a possibly modified Page Variant
   * based on what's in TempStore for this user.
   *
   * @param string $panels_storage_type
   *   The Panels storage plugin which holds the Panels display.
   * @param string $panels_storage_id
   *   The id within the Panels storage plugin for this Panels display.
   *
   * @return \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant|NULL
   */
  protected function loadPanelsDisplay($panels_storage_type, $panels_storage_id) {

    /** @var \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant $panels_display */
    $panels_display = $this->panelsStorage
      ->load($panels_storage_type, $panels_storage_id);

    // If a temporary configuration for this variant exists, use it.
    if ($variant_config = $this->tempStore
      ->get($panels_display
      ->id())) {
      $panels_display
        ->setConfiguration($variant_config);
    }
    return $panels_display;
  }

  /**
   * Removes any temporary changes to the variant.
   *
   * @param string $panels_storage_type
   *   The id of the storage plugin.
   * @param string $panels_storage_id
   *   The id within the storage plugin for the requested Panels display.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   *
   * @throws \Drupal\user\TempStoreException
   */
  public function cancel($panels_storage_type, $panels_storage_id) {
    $panels_display = $this
      ->loadPanelsDisplay($panels_storage_type, $panels_storage_id);

    // If a temporary configuration for this variant exists, use it.
    $temp_store_key = $panels_display
      ->id();
    if ($variant_config = $this->tempStore
      ->get($temp_store_key)) {
      $this->tempStore
        ->delete($temp_store_key);
    }

    // Return an empty JSON response.
    return new JsonResponse();
  }

  /**
   * Gets a list of available Layouts, without wrapping HTML.
   *
   * @param string $panels_storage_type
   *   The id of the storage plugin.
   * @param string $panels_storage_id
   *   The id within the storage plugin for the requested Panels display.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   */
  public function getLayouts($panels_storage_type, $panels_storage_id) {
    $panels_display = $this
      ->loadPanelsDisplay($panels_storage_type, $panels_storage_id);

    // Get the current layout.
    $current_layout_id = $panels_display
      ->getLayout()
      ->getPluginId();

    // Get a list of all available layouts.
    $layouts = $this->layoutPluginManager
      ->getDefinitions();
    $base_path = base_path();
    $data = [];
    foreach ($layouts as $id => $layout) {
      $icon = !empty($layout['icon']) ? $layout['icon'] : drupal_get_path('module', 'panels') . '/images/no-layout-preview.png';
      $data[] = [
        'id' => $id,
        'label' => $layout['label'],
        'icon' => $base_path . $icon,
        'current' => $id == $current_layout_id,
        'category' => $layout['category'],
      ];
    }

    // Return a structured JSON response for our Backbone App.
    return new JsonResponse($data);
  }

  /**
   * Gets a layout configuration form for the requested layout.
   *
   * @param string $panels_storage_type
   *   The id of the storage plugin.
   * @param string $panels_storage_id
   *   The id within the storage plugin for the requested Panels display.
   * @param string $layout_id
   *   The machine name of the requested layout.
   *
   * @return \Drupal\Core\Ajax\AjaxResponse
   */
  public function getLayoutForm($panels_storage_type, $panels_storage_id, $layout_id) {
    $panels_display = $this
      ->loadPanelsDisplay($panels_storage_type, $panels_storage_id);

    // Build a Block Plugin configuration form.
    $form = $this
      ->formBuilder()
      ->getForm('Drupal\\panels_ipe\\Form\\PanelsIPELayoutForm', $layout_id, $panels_display);

    // Return the rendered form as a proper Drupal AJAX response.
    $response = new AjaxResponse();
    $command = new AppendCommand('.ipe-layout-form', $form);
    $response
      ->addCommand($command);
    return $response;
  }

  /**
   * Updates (PUT) an existing Layout in this Variant.
   *
   * @param string $panels_storage_type
   *   The id of the storage plugin.
   * @param string $panels_storage_id
   *   The id within the storage plugin for the requested Panels display.
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The current request.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   */
  public function handleUpdateLayoutRequest($panels_storage_type, $panels_storage_id, Request $request) {
    $panels_display = $this
      ->loadPanelsDisplay($panels_storage_type, $panels_storage_id);
    $this->updateLayoutRequestHandler
      ->handleRequest($panels_display, $request);
    return $this->updateLayoutRequestHandler
      ->getJsonResponse();
  }

  /**
   * Stores changes to the temporary storage.
   *
   * @param string $panels_storage_type
   *   The id of the storage plugin.
   * @param string $panels_storage_id
   *   The id within the storage plugin for the requested Panels display.
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The current request.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   */
  public function handleUpdateLayoutTempStorageRequest($panels_storage_type, $panels_storage_id, Request $request) {
    $panels_display = $this
      ->loadPanelsDisplay($panels_storage_type, $panels_storage_id);
    $this->updateLayoutRequestHandler
      ->handleRequest($panels_display, $request, TRUE);
    return $this->updateLayoutRequestHandler
      ->getJsonResponse();
  }

  /**
   * Creates (POST) a new Layout for this Variant.
   *
   * @param string $panels_storage_type
   *   The id of the storage plugin.
   * @param string $panels_storage_id
   *   The id within the storage plugin for the requested Panels display.
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The current request.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   */
  public function handleCreateLayoutRequest($panels_storage_type, $panels_storage_id, Request $request) {

    // For now, creating and updating a layout is the same thing.
    return $this
      ->handleUpdateLayoutRequest($panels_storage_type, $panels_storage_id, $request);
  }

  /**
   * Removes a block from the layout.
   *
   * @param string $panels_storage_type
   *   The id of the storage plugin.
   * @param string $panels_storage_id
   *   The id within the storage plugin for the requested Panels display.
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The current request.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   */
  public function handleRemoveBlockRequest($panels_storage_type, $panels_storage_id, Request $request) {
    $panels_display = $this
      ->loadPanelsDisplay($panels_storage_type, $panels_storage_id);
    $this->removeBlockRequestHandler
      ->handleRequest($panels_display, $request, TRUE);
    return $this->updateLayoutRequestHandler
      ->getJsonResponse();
  }

  /**
   * Gets a list of Block Plugins from the server.
   *
   * @param string $panels_storage_type
   *   The id of the storage plugin.
   * @param string $panels_storage_id
   *   The id within the storage plugin for the requested Panels display.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   */
  public function getBlockPlugins($panels_storage_type, $panels_storage_id) {
    $panels_display = $this
      ->loadPanelsDisplay($panels_storage_type, $panels_storage_id);

    // Get block plugin definitions from the server.
    $definitions = $this->blockManager
      ->getDefinitionsForContexts($panels_display
      ->getContexts());

    // Assemble our relevant data.
    $blocks = [];
    foreach ($definitions as $plugin_id => $definition) {

      // Don't add broken Blocks.
      if ($plugin_id == 'broken') {
        continue;
      }
      $blocks[] = [
        'plugin_id' => $plugin_id,
        'label' => $definition['admin_label'],
        'category' => $definition['category'],
        'id' => $definition['id'],
        'provider' => $definition['provider'],
      ];
    }

    // Trigger hook_panels_ipe_blocks_alter(). Allows other modules to change
    // the list of blocks that are visible.
    \Drupal::moduleHandler()
      ->alter('panels_ipe_blocks', $blocks);

    // We need to re-index our return value, in case a hook unset a block.
    $blocks = array_values($blocks);

    // Return a structured JSON response for our Backbone App.
    return new JsonResponse($blocks);
  }

  /**
   * Drupal AJAX compatible route for rendering a given Block Plugin's form.
   *
   * @param string $panels_storage_type
   *   The id of the storage plugin.
   * @param string $panels_storage_id
   *   The id within the storage plugin for the requested Panels display.
   * @param string $plugin_id
   *   The requested Block Plugin ID.
   * @param string $block_uuid
   *   The Block UUID, if this is an existing Block.
   *
   * @return Response
   */
  public function getBlockPluginForm($panels_storage_type, $panels_storage_id, $plugin_id, $block_uuid = NULL) {
    $panels_display = $this
      ->loadPanelsDisplay($panels_storage_type, $panels_storage_id);

    // Get the configuration in the block plugin definition.
    $definitions = $this->blockManager
      ->getDefinitionsForContexts($panels_display
      ->getContexts());

    // Check if the block plugin is defined.
    if (!isset($definitions[$plugin_id])) {
      throw new NotFoundHttpException();
    }

    // Build a Block Plugin configuration form.
    $form = $this
      ->formBuilder()
      ->getForm('Drupal\\panels_ipe\\Form\\PanelsIPEBlockPluginForm', $plugin_id, $panels_display, $block_uuid);

    // Return the rendered form as a proper Drupal AJAX response.
    $response = new AjaxResponse();
    $command = new AppendCommand('.ipe-block-form', $form);
    $response
      ->addCommand($command);
    return $response;
  }

  /**
   * Gets a list of Block Content Types from the server.
   *
   * @param string $panels_storage_type
   *   The id of the storage plugin.
   * @param string $panels_storage_id
   *   The id within the storage plugin for the requested Panels display.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   */
  public function getBlockContentTypes($panels_storage_type, $panels_storage_id) {

    // Assemble our relevant data.
    $types = $this
      ->entityTypeManager()
      ->getStorage('block_content_type')
      ->loadMultiple();
    $data = [];

    /** @var \Drupal\block_content\BlockContentTypeInterface $definition */
    foreach ($types as $id => $definition) {
      $data[] = [
        'id' => $definition
          ->id(),
        'revision' => $definition
          ->shouldCreateNewRevision(),
        'label' => $definition
          ->label(),
        'description' => $definition
          ->getDescription(),
      ];
    }

    // Return a structured JSON response for our Backbone App.
    return new JsonResponse($data);
  }

  /**
   * Drupal AJAX compatible route for rendering a Block Content Type's form.
   *
   * @param string $panels_storage_type
   *   The id of the storage plugin.
   * @param string $panels_storage_id
   *   The id within the storage plugin for the requested Panels display.
   * @param string $type
   *   The requested Block Type.
   * @param string $block_content_uuid
   *   The Block Content Entity UUID, if this is an existing Block.
   *
   * @return \Drupal\Core\Ajax\AjaxResponse
   *
   * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
   */
  public function getBlockContentForm($panels_storage_type, $panels_storage_id, $type, $block_content_uuid = NULL) {
    $storage = $this
      ->entityTypeManager()
      ->getStorage('block_content');

    // Create or load a new block of the given type.
    if ($block_content_uuid) {
      $block_list = $storage
        ->loadByProperties([
        'uuid' => $block_content_uuid,
      ]);
      $block = array_shift($block_list);
      $operation = 'update';
    }
    else {
      $block = $storage
        ->create([
        'type' => $type,
      ]);
      $operation = 'create';
    }

    // Check Block Content entity access for the current operation.
    if (!$block
      ->access($operation)) {
      throw new AccessDeniedHttpException();
    }

    // Grab our Block Content Entity form handler.
    $form = $this
      ->entityFormBuilder()
      ->getForm($block, 'panels_ipe');

    // Return the rendered form as a proper Drupal AJAX response.
    $response = new AjaxResponse();
    $command = new AppendCommand('.ipe-block-form', $form);
    $response
      ->addCommand($command);
    return $response;
  }

  /**
   * Gets a single Block from the current Panels Display. Uses TempStore.
   *
   * @param string $panels_storage_type
   *   The id of the storage plugin.
   * @param string $panels_storage_id
   *   The id within the storage plugin for the requested Panels display.
   * @param string $block_uuid
   *   The Block UUID.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   */
  public function getBlock($panels_storage_type, $panels_storage_id, $block_uuid) {
    $panels_display = $this
      ->loadPanelsDisplay($panels_storage_type, $panels_storage_id);

    /** @var \Drupal\Core\Block\BlockBase $block_instance */
    $block_instance = $panels_display
      ->getBlock($block_uuid);
    $block_config = $block_instance
      ->getConfiguration();

    // Assemble data required for our App.
    $build = $this
      ->buildBlockInstance($block_instance, $panels_display);

    // Bubble Block attributes to fix bugs with the Quickedit and Contextual
    // modules.
    $this
      ->bubbleBlockAttributes($build);

    // Add our data attribute for the Backbone app.
    $build['#attributes']['data-block-id'] = $block_uuid;
    $plugin_definition = $block_instance
      ->getPluginDefinition();
    $block_model = [
      'uuid' => $block_uuid,
      'label' => $block_instance
        ->label(),
      'id' => $block_instance
        ->getPluginId(),
      'region' => $block_config['region'],
      'provider' => $block_config['provider'],
      'plugin_id' => $plugin_definition['id'],
      'html' => $this->renderer
        ->render($build),
    ];
    return new JsonResponse($block_model);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ControllerBase::$configFactory protected property The configuration factory.
ControllerBase::$currentUser protected property The current user service. 1
ControllerBase::$entityFormBuilder protected property The entity form builder.
ControllerBase::$entityManager protected property The entity manager.
ControllerBase::$entityTypeManager protected property The entity type manager.
ControllerBase::$formBuilder protected property The form builder. 2
ControllerBase::$keyValue protected property The key-value storage. 1
ControllerBase::$languageManager protected property The language manager. 1
ControllerBase::$moduleHandler protected property The module handler. 2
ControllerBase::$stateService protected property The state service.
ControllerBase::cache protected function Returns the requested cache bin.
ControllerBase::config protected function Retrieves a configuration object.
ControllerBase::container private function Returns the service container.
ControllerBase::currentUser protected function Returns the current user. 1
ControllerBase::entityFormBuilder protected function Retrieves the entity form builder.
ControllerBase::entityManager Deprecated protected function Retrieves the entity manager service.
ControllerBase::entityTypeManager protected function Retrieves the entity type manager.
ControllerBase::formBuilder protected function Returns the form builder service. 2
ControllerBase::keyValue protected function Returns a key/value storage collection. 1
ControllerBase::languageManager protected function Returns the language manager service. 1
ControllerBase::moduleHandler protected function Returns the module handler. 2
ControllerBase::redirect protected function Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait::redirect
ControllerBase::state protected function Returns the state storage service.
LinkGeneratorTrait::$linkGenerator protected property The link generator. 1
LinkGeneratorTrait::getLinkGenerator Deprecated protected function Returns the link generator.
LinkGeneratorTrait::l Deprecated protected function Renders a link to a route given a route name and its parameters.
LinkGeneratorTrait::setLinkGenerator Deprecated public function Sets the link generator service.
LoggerChannelTrait::$loggerFactory protected property The logger channel factory service.
LoggerChannelTrait::getLogger protected function Gets the logger for a specific channel.
LoggerChannelTrait::setLoggerFactory public function Injects the logger channel factory.
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
PanelsIPEBlockRendererTrait::$contextHandler protected property
PanelsIPEBlockRendererTrait::bubbleBlockAttributes protected function Bubble block attributes up if possible. This allows modules like Quickedit to function.
PanelsIPEBlockRendererTrait::buildBlockInstance protected function Compiles a render array for the given Block instance based on the form.
PanelsIPEPageController::$blockManager protected property
PanelsIPEPageController::$layoutPluginManager protected property
PanelsIPEPageController::$panelsStorage protected property The Panels storage manager.
PanelsIPEPageController::$removeBlockRequestHandler private property
PanelsIPEPageController::$renderer protected property
PanelsIPEPageController::$tempStore protected property
PanelsIPEPageController::$updateLayoutRequestHandler private property
PanelsIPEPageController::cancel public function Removes any temporary changes to the variant.
PanelsIPEPageController::create public static function Instantiates a new instance of this class. Overrides ControllerBase::create
PanelsIPEPageController::getBlock public function Gets a single Block from the current Panels Display. Uses TempStore.
PanelsIPEPageController::getBlockContentForm public function Drupal AJAX compatible route for rendering a Block Content Type's form.
PanelsIPEPageController::getBlockContentTypes public function Gets a list of Block Content Types from the server.
PanelsIPEPageController::getBlockPluginForm public function Drupal AJAX compatible route for rendering a given Block Plugin's form.
PanelsIPEPageController::getBlockPlugins public function Gets a list of Block Plugins from the server.
PanelsIPEPageController::getLayoutForm public function Gets a layout configuration form for the requested layout.
PanelsIPEPageController::getLayouts public function Gets a list of available Layouts, without wrapping HTML.
PanelsIPEPageController::handleCreateLayoutRequest public function Creates (POST) a new Layout for this Variant.
PanelsIPEPageController::handleRemoveBlockRequest public function Removes a block from the layout.
PanelsIPEPageController::handleUpdateLayoutRequest public function Updates (PUT) an existing Layout in this Variant.
PanelsIPEPageController::handleUpdateLayoutTempStorageRequest public function Stores changes to the temporary storage.
PanelsIPEPageController::loadPanelsDisplay protected function Takes the current Page Variant and returns a possibly modified Page Variant based on what's in TempStore for this user.
PanelsIPEPageController::__construct public function Constructs a new PanelsIPEController.
RedirectDestinationTrait::$redirectDestination protected property The redirect destination service. 1
RedirectDestinationTrait::getDestinationArray protected function Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url.
RedirectDestinationTrait::getRedirectDestination protected function Returns the redirect destination service.
RedirectDestinationTrait::setRedirectDestination public function Sets the redirect destination service.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
UrlGeneratorTrait::$urlGenerator protected property The url generator.
UrlGeneratorTrait::getUrlGenerator Deprecated protected function Returns the URL generator service.
UrlGeneratorTrait::setUrlGenerator Deprecated public function Sets the URL generator service.
UrlGeneratorTrait::url Deprecated protected function Generates a URL or path for a specific route based on the given parameters.