/**
  * Builds a form that configure an existing or new layout for the IPE.
  *
  * @param array $form
  *   An associative array containing the structure of the form.
  * @param \Drupal\Core\Form\FormStateInterface $form_state
  *   The current state of the form.
  * @param string $layout_id
  *   The requested Layout ID.
  * @param \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant $panels_display
  *   The current PageVariant ID.
  *
  * @return array
  *   The form structure.
  */
 public function buildForm(array $form, FormStateInterface $form_state, $layout_id = NULL, PanelsDisplayVariant $panels_display = NULL)
 {
     // We require these default arguments.
     if (!$layout_id || !$panels_display) {
         return FALSE;
     }
     // Save the panels display for later.
     $this->panelsDisplay = $panels_display;
     // Check if this is the current layout, and if not create an instance.
     $layout = $this->panelsDisplay->getLayout();
     $current = $layout->getPluginId() == $layout_id;
     if (!$current) {
         // Create a new layout instance.
         $layout = $this->layoutManager->createInstance($layout_id, []);
     }
     // Save the layout for future use.
     $this->layout = $layout;
     $form['settings'] = $layout->buildConfigurationForm([], $form_state);
     $form['settings']['#tree'] = TRUE;
     // If the form is empty, inform the user.
     if (empty(Element::getVisibleChildren($form['settings']))) {
         $form['settings'][] = ['#markup' => $this->t('<h5>This layout does not provide any configuration.</h5>')];
     }
     // Add an add button, which is only used by our App.
     $form['submit'] = ['#type' => 'button', '#value' => $current ? $this->t('Update') : $this->t('Change Layout'), '#ajax' => ['callback' => '::submitForm', 'wrapper' => 'panels-ipe-layout-form-wrapper', 'method' => 'replace', 'progress' => ['type' => 'throbber', 'message' => '']]];
     return $form;
 }
 public function setUp()
 {
     $this->account = $this->prophesize(AccountInterface::class);
     $this->contextHandler = $this->prophesize(ContextHandlerInterface::class);
     $this->uuidGenerator = $this->prophesize(UuidInterface::class);
     $this->token = $this->prophesize(Token::class);
     $this->builderManager = $this->prophesize(DisplayBuilderManagerInterface::class);
     $this->layoutManager = $this->prophesize(LayoutPluginManagerInterface::class);
     $this->layout = $this->prophesize(LayoutInterface::class);
     $this->layoutManager->createInstance(Argument::type('string'), Argument::type('array'))->willReturn($this->layout->reveal());
     $this->variant = new PanelsDisplayVariant([], '', [], $this->contextHandler->reveal(), $this->account->reveal(), $this->uuidGenerator->reveal(), $this->token->reveal(), $this->builderManager->reveal(), $this->layoutManager->reveal());
 }
 /**
  * Gets a given layout with empty regions and relevant metadata.
  *
  * @param \Drupal\page_manager\PageVariantInterface $page_variant
  *   The page variant entity.
  * @param string $layout_id
  *   The machine name of the requested layout.
  *
  * @return \Symfony\Component\HttpFoundation\JsonResponse
  */
 public function getLayout(PageVariantInterface $page_variant, $layout_id)
 {
     /** @var \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant $variant_plugin */
     $variant_plugin = $page_variant->getVariantPlugin();
     // Build the requested layout.
     $configuration = $variant_plugin->getConfiguration();
     $configuration['layout'] = $layout_id;
     $variant_plugin->setConfiguration($configuration);
     // Inherit our PageVariant's contexts before rendering.
     $variant_plugin->setContexts($page_variant->getContexts());
     $regions = $variant_plugin->getRegionNames();
     $region_data = [];
     $region_content = [];
     // Compile region content and metadata.
     foreach ($regions as $id => $label) {
         // Wrap the region with a class/data attribute that our app can use.
         $region_name = Html::getClass("block-region-{$id}");
         $region_content[$id] = ['#prefix' => '<div class="' . $region_name . '" data-region-name="' . $id . '">', '#suffix' => '</div>'];
         // Format region metadata.
         $region_data[] = ['name' => $id, 'label' => $label];
     }
     $build = $variant_plugin->getLayout()->build($region_content);
     // Get the current layout.
     $current_layout = $variant_plugin->getLayout()->getPluginId();
     // Get a list of all available layouts.
     $layouts = $this->layoutPluginManager->getLayoutOptions();
     $data = ['id' => $layout_id, 'label' => $layouts[$layout_id], 'current' => $current_layout == $layout_id, 'html' => $this->renderer->render($build), 'regions' => $region_data];
     // Update temp store.
     $this->savePageVariant($page_variant);
     // Return a structured JSON response for our Backbone App.
     return new JsonResponse($data);
 }
