diff --git a/core/lib/Drupal/Core/Booze/DrunkController.php b/core/lib/Drupal/Core/Booze/DrunkController.php new file mode 100644 index 0000000..3e53325 --- /dev/null +++ b/core/lib/Drupal/Core/Booze/DrunkController.php @@ -0,0 +1,169 @@ +renderedBlocks = new SplObjectStorage(); + } + + /** + * Injects the service container used by this object. + * + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container + * The service container this object should use. + */ + public function setContainer(ContainerInterface $container = NULL) { + $this->container = $container; + } + + /** + * Controller method for normal rendering of blocks and layouts-driven HTML + * page. + * + * @todo the output may need more or less assembling, depending on how + * '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 + * The request object. + * @param \Drupal\Core\Config\Entity\Display $_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) { + $this->display = $_display; + + // Create a Response object right away that we can easily decorate as we go. + $this->response = new Response(); + + $this->renderBlocks($request); + $this->renderLayout($request); + // @todo handle out-of-band stuff, e.g. css/js + + $content = $this->display->getLayoutPluginInstance()->renderLayout($this->renderedRegions); + $this->response->setContent($content); + + return $this->response; + } + + /** + * Renders all blocks contained in the current display object. + * + * @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'); + + $blocks = array( + 'info' => array(), + 'instances' => array(), + ); + + 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') { + // this is the direct rendering approach. + $this->renderedBlocks[$instance] = $instance->render(); + } + elseif ($info['method'] === 'subrequest') { + // this routes rendering through a subrequest. + // @todo When we have a Generator, we can replace the forward() call with + // a render() call, which would handle ESI and hInclude as well. That will + // require an _internal route. For examples, see: + // 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(); + } + } + } + + /** + * Renders all rendered blocks into their respective layout regions, using + * the layout attached to the current display object. + * + * @param \Symfony\Component\HttpFoundation\Request $request + */ + protected function renderLayout(Request $request) { + $layout = $this->display->getLayoutPluginInstance(); + // @todo need to add this method to the layout plugin interface. + // @todo this is another place we could do block placement renegotiation by region role (@see Display) + foreach ($layout->getRegions() as $region => $info) { + // @todo region styles, if we do them, would go in around here + $to_render = array(); + foreach ($this->display->getBlocksByRegion($region) as $block) { + $to_render[] = $this->renderedBlocks[$block]; + } + + $this->renderedRegions[$region] = $layout->renderRegion($region); + } + } +}