/**
  * {@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");
     }
 }
 /**
  * Compiles settings needed for the IPE to function.
  *
  * @param array $regions
  *   The render array representing regions.
  * @param \Drupal\layout_plugin\Plugin\Layout\LayoutInterface $layout
  *   The current layout.
  * @param \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant $panels_display
  *   The Panels display we are editing.
  * @param bool $unsaved
  *   Whether or not there are unsaved changes.
  *
  * @return array|bool
  *   An associative array representing the contents of drupalSettings, or
  *   FALSE if there was an error.
  */
 protected function getDrupalSettings(array $regions, LayoutInterface $layout, PanelsDisplayVariant $panels_display, $unsaved)
 {
     $settings = ['regions' => []];
     // Add current block IDs to settings sorted by region.
     foreach ($regions as $region => $blocks) {
         $settings['regions'][$region] = ['name' => $region, 'label' => '', 'blocks' => []];
         if (!$blocks) {
             continue;
         }
         /** @var \Drupal\Core\Block\BlockPluginInterface[] $blocks */
         foreach ($blocks as $block_uuid => $block) {
             $configuration = $block->getConfiguration();
             $setting = ['uuid' => $block_uuid, 'label' => $block->label(), 'id' => $block->getPluginId()];
             $settings['regions'][$region]['blocks'][$block_uuid] = NestedArray::mergeDeep($configuration, $setting);
         }
     }
     // Add the layout information.
     $layout_definition = $layout->getPluginDefinition();
     $settings['layout'] = ['id' => $layout->getPluginId(), 'label' => $layout_definition['label'], 'original' => true];
     // Add the display variant's config.
     $settings['panels_display'] = ['storage_type' => $panels_display->getStorageType(), 'storage_id' => $panels_display->getStorageId(), 'id' => $panels_display->id()];
     // Inform the App of our saved state.
     $settings['unsaved'] = $unsaved;
     return $settings;
 }
 /**
  * {@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') && $this->panelsStorage->access($panels_display->getStorageType(), $panels_display->getStorageId(), 'update', $this->account)->isAllowed();
     // 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;
 }