Example #1
0
/**
 * Act on a Panels Display before it is saved via the IPE.
 *
 * @param \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant $panels_display
 *   The current Panels display.
 * @param array $layout_model
 *   The decoded LayoutModel from our App.
 */
function hook_panels_ipe_panels_display_presave(PanelsDisplayVariant $panels_display, array $layout_model)
{
    if (isset($layout_model['use_custom_storage'])) {
        $configuration = $panels_display->getConfiguration();
        $panels_display->setStorage('custom_storage_key', $configuration['storage_id']);
    }
}
 /**
  * @inheritdoc
  */
 protected function handle(PanelsDisplayVariant $panels_display, $decoded_request, $save_to_temp_store = FALSE)
 {
     $panels_display->removeBlock($decoded_request);
     if ($save_to_temp_store) {
         $this->savePanelsDisplayToTempStore($panels_display);
     } else {
         $this->savePanelsDisplay($panels_display);
     }
 }
 /**
  * {@inheritdoc}
  */
 public function save(PanelsDisplayVariant $panels_display)
 {
     $id = $panels_display->getStorageId();
     if ($id && ($page_variant = $this->loadPageVariant($id))) {
         $variant_plugin = $page_variant->getVariantPlugin();
         if (!$variant_plugin instanceof PanelsDisplayVariant) {
             throw new \Exception("Page variant doesn't use a Panels display variant");
         }
         $variant_plugin->setConfiguration($panels_display->getConfiguration());
         $page_variant->save();
     } else {
         throw new \Exception("Couldn't find page variant to store Panels display");
     }
 }
 /**
  * Updates the current Panels display based on the changes done in our app.
  *
  * @param \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant $panels_display
  *   The current Panels display.
  * @param array $layout_model
  *   The decoded LayoutModel from our App.
  *
  * @return \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant
  */
 private static function updatePanelsDisplay(PanelsDisplayVariant $panels_display, array $layout_model)
 {
     // Set our weight and region based on the metadata in our Backbone app.
     foreach ($layout_model['regionCollection'] as $region) {
         $weight = 0;
         foreach ($region['blockCollection'] as $block) {
             /** @var \Drupal\Core\Block\BlockBase $block_instance */
             $block_instance = $panels_display->getBlock($block['uuid']);
             $block_instance->setConfigurationValue('region', $region['name']);
             $block_instance->setConfigurationValue('weight', ++$weight);
             $panels_display->updateBlock($block['uuid'], $block_instance->getConfiguration());
         }
     }
     return $panels_display;
 }
 /**
  * @covers ::save
  *
  * @expectedException \Exception
  * @expectedExceptionMessage Page variant doesn't use a Panels display variant
  */
 public function testSaveNotPanels()
 {
     $this->storage->load('not_a_panel')->willReturn($this->pageVariantNotPanels->reveal());
     $this->panelsDisplay->setConfiguration(Argument::cetera())->shouldNotBeCalled();
     $this->pageVariant->save()->shouldNotBeCalled();
     $panels_display = $this->prophesize(PanelsDisplayVariant::class);
     $panels_display->getStorageId()->willReturn('not_a_panel');
     $panels_display->getConfiguration()->shouldNotBeCalled();
     $panels_storage = new PageManagerPanelsStorage([], '', [], $this->entityTypeManager->reveal());
     $panels_storage->save($panels_display->reveal());
 }
 /**
  * {@inheritdoc}
  */
 public function submitForm(array &$form, FormStateInterface $form_state)
 {
     // Return early if there are any errors.
     if ($form_state->hasAnyErrors()) {
         return $form;
     }
     $panels_display = $this->panelsDisplay;
     // Submit the layout form.
     $layout_form_state = (new FormState())->setValues($form_state->getValue('settings', []));
     $this->layout->submitConfigurationForm($form, $layout_form_state);
     $layout_config = $this->layout->getConfiguration();
     // Shift our blocks to the first available region. The IPE can control
     // re-assigning blocks in a smarter way.
     $region_definitions = $this->layout->getRegionDefinitions();
     $first_region = reset(array_keys($region_definitions));
     // For each block, set the region to match the new layout.
     foreach ($panels_display->getRegionAssignments() as $region => $region_assignment) {
         /** @var \Drupal\Core\Block\BlockPluginInterface $block */
         foreach ($region_assignment as $block_id => $block) {
             $block_config = $block->getConfiguration();
             // If the new layout does not have a region with the same name, use the
             // first available region.
             if (!isset($region_definitions[$block_config['region']])) {
                 $block_config['region'] = $first_region;
                 $panels_display->updateBlock($block_id, $block_config);
             }
         }
     }
     // Have our panels display use the new layout.
     $this->panelsDisplay->setLayout($this->layout, $layout_config);
     // Update tempstore.
     $this->tempStore->set($panels_display->id(), $panels_display->getConfiguration());
     $region_data = [];
     $region_content = [];
     // Compile region content and metadata.
     $regions = $panels_display->getRegionAssignments();
     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 = $panels_display->getLayout()->build($region_content);
     $form['build'] = $build;
     $data = ['id' => $this->layout->getPluginId(), 'label' => $layout_config['label'], 'current' => TRUE, 'html' => $this->renderer->render($build), 'regions' => $region_data];
     // Add Block metadata and HTML as a drupalSetting.
     $form['#attached']['drupalSettings']['panels_ipe']['updated_layout'] = $data;
     return $form;
 }
 /**
  * Compiles a render array for the given Block instance based on the form.
  *
  * @param \Drupal\Core\Block\BlockBase $block_instance
  *   The Block instance you want to render.
  *
  * @return array $build
  *   The Block render array.
  */
 protected function buildBlockInstance($block_instance)
 {
     // Get the new block configuration.
     $configuration = $block_instance->getConfiguration();
     // Add context to the block.
     if ($block_instance instanceof ContextAwarePluginInterface) {
         $this->contextHandler->applyContextMapping($block_instance, $this->panelsDisplay->getContexts());
     }
     // Build the block content.
     $content = $block_instance->build();
     // Disable any nested forms from the render array.
     $content = $this->removeFormWrapperRecursive($content);
     // Compile the render array.
     $build = ['#theme' => 'block', '#attributes' => [], '#contextual_links' => [], '#configuration' => $configuration, '#plugin_id' => $block_instance->getPluginId(), '#base_plugin_id' => $block_instance->getBaseId(), '#derivative_plugin_id' => $block_instance->getDerivativeId(), 'content' => $content];
     return $build;
 }
 /**
  * Loads or creates a Block Plugin instance suitable for rendering or testing.
  *
  * @param \Drupal\Core\Form\FormStateInterface $form_state
  *   The current state of the form.
  *
  * @return \Drupal\Core\Block\BlockBase
  *   The Block Plugin instance.
  */
 protected function getBlockInstance(FormStateInterface $form_state)
 {
     // If a UUID is provided, the Block should already exist.
     if ($uuid = $form_state->getValue('uuid')) {
         // If a temporary configuration for this variant exists, use it.
         $temp_store_key = $this->panelsDisplay->id();
         if ($variant_config = $this->tempStore->get($temp_store_key)) {
             $this->panelsDisplay->setConfiguration($variant_config);
         }
         // Load the existing Block instance.
         $block_instance = $this->panelsDisplay->getBlock($uuid);
     } else {
         // Create an instance of this Block plugin.
         /** @var \Drupal\Core\Block\BlockBase $block_instance */
         $block_instance = $this->blockManager->createInstance($form_state->getValue('plugin_id'));
     }
     // Add context to the block.
     if ($block_instance instanceof ContextAwarePluginInterface) {
         $this->contextHandler->applyContextMapping($block_instance, $this->panelsDisplay->getContexts());
     }
     return $block_instance;
 }
 /**
  * {@inheritdoc}
  */
 public function exportDisplay(PanelsDisplayVariant $display)
 {
     return $display->getConfiguration();
 }
 /**
  * @covers ::defaultConfiguration
  */
 public function testDefaultConfiguration()
 {
     $defaults = $this->variant->defaultConfiguration();
     $this->assertSame('', $defaults['layout']);
     $this->assertSame('', $defaults['page_title']);
 }
 /**
  * {@inheritdoc}
  */
 public function build(PanelsDisplayVariant $panels_display)
 {
     // Check to see if the current user has permissions to use the IPE.
     $has_permission = $this->account->hasPermission('access panels in-place editing');
     // Attach the Panels In-place editor library based on permissions.
     if ($has_permission) {
         // This flag tracks whether or not there are unsaved changes.
         $unsaved = FALSE;
         // 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)) {
             unset($variant_config['id']);
             $panels_display->setConfiguration($variant_config);
             // Indicate that the user is viewing un-saved changes.
             $unsaved = TRUE;
         }
         $build = parent::build($panels_display);
         $regions = $panels_display->getRegionAssignments();
         $layout = $panels_display->getLayout();
         foreach ($regions as $region => $blocks) {
             // Wrap each region with a unique class and data attribute.
             $region_name = Html::getClass("block-region-{$region}");
             $build[$region]['#prefix'] = '<div class="' . $region_name . '" data-region-name="' . $region . '">';
             $build[$region]['#suffix'] = '</div>';
             if ($blocks) {
                 foreach ($blocks as $block_id => $block) {
                     $build[$region][$block_id]['#attributes']['data-block-id'] = $block_id;
                 }
             }
         }
         // Attach the required settings and IPE.
         $build['#attached']['library'][] = 'panels_ipe/panels_ipe';
         $build['#attached']['drupalSettings']['panels_ipe'] = $this->getDrupalSettings($regions, $layout, $panels_display, $unsaved);
         // Add our custom elements to the build.
         $build['#prefix'] = '<div id="panels-ipe-content">';
         $build['#suffix'] = '</div><div id="panels-ipe-tray"></div>';
     } else {
         $build = parent::build($panels_display);
     }
     return $build;
 }
 /**
  * Build the render array for a single panelized entity.
  *
  * @param \Drupal\Core\Entity\EntityInterface $entity
  * @param \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant $panels_display
  * @param string $view_mode
  * @param string $langcode
  *
  * @return array
  */
 protected function buildPanelized(EntityInterface $entity, PanelsDisplayVariant $panels_display, $view_mode, $langcode)
 {
     $contexts = $panels_display->getContexts();
     $entity_context = new Context(new ContextDefinition('entity:' . $this->entityTypeId, NULL, TRUE), $entity);
     $contexts['@panelizer.entity_context:' . $this->entityTypeId] = $entity_context;
     $panels_display->setContexts($contexts);
     $build = $panels_display->build();
     // @todo: I'm sure more is necessary to get the cache contexts right...
     CacheableMetadata::createFromObject($entity)->applyTo($build);
     $this->getPanelizerPlugin()->alterBuild($build, $entity, $panels_display, $view_mode);
     return $build;
 }
 /**
  * {@inheritdoc}
  */
 public function save(PanelsDisplayVariant $panels_display)
 {
     $storage = $this->getStorage($panels_display->getStorageType());
     $storage->save($panels_display);
 }
 /**
  * {@inheritdoc}
  */
 public function build(PanelsDisplayVariant $panels_display)
 {
     $regions = $panels_display->getRegionAssignments();
     $contexts = $panels_display->getContexts();
     $layout = $panels_display->getLayout();
     $regions = $this->buildRegions($regions, $contexts);
     if ($layout) {
         $regions = $layout->build($regions);
     }
     return $regions;
 }
 /**
  * Updates the current Panels display based on the changes done in our app.
  *
  * @param \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant $panels_display
  *   The current Panels display.
  * @param array $layout_model
  *   The decoded LayoutModel from our App.
  *
  * @return \Symfony\Component\HttpFoundation\JsonResponse
  */
 protected function updatePanelsDisplay(PanelsDisplayVariant $panels_display, array $layout_model)
 {
     // Set our weight and region based on the metadata in our Backbone app.
     foreach ($layout_model['regionCollection'] as $region) {
         $weight = 0;
         foreach ($region['blockCollection'] as $block) {
             /** @var \Drupal\Core\Block\BlockBase $block_instance */
             $block_instance = $panels_display->getBlock($block['uuid']);
             $block_instance->setConfigurationValue('region', $region['name']);
             $block_instance->setConfigurationValue('weight', ++$weight);
             $panels_display->updateBlock($block['uuid'], $block_instance->getConfiguration());
         }
     }
     // Remove blocks that need removing.
     // @todo We should do this on the fly instead of at on save.
     foreach ($layout_model['deletedBlocks'] as $uuid) {
         $panels_display->removeBlock($uuid);
     }
     // Save the variant and remove temp storage.
     $this->savePanelsDisplay($panels_display, FALSE);
     return new JsonResponse(['deletedBlocks' => []]);
 }
Example #16
0
 /**
  * {@inheritdoc}
  */
 public function build(PanelsDisplayVariant $panels_display)
 {
     $regions = $panels_display->getRegionAssignments();
     return $regions;
 }
 /**
  * Deletes the given Panels Display from TempStore.
  *
  * @param \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant $panels_display
  * @throws \Drupal\user\TempStoreException
  */
 protected function deletePanelsDisplayTempStore(PanelsDisplayVariant $panels_display)
 {
     $this->tempStore->delete($panels_display->id());
 }