Commit ba144426 authored by Dries's avatar Dries

Issue #2053879 by tstoeckler, effulgentsia: Remove layout.module from core.

parent ded07e9a
.layout-display {
background: rgb(224, 224, 224);
}
.layout-region-demonstration {
background-image: -moz-linear-gradient(bottom, rgb(70,70,71) 40%, rgb(91,91,94) 70%, rgb(125,124,125) 88%);
background-image: -o-linear-gradient(bottom, rgb(70,70,71) 40%, rgb(91,91,94) 70%, rgb(125,124,125) 88%);
background-image: -ms-linear-gradient(bottom, rgb(70,70,71) 40%, rgb(91,91,94) 70%, rgb(125,124,125) 88%);
background-image: -webkit-linear-gradient(bottom, rgb(70,70,71) 40%, rgb(91,91,94) 70%, rgb(125,124,125) 88%);
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.4, rgb(70,70,71)), color-stop(0.7, rgb(91,91,94)), color-stop(0.88, rgb(125,124,125)));
background-image: linear-gradient(bottom, rgb(70,70,71) 40%, rgb(91,91,94) 70%, rgb(125,124,125) 88%);
color: white;
font-size: 0.8em;
margin: 3px;
padding: 10px;
text-transform: uppercase;
}
name: Layout
type: module
description: 'Makes it possible to swap different page layouts.'
package: Core
version: VERSION
core: 8.x
<?php
/**
* @file
* Manages page layouts for content presentation.
*/
/**
* Implements hook_menu().
*/
function layout_menu() {
$items['admin/structure/templates'] = array(
'title' => 'Templates',
'description' => 'Overview of the list of layout templates available.',
'route_name' => 'layout_page_list',
);
$items['admin/structure/templates/manage/%'] = array(
'title' => 'View template',
'route_name' => 'layout_page_view',
);
return $items;
}
/**
* Implements hook_permission().
*/
function layout_permission() {
return array(
'administer layouts' => array(
'title' => t('Administer templates'),
'description' => t('Access administration functions for templates.'),
),
);
}
/**
* Implements hook_theme().
*
* Expose all layouts as theme items, so themes can override layout markup.
*/
function layout_theme($existing, $type, $theme, $path) {
$items = array();
foreach (Drupal::service('plugin.manager.layout')->getDefinitions() as $name => $layout) {
$items[$layout['theme']] = array(
'variables' => array('content' => NULL),
'path' => $layout['path'],
'template' => $layout['template'],
);
}
return $items;
}
layout_page_list:
pattern: '/admin/structure/templates'
defaults:
_content: '\Drupal\layout\Controller\LayoutController::layoutPageList'
requirements:
_permission: 'administer layouts'
layout_page_view:
pattern: '/admin/structure/templates/manage/{key}'
defaults:
_content: '\Drupal\layout\Controller\LayoutController::layoutPageView'
options:
_access_mode: 'ALL'
requirements:
_permission: 'administer layouts'
_access_layout_user: 'TRUE'
services:
plugin.manager.layout:
class: Drupal\layout\Plugin\Type\LayoutManager
arguments: ['@container.namespaces']
access_check.layout:
class: Drupal\layout\Access\LayoutAccessCheck
arguments: ['@plugin.manager.layout']
tags:
- { name: access_check }
{#
/**
* @file
* Template for a 1 column layout.
*
* This template provides a simple one column display layout.
*
* Avaiable variables:
* - attributes: Attributes to be placed on the wrapping element.
* - content: All content items, each content item is keyed to one region of the
* layout. 'content' contains the following section:
* - content: Content in the content column.
*
* @ingroup themeable
*/
#}
<div class="layout-display layout-one-col {{ attributes.class }}"{{ attributes }}>
<div class="layout-region">
{{ content.content }}
</div>
</div>
title: One column
category: Columns: 1
template: one-col
regions:
content:
label: Middle column
type: content
\ No newline at end of file
/* Large resolutions (desktop, tablets in landscape, ...) */
@media only screen and (min-width: 59em) {
.layout-two-col .layout-region {
float: left; /* LTR */
width: 50%;
}
[dir="rtl"] .layout-two-col .layout-region {
float: right;
}
}
{#
/**
* @file
* Template for a 2 column layout.
*
* This template provides a two column display layout, with each column equal in
* width.
*
* Available variables:
* - attributes: Attributes to be placed on the wrapping element.
* - content: All content items, each content item is keyed to one region of the
* layout. 'content' contains the following sections:
* - first: Content in the first column.
* - second: Content in the second column.
*
* @ingroup themeable
*/
#}
<div class="layout-display layout-two-col clearfix {{ attributes.class }}"{{ attributes }}>
<div class="layout-region layout-col-first">
{{ content.first }}
</div>
<div class="layout-region layout-col-second">
{{ content.second }}
</div>
</div>
title: Two column
category: Columns: 2
template: two-col
stylesheets:
- two-col.css
regions:
first:
label: Left side
type: content
second:
label: Right side
type: aside
<?php
/**
* @file
* Contains \Drupal\layout\Access\LayoutAccessCheck.
*/
namespace Drupal\layout\Access;
use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Core\Access\StaticAccessCheckInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\HttpFoundation\Request;
/**
* Checks layout access.
*/
class LayoutAccessCheck implements StaticAccessCheckInterface {
/**
* The layout manager.
*
* @var \Drupal\Component\Plugin\PluginManagerInterface
*/
protected $layoutManager;
/**
* Constructs a LayoutAccessCheck object.
*
* @param \Drupal\Component\Plugin\PluginManagerInterface $layout_manager
* The layout manager.
*/
public function __construct(PluginManagerInterface $layout_manager) {
$this->layoutManager = $layout_manager;
}
/**
* {@inheritdoc}
*/
public function appliesTo() {
return '_access_layout_user';
}
/**
* {@inheritdoc}
*/
public function access(Route $route, Request $request) {
return $this->layoutManager->getDefinition($request->attributes->get('key')) ? static::ALLOW : static::DENY;
}
}
<?php
/**
* @file
* Definition of Drupal\layout\Config\BoundDisplayInterface
*/
namespace Drupal\layout\Config;
use Drupal\layout\Plugin\LayoutInterface;
/**
* Interface for a Display object that is coupled to a specific layout.
*
* Bound displays contains references both to block instances and a specific
* layout, and the blocks are assigned to specific regions in that layout. Bound
* displays are used to serve real pages at request time.
*
* @see \Drupal\layout\Config\DisplayInterface
*/
interface BoundDisplayInterface extends DisplayInterface {
/**
* Sets the layout to be used by this display.
*
* @param string $layout_id
* The id of the desired layout.
*/
public function setLayout($layout_id);
/**
* Returns the blocks in the requested region, ordered by weight.
*
* @param string $region
* The region from which to return the set of blocks.
*
* @return array
* The list of blocks, ordered by their weight within this display. Each
* value in the list is the configuration object name of the block.
*/
public function getSortedBlocksByRegion($region);
/**
* Returns this display's blocks, organized by region and ordered by weight.
*
* @return array
* An array keyed by region name. For each region, the value is the same as
* what is returned by getSortedBlocksByRegion().
*
* @see getSortedBlocksByRegion()
*/
public function getAllSortedBlocks();
/**
* Returns the instantiated layout object to be used by this display.
*
* @return \Drupal\layout\Plugin\LayoutInterface
*/
public function getLayoutInstance();
/**
* Adjusts this display's block placement to work with the provided layout.
*
* Essentially a shortcut that calls DisplayInterface::mapBlocksToLayout(),
* saves the result in the appropriate object property, and finally calls
* BoundDisplayInterface::setLayout().
*
* @param \Drupal\layout\Plugin\LayoutInterface $layout
* The new layout to which blocks should be remapped.
*
* @see \Drupal\layout\Config\DisplayInterface::mapBlocksToLayout()
*/
public function remapToLayout(LayoutInterface $layout);
/**
* Returns an entity with the non-layout-specific configuration of this one.
*
* @param string $id
* The entity id to assign to the newly created entity.
*
* @param string $entity_type
* The type of entity to create. The PHP class for this entity type must
* implement \Drupal\layout\Config\UnboundDisplayInterface.
*
* @return \Drupal\layout\Config\UnboundDisplayInterface
* The newly-created unbound display.
*/
public function generateUnboundDisplay($id, $entity_type = 'unbound_display');
}
<?php
/**
* @file
* Definition of Drupal\layout\Config\DisplayBase.
*/
namespace Drupal\layout\Config;
use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\layout\Plugin\LayoutInterface;
/**
* Base class for 'display' and 'unbound_display' configuration entities.
*
* @see \Drupal\layout\Config\DisplayInterface
*/
abstract class DisplayBase extends ConfigEntityBase implements DisplayInterface {
/**
* The ID (config name) identifying a specific display object.
*
* @var string
*/
public $id;
/**
* The UUID identifying a specific display object.
*
* @var string
*/
public $uuid;
/**
* Contains all block configuration.
*
* There are two levels to the configuration contained herein: display-level
* block configuration, and then block instance configuration.
*
* Block instance configuration is stored in a separate config object. This
* array is keyed by the config name that uniquely identifies each block
* instance. At runtime, various object methods will retrieve this additional
* config and return it to calling code.
*
* Display-level block configuration is data that determines the behavior of
* a block *in this display*. The most important examples of this are the
* region to which the block is assigned, and its weighting in that region.
*
* @code
* array(
* 'block1-configkey' => array(
* 'region' => 'content',
* // store the region type name here so that we can do type conversion w/out
* // needing to have access to the original layout plugin
* 'region-type' => 'content',
* // increment by 100 so there is ALWAYS plenty of space for manual insertion
* 'weight' => -100,
* ),
* 'block2-configkey' => array(
* 'region' => 'sidebar_first',
* 'region-type' => 'aside',
* 'weight' => -100,
* ),
* 'block2-configkey' => array(
* 'region' => 'sidebar_first',
* 'region-type' => 'aside',
* 'weight' => 0,
* ),
* 'maincontent' => array(
* 'region' => 'content',
* 'region-type' => 'content',
* 'weight' => -200,
* ),
* );
* @endcode
*
* @var array
*/
protected $blockInfo = array();
/**
* Implements DisplayInterface::getAllBlockInfo().
*/
public function getAllBlockInfo() {
return $this->blockInfo;
}
/**
* Implements DisplayInterface::mapBlocksToLayout().
*
* @todo Decouple this implementation from this class, so that it could be
* more easily customized.
*/
public function mapBlocksToLayout(LayoutInterface $layout) {
$types = array();
$layout_regions = $layout->getRegions();
$layout_regions_indexed = array_keys($layout_regions);
foreach ($layout_regions as $name => $info) {
$types[$info['type']][] = $name;
}
$remapped_config = array();
foreach ($this->blockInfo as $name => $info) {
// First, if there's a direct region name match, use that.
if (!empty($info['region']) && isset($layout_regions[$info['region']])) {
// No need to do anything.
}
// Then, try to remap using region types.
else if (!empty($types[$info['region-type']])) {
$info['region'] = reset($types[$info['region-type']]);
}
// Finally, fall back to dumping everything in the layout's first region.
else {
if (!isset($first_region)) {
reset($layout_regions);
$first_region = key($layout_regions);
}
$info['region'] = $first_region;
}
$remapped_config[$name] = $info;
}
return $remapped_config;
}
/**
* Implements DisplayInterface::getAllRegionTypes().
*/
public function getAllRegionTypes() {
$types = array();
foreach ($this->blockInfo as $info) {
$types[] = $info['region-type'];
}
return array_unique($types);
}
}
<?php
/**
* @file
* Definition of Drupal\layout\Config\DisplayInterface
*/
namespace Drupal\layout\Config;
use Drupal\layout\Plugin\LayoutInterface;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
/**
* Interface describing a Display configuration object.
*
* Displays are configuration that describe the placement of block instances
* in regions. Drupal includes two types of Display objects:
* - Bound displays include a reference to a specific layout, and each block is
* specified to display in a specific region of that layout. Bound displays
* are used to serve real pages at request time.
* - Unbound displays do not include a reference to any layout, and each block
* is assigned a region type, but not a specific region. Developers including
* default displays with their modules or distributions are encouraged to use
* unbound displays in order to minimize dependencies on specific layouts and
* allow site-specific configuration to dictate the layout.
*
* This interface defines what is common to all displays, whether bound or
* unbound.
*
* @see \Drupal\layout\Config\BoundDisplayInterface
* @see \Drupal\layout\Config\UnboundDisplayInterface
*/
interface DisplayInterface extends ConfigEntityInterface {
/**
* Returns the display-specific configuration of all blocks in this display.
*
* For each block that exists in Drupal (e.g., the "Who's Online" block),
* multiple "configured instances" can be created (e.g., a "Who's been online
* in the last 5 minutes" instance and a "Who's been online in the last 60
* minutes" instance). Each configured instance can be referenced by multiple
* displays (e.g., by a "regular" page, by an administrative page, and within
* one or more dashboards). This function returns the block instances that
* have been added to this display. Each key of the returned array is the
* block instance's configuration object name, and \Drupal::config() may be called on
* it in order to retrieve the full configuration that is shared across all
* displays. For each key, the value is an array of display-specific
* configuration, primarily the 'region' and 'weight', and anything else that
* affects the placement of the block within the layout rather than only the
* contents of the block.
*
* @return array
* An array keyed on each block's configuration object name. Each value is
* an array of information that determines the placement of the block within
* a layout, including:
* - region: The region in which to display the block (for bound displays
* only).
* - region-type: The type of region that is most appropriate for the block.
* Usually one of 'header', 'footer', 'nav', 'content', 'aside', or
* 'system', though custom region types are also allowed. This is
* primarily specified by unbound displays, where specifying a specific
* region name is impossible, because different layouts come with
* different regions.
* - weight: Within a region, blocks are rendered from low to high weight.
*/
public function getAllBlockInfo();
/**
* Maps the contained block info to the provided layout.
*
* @param \Drupal\layout\Plugin\LayoutInterface $layout
*
* @return array
* An array containing block configuration info, identical to that which
* is returned by DisplayInterface::getAllBlockInfo().
*/
public function mapBlocksToLayout(LayoutInterface $layout);
/**
* Returns the names of all region types to which blocks are assigned.
*
* @return array
* An indexed array of unique region type names, or an empty array if no
* region types were assigned.
*/
public function getAllRegionTypes();
}
<?php
/**
* @file
* Definition of Drupal\layout\Config\UnboundDisplayInterface
*/
namespace Drupal\layout\Config;
use Drupal\layout\Plugin\LayoutInterface;
/**
* Interface for a Display that is not coupled with any layout.
*
* Unbound displays contain references to blocks, but not to any particular
* layout. Their primary use case is to express a set of relative block
* placements without necessitating any particular layout be present. This
* allows upstream (module and distribution) developers to express a visual
* composition of blocks without knowing anything about the layouts a
* particular site has available.
*
* @see \Drupal\layout\Config\DisplayInterface
*/
interface UnboundDisplayInterface extends DisplayInterface {
/**
* Returns a bound display entity by binding a layout to this unbound display.
*
* This will DisplayInterface::mapBlocksToLayout() using the provided layout,
* then create and return a new Display object with the output. This is just
* a factory - calling code is responsible for saving the returned object.
*
* @param \Drupal\layout\Plugin\LayoutInterface $layout
* The desired layout.
*
* @param string $id
* The entity id to assign to the newly created entity.
*
* @param string $entity_type
* The type of entity to create. The PHP class for this entity type must
* implement \Drupal\layout\Config\BoundDisplayInterface.
*
* @return \Drupal\layout\Config\BoundDisplayInterface
* The newly created entity.
*/
public function generateDisplay(LayoutInterface $layout, $id, $entity_type = 'display');
}
<?php
/**
* @file
* Contains \Drupal\layout\Controller\LayoutController.
*/
namespace Drupal\layout\Controller;
use Drupal\Component\Utility\String;
use Drupal\Core\Controller\ControllerInterface;
use Drupal\layout\Plugin\Type\LayoutManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Controller routines for layout routes.
*/
class LayoutController implements ControllerInterface {
/**
* Stores the Layout manager.
*
* @var \Drupal\layout\Plugin\Type\LayoutManager
*/
protected $layoutManager;
/**
* Constructs a \Drupal\layout\Controller\LayoutController object.
*
* @param \Drupal\layout\Plugin\Type\LayoutManager $layout_manager
* The Layout manager.
*/
function __construct(LayoutManager $layout_manager) {
$this->layoutManager = $layout_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('plugin.manager.layout'));
}
/**
* Presents a list of layouts.
*
* @return array
* A form array as expected by drupal_render().
*/
public function layoutPageList() {
// Get list of layouts defined by enabled modules and themes.
$layouts = $this->layoutManager->getDefinitions();
$rows = array();