Example #4
0
 /**
  * Build the mega menu link/content tree.
  *
  * @param MegaMenuInterface $mega_menu
  *
  * @return array
  */
 private function buildMegaMenuTree(MegaMenuInterface $mega_menu)
 {
     $tree = $this->loadMenuTree($mega_menu->getTargetMenu());
     $build = $this->menuLinkTree->build($tree);
     $build['#mega_menu'] = $mega_menu;
     $cacheability = CacheableMetadata::createFromRenderArray($build);
     $cacheability->addCacheableDependency($mega_menu);
     // Add content from the mega menus to the link tree.
     foreach ($build['#items'] as $item_key => $item) {
         $safe_item_key = str_replace('.', '_', $item_key);
         $layout = $mega_menu->getLinkLayout($safe_item_key);
         if ($layout === MegaMenuInterface::NO_LAYOUT) {
             continue;
         }
         $build['#items'][$item_key]['attributes']['data-mega-menu-content-target'] = $item_key;
         /** @var LayoutInterface $layout_plugin */
         $layout_plugin = $this->layoutPluginManager->createInstance($layout);
         $plugin_definition = $layout_plugin->getPluginDefinition();
         // Build an array of the region names in the right order.
         $empty = array_fill_keys(array_keys($plugin_definition['region_names']), []);
         $full = $mega_menu->getBlocksByLink($safe_item_key)->getAllByRegion();
         // Merge it with the actual values to maintain the ordering.
         $block_assignments = array_intersect_key(array_merge($empty, $full), $empty);
         $build['#items'][$item_key]['content'] = ['#prefix' => '<div data-mega-menu-content="' . $item_key . '" class="mega-menu-content">', '#suffix' => '</div>', '#theme' => $plugin_definition['theme'], '#settings' => [], '#layout' => $plugin_definition];
         if (isset($plugin_definition['library'])) {
             $build['#items'][$item_key]['content']['#attached']['library'][] = $plugin_definition['library'];
         }
         foreach ($block_assignments as $region => $blocks) {
             $build['#items'][$item_key]['content'][$region] = [];
             /** @var \Drupal\Core\Block\BlockPluginInterface[] $blocks */
             foreach ($blocks as $block_id => $block) {
                 if ($block instanceof ContextAwarePluginInterface) {
                     $contexts = $this->contextRepository->getRuntimeContexts($block->getContextMapping());
                     $this->contextHandler->applyContextMapping($block, $contexts);
                 }
                 // Make sure the user is allowed to view the block.
                 $access = $block->access($this->account, TRUE);
                 $cacheability->addCacheableDependency($access);
                 // If the user is not allowed then do not render the block.
                 if (!$access->isAllowed()) {
                     continue;
                 }
                 $configuration = $block->getConfiguration();
                 // Create the render array for the block as a whole.
                 // @see template_preprocess_block().
                 $block_build = ['#theme' => 'block', '#attributes' => [], '#weight' => $configuration['weight'], '#configuration' => $configuration, '#plugin_id' => $block->getPluginId(), '#base_plugin_id' => $block->getBaseId(), '#derivative_plugin_id' => $block->getDerivativeId(), '#block_plugin' => $block, '#pre_render' => [[$this, 'preRenderBlock']], '#cache' => ['keys' => ['mega_menu', $mega_menu->id(), 'block', $block_id], 'tags' => Cache::mergeTags($mega_menu->getCacheTags(), $block->getCacheTags()), 'contexts' => $block->getCacheContexts(), 'max-age' => $block->getCacheMaxAge()]];
                 $build['#items'][$item_key]['content'][$region][$block_id] = $block_build;
                 $cacheability->addCacheableDependency($block);
             }
         }
     }
     $cacheability->applyTo($build);
     return $build;
 }
 /**
  * Gets a list of available Layouts, without wrapping HTML.
  *
  * @param string $panels_storage_type
  *   The id of the storage service.
  * @param string $panels_storage_id
  *   The id within the storage service 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();
     $data = [];
     foreach ($layouts as $id => $layout) {
         $data[] = ['id' => $id, 'label' => $layout['label'], 'icon' => !empty($layout['icon']) ? $layout['icon'] : drupal_get_path('module', 'panels') . '/images/no-layout-preview.png', 'current' => $id == $current_layout_id, 'category' => $layout['category']];
     }
     // Return a structured JSON response for our Backbone App.
     return new JsonResponse($data);
 }
Example #6
0
 /**
  * Get a list of regions for the specified layout.
  *
  * @param string $layout
  *
  * @return array
  */
 protected function getLayoutRegions($layout)
 {
     $default_regions = $this->getDefaultRegions();
     if ($layout === MegaMenuInterface::NO_LAYOUT) {
         return $default_regions;
     }
     $definition = $this->layoutPluginManager->getDefinition($layout, FALSE);
     if (!$definition) {
         return $default_regions;
     }
     if (!isset($definition['region_names']) || !count($definition['region_names'])) {
         return $default_regions;
     }
     return $definition['region_names'] + $default_regions;
 }