diff --git a/core/lib/Drupal/Core/Booze/ContentRouteEnhancer.php b/core/lib/Drupal/Core/Booze/ContentRouteEnhancer.php
new file mode 100644
index 0000000..cebd222
--- /dev/null
+++ b/core/lib/Drupal/Core/Booze/ContentRouteEnhancer.php
@@ -0,0 +1,46 @@
+resolver = $resolver;
+ }
+
+ public function enhance(array $defaults, Request $request) {
+ if (isset($defaults['_content']) && !isset($defaults['_content_closure'])) {
+ // Clone the request and pretend like _content is the _controller
+ $request = clone $request;
+ $request->attributes->set('_controller', $defaults['_content']);
+
+ $controller = $this->resolver->getController($request);
+ $arguments = $this->resolver->getArguments($request, $controller);
+
+ $defaults['_content_closure'] = function() use ($controller, $arguments) {
+ return call_user_func_array($controller, $arguments);
+ };
+ }
+
+ return $defaults;
+ }
+}
diff --git a/core/lib/Drupal/Core/Booze/DisplayRouteEnhancer.php b/core/lib/Drupal/Core/Booze/DisplayRouteEnhancer.php
new file mode 100644
index 0000000..0d4c5f5
--- /dev/null
+++ b/core/lib/Drupal/Core/Booze/DisplayRouteEnhancer.php
@@ -0,0 +1,41 @@
+getPath()));
+ }
+ $defaults['_display'] = $entity;
+ }
+
+ return $defaults;
+ }
+}
diff --git a/core/lib/Drupal/Core/Booze/DrunkController.php b/core/lib/Drupal/Core/Booze/DrunkController.php
index 3e53325..4bd1cd3 100644
--- a/core/lib/Drupal/Core/Booze/DrunkController.php
+++ b/core/lib/Drupal/Core/Booze/DrunkController.php
@@ -7,13 +7,15 @@
namespace Drupal\Core\Booze;
-use SplObjectStorage;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
-
-use Drupal\Core\Config\Entity\Display;
+use Drupal\layout\Config\BoundDisplayInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Entity\EntityManager;
+use Drupal\block\Plugin\Core\Entity\Block;
+use Drupal\system\Plugin\block\block\SystemMainBlock;
/**
* Default controller for handling text/html responses.
@@ -25,12 +27,12 @@
class DrunkController implements ContainerAwareInterface {
/**
- * A SPLOS containing rendered block output, keyed by the block instance that
+ * An array containing rendered block output, keyed by the block instance that
* produced it.
*
- * @var \SplObjectStorage
+ * @var array
*/
- public $renderedBlocks;
+ public $renderedBlocks = array();
/**
* An associative array of rendered regions.
@@ -57,12 +59,23 @@ class DrunkController implements ContainerAwareInterface {
* The display configuration object containing layout and block information,
* used by this controller to assemble all page elements.
*
- * @var \Drupal\Core\Config\Entity\Display
+ * @var \Drupal\layout\Config\BoundDisplayInterface
*/
protected $display;
- public function __construct() {
- $this->renderedBlocks = new SplObjectStorage();
+ /**
+ * @var \Drupal\Core\Extension\ModuleHandlerInterface
+ */
+ protected $moduleHandler;
+
+ /**
+ * @var \Drupal\Core\Entity\EntityManager
+ */
+ protected $entityManager;
+
+ public function __construct(ModuleHandlerInterface $moduleHandler, EntityManager $entityManager) {
+ $this->moduleHandler = $moduleHandler;
+ $this->entityManager = $entityManager;
}
/**
@@ -83,16 +96,16 @@ public function setContainer(ContainerInterface $container = NULL) {
* 'compiled' of a template we have in the display. We either can handle it
* below here via a delegator pattern, or with sibling classes.
*
- * @param \Symfony\Component\HttpFoundation\Request $request
+ * @param \Symfony\Component\HttpFoundation\Request $request
* The request object.
- * @param \Drupal\Core\Config\Entity\Display $_display
+ * @param \Drupal\layout\Config\BoundDisplayInterface $_display
* A configuration object containing the layout instance and set of
* block instances that have been configured to be used for the current
* route.
*
* @return \Symfony\Component\HttpFoundation\Response
*/
- public function respond(Request $request, Display $_display) {
+ public function respond(Request $request, BoundDisplayInterface $_display) {
$this->display = $_display;
// Create a Response object right away that we can easily decorate as we go.
@@ -114,24 +127,24 @@ public function respond(Request $request, Display $_display) {
* @param \Symfony\Component\HttpFoundation\Request $request
*/
protected function renderBlocks(Request $request) {
- $attributes = $request->attributes;
- // Strip off stuff that can't go through to subrequests.
- $attributes->remove('system_path');
- $attributes->remove('_content');
+ foreach ($this->display->getAllBlockInfo() as $name => $info) {
+ $instance = entity_load('block', $name);
+ $plugin = $instance->getPlugin();
- $blocks = array(
- 'info' => array(),
- 'instances' => array(),
- );
+ // @todo this should be rolled into the more general pattern of context prep
+ if ($plugin instanceof SystemMainBlock) {
+ $instance->set('_content_closure', $request->attributes->get('_content_closure'));
+ }
- foreach ($this->display->getAllBlockInfo() as $name => $info) {
- $instance = block_manager()->getInstance(array('config' => $name));
// @todo block/pane styles - we're keeping them, right?
// @todo still need very much to handle context injection. yikes.
// @todo handle out-of-band attached stuff from blocks, e.g. css/js
- if ($info['method'] === 'direct') {
+ if (empty($info['method']) || $info['method'] === 'direct') {
// this is the direct rendering approach.
- $this->renderedBlocks[$instance] = $instance->render();
+ // Should probably not be called like this and not keyed by name but instance - dysrama
+ $this->renderedBlocks[$name] = $this->entityManager
+ ->getRenderController($instance->entityType())
+ ->render($instance);
}
elseif ($info['method'] === 'subrequest') {
// this routes rendering through a subrequest.
@@ -141,7 +154,7 @@ protected function renderBlocks(Request $request) {
// https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing/internal.xml
// https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Controller/InternalController.php
$response = $this->container->get('http_kernel')->forward(array($instance, 'render'), $attributes, $request->query->all());
- $this->renderedBlocks[$instance] = $response->getContent();
+ $this->renderedBlocks[$name] = $response->getContent();
}
}
}
@@ -162,7 +175,6 @@ protected function renderLayout(Request $request) {
foreach ($this->display->getBlocksByRegion($region) as $block) {
$to_render[] = $this->renderedBlocks[$block];
}
-
$this->renderedRegions[$region] = $layout->renderRegion($region);
}
}
diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index 035f282..f060450 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -212,6 +212,11 @@ public function build(ContainerBuilder $container) {
$container->register('paramconverter.entity', 'Drupal\Core\ParamConverter\EntityConverter')
->addArgument(new Reference('plugin.manager.entity'))
->addTag('paramconverter');
+ $container->register('display_route_enhancer', 'Drupal\Core\Booze\DisplayRouteEnhancer')
+ ->addTag('route_enhancer');
+ $container->register('content_route_enhancer', 'Drupal\Core\Booze\ContentRouteEnhancer')
+ ->addArgument(new Reference('controller_resolver'))
+ ->addTag('route_enhancer');
$container->register('router_processor_subscriber', 'Drupal\Core\EventSubscriber\RouteProcessorSubscriber')
->addArgument(new Reference('content_negotiation'))
@@ -270,6 +275,14 @@ public function build(ContainerBuilder $container) {
$container->register('flood', 'Drupal\Core\Flood\DatabaseBackend')
->addArgument(new Reference('database'));
+ $container->register('drunk_controller_subscriber', 'Drupal\Core\EventSubscriber\DrunkControllerSubscriber')
+ ->addArgument(new Reference('content_negotiation'))
+ ->addTag('event_subscriber');
+
+ $container->register('drunk_controller', 'Drupal\Core\Booze\DrunkController')
+ ->addArgument(new Reference('module_handler'))
+ ->addArgument(new Reference('plugin.manager.entity'));
+
$container->addCompilerPass(new RegisterMatchersPass());
$container->addCompilerPass(new RegisterRouteFiltersPass());
// Add a compiler pass for registering event subscribers.
diff --git a/core/lib/Drupal/Core/EventSubscriber/DrunkControllerSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/DrunkControllerSubscriber.php
new file mode 100644
index 0000000..d44015d
--- /dev/null
+++ b/core/lib/Drupal/Core/EventSubscriber/DrunkControllerSubscriber.php
@@ -0,0 +1,70 @@
+getRequest();
+
+ // @todo implement a separate flag and remove this hardmapping
+ if ('drunk_controller:respond' !== $request->attributes->get('_controller')
+ || $request->attributes->get('_display') instanceof BoundDisplayInterface) {
+ return;
+ }
+
+ $route = $request->attributes->get('_route');
+
+ if (!empty($route)) {
+ $display = entity_load('display', $route);
+ }
+
+ if (empty($display)) {
+ throw new NotFoundHttpException(sprintf('No display could be located for the route %s.', $route));
+ return;
+ }
+
+ $display->setMainContent($request->attributes->get('_content'));
+
+ $request->attributes->set('_display', $display);
+ }
+
+ /**
+ * Registers the methods in this class that should be listeners.
+ *
+ * @return array
+ * An array of event listener definitions.
+ */
+ public static function getSubscribedEvents() {
+ $events[KernelEvents::CONTROLLER][] = array('onDrunkenKernelController', 100);
+
+ return $events;
+ }
+}
\ No newline at end of file
diff --git a/core/lib/Drupal/Core/EventSubscriber/RouteProcessorSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RouteProcessorSubscriber.php
index 0061530..cb1862a 100644
--- a/core/lib/Drupal/Core/EventSubscriber/RouteProcessorSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/RouteProcessorSubscriber.php
@@ -39,7 +39,7 @@ public function onRequestSetController(GetResponseEvent $event) {
$request = $event->getRequest();
if (!$request->attributes->has('_controller') && $this->negotiation->getContentType($request) === 'html') {
- $request->attributes->set('_controller', '\Drupal\Core\HtmlPageController::content');
+ $request->attributes->set('_controller', 'drunk_controller:respond');
}
}
diff --git a/core/modules/block/lib/Drupal/block/BlockRenderController.php b/core/modules/block/lib/Drupal/block/BlockRenderController.php
index e705310..cc751f2 100644
--- a/core/modules/block/lib/Drupal/block/BlockRenderController.php
+++ b/core/modules/block/lib/Drupal/block/BlockRenderController.php
@@ -87,4 +87,15 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la
return $build;
}
+ /**
+ * Use render instead of view
+ * @param EntityInterface $entity
+ * @param type $view_mode
+ * @param type $langcode
+ * @return type
+ */
+ public function render(EntityInterface $entity, $langcode = NULL) {
+ $render = $this->view($entity, 'block', $langcode);
+ return drupal_render($render);
+ }
}
diff --git a/core/modules/layout/layout.info b/core/modules/layout/layout.info
index 187bfea..4d5d23a 100644
--- a/core/modules/layout/layout.info
+++ b/core/modules/layout/layout.info
@@ -3,3 +3,4 @@ description = Makes it possible to swap different page layouts.
package = Core
version = VERSION
core = 8.x
+required = TRUE
diff --git a/core/modules/layout/lib/Drupal/layout/Config/UnboundDisplayStorageController.php b/core/modules/layout/lib/Drupal/layout/Config/UnboundDisplayStorageController.php
index adf4675..dc28ef3 100644
--- a/core/modules/layout/lib/Drupal/layout/Config/UnboundDisplayStorageController.php
+++ b/core/modules/layout/lib/Drupal/layout/Config/UnboundDisplayStorageController.php
@@ -9,6 +9,11 @@
use Drupal\Core\Config\Entity\ConfigStorageController;
use Drupal\layout\Plugin\Core\Entity\Display;
+/**
+ * Storage controller for Unbound Displays.
+ *
+ * @see \Drupal\layout\Config\UnboundDisplayInterface
+ */
class UnboundDisplayStorageController extends ConfigStorageController {
public function importCreate($name, Config $new_config, Config $old_config) {
// First, import the unbound display into active config
diff --git a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMainBlock.php b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMainBlock.php
index 2f10f57..ea6a137 100644
--- a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMainBlock.php
+++ b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMainBlock.php
@@ -26,9 +26,13 @@ class SystemMainBlock extends BlockBase {
* Implements \Drupal\block\BlockBase::build().
*/
public function build() {
- return array(
- drupal_set_page_content()
- );
+ // @todo this lets the old way work transparently while we do new stuff.
+ if ($ret = drupal_set_page_content()) {
+ return array($ret);
+ }
+
+ $callback = $this->entity->get('_content_closure');
+ return call_user_func($callback);
}
}
diff --git a/core/profiles/standard/config/display.bound.frontend.yml b/core/profiles/standard/config/display.bound.frontend.yml
new file mode 100644
index 0000000..e1161b4
--- /dev/null
+++ b/core/profiles/standard/config/display.bound.frontend.yml
@@ -0,0 +1,35 @@
+id: frontend
+label: Frontend master display
+layout: static_layout:bartik__frontend
+layoutSettings: { }
+blockInfo:
+# these have bartik in their namespace, but that's irrelevant to our use here -
+# we're just reusing them while we get everything together.
+ block.block.bartik.help:
+ region: help
+ region-type: content
+ weight: 0 # should float in unbound/master
+ block.block.bartik.content:
+ region: content
+ region-type: content
+ weight: 0 # should float in unbound/master
+ block.block.bartik.footer:
+ region: footer
+ region-type: footer
+ weight: 0 # stick-top in unbound/master
+ block.block.bartik.powered:
+ region: footer
+ region-type: footer
+ weight: 10 # float in unbound/master
+ block.block.bartik.search:
+ region: sidebar_first
+ region-type: aside
+ weight: 0 # stick-top in unbound/master
+ block.block.bartik.login:
+ region: sidebar_first
+ region-type: aside
+ weight: 10 # stick-top in unbound/master
+ block.block.bartik.tools:
+ region: sidebar_first
+ region-type: aside
+ weight: 20 # stick-top in unbound/master
\ No newline at end of file
diff --git a/core/profiles/standard/standard.install b/core/profiles/standard/standard.install
index de24c4a..10f67cb 100644
--- a/core/profiles/standard/standard.install
+++ b/core/profiles/standard/standard.install
@@ -22,7 +22,7 @@ function standard_install() {
// Set front page to "node".
config('system.site')->set('page.front', 'node')->save();
// Set default layout to Bartik's frontend layout.
- config('system.site')->set('default_layout', 'bartik__frontend');
+ config('system.site')->set('default_layout', 'static_layout:bartik__frontend');
// Insert default pre-defined node types into the database. For a complete
// list of available node type attributes, refer to the node type API
diff --git a/core/themes/bartik/layouts/static/frontend/frontend.html.twig b/core/themes/bartik/layouts/static/frontend/frontend.html.twig
index 8640fe7..195e411 100644
--- a/core/themes/bartik/layouts/static/frontend/frontend.html.twig
+++ b/core/themes/bartik/layouts/static/frontend/frontend.html.twig
@@ -1,106 +1,146 @@
{#
-/**
- * @file
- * Bartik's theme implementation to display a single Drupal page.
- *
- * The doctype, html, head, and body tags are not in this template. Instead
- * they can be found in the html.tpl.php template normally located in the
- * core/modules/system directory.
- *
- * Available variables:
- *
- * General utility variables:
- * - $base_path: The base URL path of the Drupal installation. At the very
- * least, this will always default to /.
- * - $directory: The directory the template is located in, e.g. modules/system
- * or themes/bartik.
- * - $is_front: TRUE if the current page is the front page.
- * - $logged_in: TRUE if the user is registered and signed in.
- * - $is_admin: TRUE if the user has permission to access administration pages.
- *
- * Site identity:
- * - $front_page: The URL of the front page. Use this instead of $base_path,
- * when linking to the front page. This includes the language domain or
- * prefix.
- * - $logo: The path to the logo image, as defined in theme configuration.
- * - $site_name: The name of the site, empty when display has been disabled
- * in theme settings.
- * - $site_slogan: The slogan of the site, empty when display has been disabled
- * in theme settings.
- * - $hide_site_name: TRUE if the site name has been toggled off on the theme
- * settings page. If hidden, the "element-invisible" class is added to make
- * the site name visually hidden, but still accessible.
- * - $hide_site_slogan: TRUE if the site slogan has been toggled off on the
- * theme settings page. If hidden, the "element-invisible" class is added to
- * make the site slogan visually hidden, but still accessible.
- *
- * Navigation:
- * - $main_menu (array): An array containing the Main menu links for the
- * site, if they have been configured.
- * - $secondary_menu (array): An array containing the Secondary menu links for
- * the site, if they have been configured.
- * - $breadcrumb: The breadcrumb trail for the current page.
- *
- * Page content (in order of occurrence in the default page.tpl.php):
- * - $title_prefix (array): An array containing additional output populated by
- * modules, intended to be displayed in front of the main title tag that
- * appears in the template.
- * - $title: The page title, for use in the actual HTML content.
- * - $title_suffix (array): An array containing additional output populated by
- * modules, intended to be displayed after the main title tag that appears in
- * the template.
- * - $messages: HTML for status and error messages. Should be displayed
- * prominently.
- * - $tabs (array): Tabs linking to any sub-pages beneath the current page
- * (e.g., the view and edit tabs when displaying a node).
- * - $action_links (array): Actions local to the page, such as 'Add menu' on
- * the menu administration interface.
- * - $feed_icons: A string of all feed icons for the current page.
- * - $node: The node entity, if there is an automatically-loaded node
- * associated with the page, and the node ID is the second argument
- * in the page's path (e.g. node/12345 and node/12345/revisions, but not
- * comment/reply/12345).
- *
- * Regions:
- * - $page['header']: Items for the header region.
- * - $page['featured']: Items for the featured region.
- * - $page['highlighted']: Items for the highlighted content region.
- * - $page['help']: Dynamic help text, mostly for admin pages.
- * - $page['content']: The main content of the current page.
- * - $page['sidebar_first']: Items for the first sidebar.
- * - $page['sidebar_second']: Items for the second sidebar.
- * - $page['triptych_first']: Items for the first triptych.
- * - $page['triptych_middle']: Items for the middle triptych.
- * - $page['triptych_last']: Items for the last triptych.
- * - $page['footer_firstcolumn']: Items for the first footer column.
- * - $page['footer_secondcolumn']: Items for the second footer column.
- * - $page['footer_thirdcolumn']: Items for the third footer column.
- * - $page['footer_fourthcolumn']: Items for the fourth footer column.
- * - $page['footer']: Items for the footer region.
- *
- * @see template_preprocess()
- * @see template_preprocess_page()
- * @see template_process()
- * @see bartik_process_page()
- * @see html.tpl.php
- *
- * @ingroup themeable
- */
+
+@file
+Bartik's primary frontend layout implementation.
+
+
+The doctype, html, head, and body tags are not in this template. Instead
+they can be found in the html.tpl.php template normally located in the
+core/modules/system directory.
+
+Available variables:
+
+General utility variables:
+- base_path: The base URL path of the Drupal installation. At the very
+ least, this will always default to /.
+- directory: The directory the template is located in, e.g. modules/system
+ or themes/bartik.
+- is_front: TRUE if the current page is the front page.
+- logged_in: TRUE if the user is registered and signed in.
+- is_admin: TRUE if the user has permission to access administration pages.
+
+Site identity:
+- front_page: The URL of the front page. Use this instead of base_path,
+ when linking to the front page. This includes the language domain or
+ prefix.
+- logo: The path to the logo image, as defined in theme configuration.
+- site_name: The name of the site, empty when display has been disabled
+ in theme settings.
+- site_slogan: The slogan of the site, empty when display has been disabled
+ in theme settings.
+- hide_site_name: TRUE if the site name has been toggled off on the theme
+ settings page. If hidden, the "element-invisible" class is added to make
+ the site name visually hidden, but still accessible.
+- hide_site_slogan: TRUE if the site slogan has been toggled off on the
+ theme settings page. If hidden, the "element-invisible" class is added to
+ make the site slogan visually hidden, but still accessible.
+
+Navigation:
+- main_menu (array): An array containing the Main menu links for the
+ site, if they have been configured.
+- secondary_menu (array): An array containing the Secondary menu links for
+ the site, if they have been configured.
+- breadcrumb: The breadcrumb trail for the current page.
+
+Page content (in order of occurrence in the default page.tpl.php):
+- title_prefix (array): An array containing additional output populated by
+ modules, intended to be displayed in front of the main title tag that
+ appears in the template.
+- title: The page title, for use in the actual HTML content.
+- title_suffix (array): An array containing additional output populated by
+ modules, intended to be displayed after the main title tag that appears in
+ the template.
+- messages: HTML for status and error messages. Should be displayed
+ prominently.
+- tabs (array): Tabs linking to any sub-pages beneath the current page
+ (e.g., the view and edit tabs when displaying a node).
+- action_links (array): Actions local to the page, such as 'Add menu' on
+ the menu administration interface.
+- feed_icons: A string of all feed icons for the current page.
+- node: The node entity, if there is an automatically-loaded node
+ associated with the page, and the node ID is the second argument
+ in the page's path (e.g. node/12345 and node/12345/revisions, but not
+ comment/reply/12345).
+
+Regions:
+- page.header: Items for the header region.
+- page.featured: Items for the featured region.
+- page.highlighted: Items for the highlighted content region.
+- page.help: Dynamic help text, mostly for admin pages.
+- page.content: The main content of the current page.
+- page.sidebar_first: Items for the first sidebar.
+- page.sidebar_second: Items for the second sidebar.
+- page.triptych_first: Items for the first triptych.
+- page.triptych_middle: Items for the middle triptych.
+- page.triptych_last: Items for the last triptych.
+- page.footer_firstcolumn: Items for the first footer column.
+- page.footer_secondcolumn: Items for the second footer column.
+- page.footer_thirdcolumn: Items for the third footer column.
+- page.footer_fourthcolumn: Items for the fourth footer column.
+- page.footer: Items for the footer region.
+
+@see template_preprocess()
+@see template_preprocess_page()
+@see template_process()
+@see bartik_process_page()
+@see html.tpl.php
+
+@ingroup themeable
+
#}
+
+{# system is emitted before & above everything else #}
+{% if page.system %}{{ page.system }}{% endif %}
+
- {% if page.header is defined %}
+ {% if page.header %}