Mercurial > hg > isophonics-drupal-site
diff core/modules/layout_builder/src/Controller/LayoutBuilderController.php @ 14:1fec387a4317
Update Drupal core to 8.5.2 via Composer
author | Chris Cannam |
---|---|
date | Mon, 23 Apr 2018 09:46:53 +0100 |
parents | |
children | c2387f117808 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/layout_builder/src/Controller/LayoutBuilderController.php Mon Apr 23 09:46:53 2018 +0100 @@ -0,0 +1,328 @@ +<?php + +namespace Drupal\layout_builder\Controller; + +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Drupal\Core\Messenger\MessengerInterface; +use Drupal\Core\Plugin\PluginFormInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Core\Url; +use Drupal\layout_builder\Context\LayoutBuilderContextTrait; +use Drupal\layout_builder\LayoutTempstoreRepositoryInterface; +use Drupal\layout_builder\OverridesSectionStorageInterface; +use Drupal\layout_builder\Section; +use Drupal\layout_builder\SectionStorageInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\HttpFoundation\RedirectResponse; + +/** + * Defines a controller to provide the Layout Builder admin UI. + * + * @internal + */ +class LayoutBuilderController implements ContainerInjectionInterface { + + use LayoutBuilderContextTrait; + use StringTranslationTrait; + + /** + * The layout tempstore repository. + * + * @var \Drupal\layout_builder\LayoutTempstoreRepositoryInterface + */ + protected $layoutTempstoreRepository; + + /** + * The messenger service. + * + * @var \Drupal\Core\Messenger\MessengerInterface + */ + protected $messenger; + + /** + * LayoutBuilderController constructor. + * + * @param \Drupal\layout_builder\LayoutTempstoreRepositoryInterface $layout_tempstore_repository + * The layout tempstore repository. + * @param \Drupal\Core\Messenger\MessengerInterface $messenger + * The messenger service. + */ + public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore_repository, MessengerInterface $messenger) { + $this->layoutTempstoreRepository = $layout_tempstore_repository; + $this->messenger = $messenger; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('layout_builder.tempstore_repository'), + $container->get('messenger') + ); + } + + /** + * Provides a title callback. + * + * @param \Drupal\layout_builder\SectionStorageInterface $section_storage + * The section storage. + * + * @return string + * The title for the layout page. + */ + public function title(SectionStorageInterface $section_storage) { + return $this->t('Edit layout for %label', ['%label' => $section_storage->label()]); + } + + /** + * Renders the Layout UI. + * + * @param \Drupal\layout_builder\SectionStorageInterface $section_storage + * The section storage. + * @param bool $is_rebuilding + * (optional) Indicates if the layout is rebuilding, defaults to FALSE. + * + * @return array + * A render array. + */ + public function layout(SectionStorageInterface $section_storage, $is_rebuilding = FALSE) { + $this->prepareLayout($section_storage, $is_rebuilding); + + $output = []; + $count = 0; + for ($i = 0; $i < $section_storage->count(); $i++) { + $output[] = $this->buildAddSectionLink($section_storage, $count); + $output[] = $this->buildAdministrativeSection($section_storage, $count); + $count++; + } + $output[] = $this->buildAddSectionLink($section_storage, $count); + $output['#attached']['library'][] = 'layout_builder/drupal.layout_builder'; + $output['#type'] = 'container'; + $output['#attributes']['id'] = 'layout-builder'; + // Mark this UI as uncacheable. + $output['#cache']['max-age'] = 0; + return $output; + } + + /** + * Prepares a layout for use in the UI. + * + * @param \Drupal\layout_builder\SectionStorageInterface $section_storage + * The section storage. + * @param bool $is_rebuilding + * Indicates if the layout is rebuilding. + */ + protected function prepareLayout(SectionStorageInterface $section_storage, $is_rebuilding) { + // Only add sections if the layout is new and empty. + if (!$is_rebuilding && $section_storage->count() === 0) { + $sections = []; + // If this is an empty override, copy the sections from the corresponding + // default. + if ($section_storage instanceof OverridesSectionStorageInterface) { + $sections = $section_storage->getDefaultSectionStorage()->getSections(); + } + + // For an empty layout, begin with a single section of one column. + if (!$sections) { + $sections[] = new Section('layout_onecol'); + } + + foreach ($sections as $section) { + $section_storage->appendSection($section); + } + $this->layoutTempstoreRepository->set($section_storage); + } + } + + /** + * Builds a link to add a new section at a given delta. + * + * @param \Drupal\layout_builder\SectionStorageInterface $section_storage + * The section storage. + * @param int $delta + * The delta of the section to splice. + * + * @return array + * A render array for a link. + */ + protected function buildAddSectionLink(SectionStorageInterface $section_storage, $delta) { + $storage_type = $section_storage->getStorageType(); + $storage_id = $section_storage->getStorageId(); + return [ + 'link' => [ + '#type' => 'link', + '#title' => $this->t('Add Section'), + '#url' => Url::fromRoute('layout_builder.choose_section', + [ + 'section_storage_type' => $storage_type, + 'section_storage' => $storage_id, + 'delta' => $delta, + ], + [ + 'attributes' => [ + 'class' => ['use-ajax'], + 'data-dialog-type' => 'dialog', + 'data-dialog-renderer' => 'off_canvas', + ], + ] + ), + ], + '#type' => 'container', + '#attributes' => [ + 'class' => ['add-section'], + ], + ]; + } + + /** + * Builds the render array for the layout section while editing. + * + * @param \Drupal\layout_builder\SectionStorageInterface $section_storage + * The section storage. + * @param int $delta + * The delta of the section. + * + * @return array + * The render array for a given section. + */ + protected function buildAdministrativeSection(SectionStorageInterface $section_storage, $delta) { + $storage_type = $section_storage->getStorageType(); + $storage_id = $section_storage->getStorageId(); + $section = $section_storage->getSection($delta); + + $layout = $section->getLayout(); + $build = $section->toRenderArray($this->getAvailableContexts($section_storage), TRUE); + $layout_definition = $layout->getPluginDefinition(); + + foreach ($layout_definition->getRegions() as $region => $info) { + if (!empty($build[$region])) { + foreach ($build[$region] as $uuid => $block) { + $build[$region][$uuid]['#attributes']['class'][] = 'draggable'; + $build[$region][$uuid]['#attributes']['data-layout-block-uuid'] = $uuid; + $build[$region][$uuid]['#contextual_links'] = [ + 'layout_builder_block' => [ + 'route_parameters' => [ + 'section_storage_type' => $storage_type, + 'section_storage' => $storage_id, + 'delta' => $delta, + 'region' => $region, + 'uuid' => $uuid, + ], + ], + ]; + } + } + + $build[$region]['layout_builder_add_block']['link'] = [ + '#type' => 'link', + '#title' => $this->t('Add Block'), + '#url' => Url::fromRoute('layout_builder.choose_block', + [ + 'section_storage_type' => $storage_type, + 'section_storage' => $storage_id, + 'delta' => $delta, + 'region' => $region, + ], + [ + 'attributes' => [ + 'class' => ['use-ajax'], + 'data-dialog-type' => 'dialog', + 'data-dialog-renderer' => 'off_canvas', + ], + ] + ), + ]; + $build[$region]['layout_builder_add_block']['#type'] = 'container'; + $build[$region]['layout_builder_add_block']['#attributes'] = ['class' => ['add-block']]; + $build[$region]['layout_builder_add_block']['#weight'] = 1000; + $build[$region]['#attributes']['data-region'] = $region; + $build[$region]['#attributes']['class'][] = 'layout-builder--layout__region'; + } + + $build['#attributes']['data-layout-update-url'] = Url::fromRoute('layout_builder.move_block', [ + 'section_storage_type' => $storage_type, + 'section_storage' => $storage_id, + ])->toString(); + $build['#attributes']['data-layout-delta'] = $delta; + $build['#attributes']['class'][] = 'layout-builder--layout'; + + return [ + '#type' => 'container', + '#attributes' => [ + 'class' => ['layout-section'], + ], + 'configure' => [ + '#type' => 'link', + '#title' => $this->t('Configure section'), + '#access' => $layout instanceof PluginFormInterface, + '#url' => Url::fromRoute('layout_builder.configure_section', [ + 'section_storage_type' => $storage_type, + 'section_storage' => $storage_id, + 'delta' => $delta, + ]), + '#attributes' => [ + 'class' => ['use-ajax', 'configure-section'], + 'data-dialog-type' => 'dialog', + 'data-dialog-renderer' => 'off_canvas', + ], + ], + 'remove' => [ + '#type' => 'link', + '#title' => $this->t('Remove section'), + '#url' => Url::fromRoute('layout_builder.remove_section', [ + 'section_storage_type' => $storage_type, + 'section_storage' => $storage_id, + 'delta' => $delta, + ]), + '#attributes' => [ + 'class' => ['use-ajax', 'remove-section'], + 'data-dialog-type' => 'dialog', + 'data-dialog-renderer' => 'off_canvas', + ], + ], + 'layout-section' => $build, + ]; + } + + /** + * Saves the layout. + * + * @param \Drupal\layout_builder\SectionStorageInterface $section_storage + * The section storage. + * + * @return \Symfony\Component\HttpFoundation\RedirectResponse + * A redirect response. + */ + public function saveLayout(SectionStorageInterface $section_storage) { + $section_storage->save(); + $this->layoutTempstoreRepository->delete($section_storage); + + if ($section_storage instanceof OverridesSectionStorageInterface) { + $this->messenger->addMessage($this->t('The layout override has been saved.')); + } + else { + $this->messenger->addMessage($this->t('The layout has been saved.')); + } + + return new RedirectResponse($section_storage->getRedirectUrl()->setAbsolute()->toString()); + } + + /** + * Cancels the layout. + * + * @param \Drupal\layout_builder\SectionStorageInterface $section_storage + * The section storage. + * + * @return \Symfony\Component\HttpFoundation\RedirectResponse + * A redirect response. + */ + public function cancelLayout(SectionStorageInterface $section_storage) { + $this->layoutTempstoreRepository->delete($section_storage); + + $this->messenger->addMessage($this->t('The changes to the layout have been discarded.')); + + return new RedirectResponse($section_storage->getRedirectUrl()->setAbsolute()->toString()); + } + +}