diff --git a/core/modules/layout/layout.info b/core/modules/layout/layout.info
new file mode 100644
index 0000000..187bfea
--- /dev/null
+++ b/core/modules/layout/layout.info
@@ -0,0 +1,5 @@
+name = Layout
+description = Makes it possible to swap different page layouts.
+package = Core
+version = VERSION
+core = 8.x
diff --git a/core/modules/layout/layout.module b/core/modules/layout/layout.module
new file mode 100644
index 0000000..7b0ab2c
--- /dev/null
+++ b/core/modules/layout/layout.module
@@ -0,0 +1,39 @@
+renderLayout().
+ */
+function layout_page_build(&$page) {
+ $request = drupal_container()->get('request');
+ $options = array(
+ 'request' => $request,
+ );
+ $layout = layout_manager()->getInstance($options);
+ if ($layout) {
+ $page['#children'] = $layout->renderLayout();
+ $page['#theme'] = NULL;
+ }
+}
+
+/**
+ * Get the layout plugin manager instance.
+ *
+ * @return Drupal\layout\Plugin\Type\LayoutManager
+ * The layout plugin manager instance.
+ */
+function layout_manager() {
+ return drupal_container()->get('plugin.manager.layout');
+}
diff --git a/core/modules/layout/layout/onecol/layout--onecol.tpl.php b/core/modules/layout/layout/onecol/layout--onecol.tpl.php
new file mode 100644
index 0000000..27eefa9
--- /dev/null
+++ b/core/modules/layout/layout/onecol/layout--onecol.tpl.php
@@ -0,0 +1,19 @@
+
+
diff --git a/core/modules/layout/layout/onecol/onecol.css b/core/modules/layout/layout/onecol/onecol.css
new file mode 100644
index 0000000..9515b54
--- /dev/null
+++ b/core/modules/layout/layout/onecol/onecol.css
@@ -0,0 +1,22 @@
+
+.layout-1col {
+/* overflow: hidden; */
+}
+
+.layout-2col .layout-col-first .inside {
+ margin: 0;
+}
+
+
+.layout-1col .layout-col {
+ width: 100%;
+}
+
+#layout-edit-display .layout-region,
+#layout-edit-display .helperclass {
+ margin: .5em;
+}
+
+.layout-2col .layout-separator {
+ margin: 0 0 1em 0;
+}
diff --git a/core/modules/layout/layout/onecol/onecol.yml b/core/modules/layout/layout/onecol/onecol.yml
new file mode 100644
index 0000000..2ad8959
--- /dev/null
+++ b/core/modules/layout/layout/onecol/onecol.yml
@@ -0,0 +1,6 @@
+title: Single column
+category: Columns: 1
+icon: onecol.png
+css: onecol.css
+regions:
+ middle: 'Middle column'
diff --git a/core/modules/layout/layout/twocol/layout--twocol.tpl.php b/core/modules/layout/layout/twocol/layout--twocol.tpl.php
new file mode 100644
index 0000000..90a69af
--- /dev/null
+++ b/core/modules/layout/layout/twocol/layout--twocol.tpl.php
@@ -0,0 +1,25 @@
+
+
diff --git a/core/modules/layout/layout/twocol/twocol.css b/core/modules/layout/layout/twocol/twocol.css
new file mode 100644
index 0000000..ecbd867
--- /dev/null
+++ b/core/modules/layout/layout/twocol/twocol.css
@@ -0,0 +1,37 @@
+
+.layout-2col {
+/* overflow: hidden; */
+}
+
+.layout-2col .layout-col-first {
+ float: left;
+ width: 50%;
+}
+* html .layout-2col .layout-col-first {
+ width: 49.9%;
+}
+
+.layout-2col .layout-col-first .inside {
+ margin: 0 .5em 1em 0;
+}
+
+.layout-2col .layout-col-last {
+ float: left;
+ width: 50%;
+}
+* html .layout-2col .layout-col-last {
+ width: 49.9%;
+}
+
+.layout-2col .layout-col-last .inside {
+ margin: 0 0 1em .5em;
+}
+
+#layout-edit-display .layout-region,
+#layout-edit-display .helperclass {
+ margin: .5em;
+}
+
+.layout-2col .layout-separator {
+ margin: 0 0 1em 0;
+}
diff --git a/core/modules/layout/layout/twocol/twocol.yml b/core/modules/layout/layout/twocol/twocol.yml
new file mode 100644
index 0000000..90c4a3e
--- /dev/null
+++ b/core/modules/layout/layout/twocol/twocol.yml
@@ -0,0 +1,7 @@
+title: Two column
+category: Columns: 2
+icon: twocol.png
+css: twocol.css
+regions:
+ left: 'Left side'
+ right: 'Right side'
diff --git a/core/modules/layout/lib/Drupal/layout/LayoutBundle.php b/core/modules/layout/lib/Drupal/layout/LayoutBundle.php
new file mode 100644
index 0000000..92b4796
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/LayoutBundle.php
@@ -0,0 +1,24 @@
+register('plugin.manager.layout', 'Drupal\layout\Plugin\Type\LayoutManager');
+ }
+}
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/Derivative/Layout.php b/core/modules/layout/lib/Drupal/layout/Plugin/Derivative/Layout.php
new file mode 100644
index 0000000..f7a9146
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/Derivative/Layout.php
@@ -0,0 +1,74 @@
+derivatives) && !empty($this->derivatives[$derivative_id])) {
+ return $this->derivatives[$derivative_id];
+ }
+ $this->getDerivativeDefinitions($base_plugin_definition);
+ return $this->derivatives[$derivative_id];
+ }
+
+ /**
+ * Implements DerivativeInterface::getDerivativeDefinitions().
+ */
+ public function getDerivativeDefinitions(array $base_plugin_definition) {
+ $available_layout_providers = array();
+ foreach (module_list() as $module) {
+ $available_layout_providers[$module] = array(
+ 'type' => 'module',
+ 'provider' => $module,
+ 'dir' => drupal_get_path('module', $module),
+ );
+ }
+ foreach (list_themes() as $theme_id => $theme) {
+ $available_layout_providers[$theme_id] = array(
+ 'type' => 'theme',
+ 'provider' => $theme->name,
+ 'dir' => drupal_get_path('theme', $theme->name),
+ );
+ }
+ foreach ($available_layout_providers as $provider) {
+ $dir = $provider['dir'] . DIRECTORY_SEPARATOR . 'layout';
+ // If the directory structure exists, look for layouts.
+ if (file_exists($dir)) {
+ $this->iterateDirectories($dir, $provider);
+ }
+ }
+ return $this->derivatives;
+ }
+
+ /**
+ * Finds layout definitions by looking for layout metadata.
+ */
+ protected function iterateDirectories($dir, $provider) {
+ $directories = new DirectoryIterator($dir);
+ foreach ($directories as $fileinfo) {
+ if ($fileinfo->isDir() && !$fileinfo->isDot()) {
+ $this->iterateDirectories($fileinfo->getPathname(), $provider);
+ }
+ elseif ($fileinfo->isFile() && $fileinfo->getExtension() == 'yml') {
+ $directory = new FileStorage($fileinfo->getPath());
+ $this->derivatives[$provider['provider'] . '__' . $fileinfo->getBasename('.yml')] = $directory->read($fileinfo->getBasename('.yml'));
+ $this->derivatives[$provider['provider'] . '__' . $fileinfo->getBasename('.yml')]['template'] = $provider['provider'] . '--' . $fileinfo->getBasename('.yml');
+ $this->derivatives[$provider['provider'] . '__' . $fileinfo->getBasename('.yml')]['path'] = $fileinfo->getPath();
+ }
+ }
+ }
+}
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/LayoutInterface.php b/core/modules/layout/lib/Drupal/layout/Plugin/LayoutInterface.php
new file mode 100644
index 0000000..0863a67
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/LayoutInterface.php
@@ -0,0 +1,27 @@
+manager = $manager;
+ }
+
+ /**
+ * Implements MapperInterface::getInstance().
+ */
+ public function getInstance(array $options) {
+ if (empty($options['request']) || !$options['request'] instanceof Request) {
+ // Throw an exception.
+ }
+ // Find all modules that respond with a layout for the current request and
+ // sort them by weight and take the first one in the list.
+ if ($layouts = module_invoke_all('layout', $options['request'])) {
+ usort($layouts, array($this, 'sort'));
+ $layout = array_shift($layouts);
+ return $this->manager->createInstance($layout['layout'], $layout);
+ }
+ // If no modules responded for the current request, then fallback to the
+ // default that the block administration page represents.
+ else {
+ global $theme;
+ if ($theme != 'bartik') {
+ return;
+ }
+ $conf = array();
+ $blocks = array();
+ $block_configs = config_get_storage_names_with_prefix('plugin.core.block.' . $theme);
+ foreach ($block_configs as $config) {
+ $blocks[$config] = config($config)->get();
+ if (empty($blocks[$config]['config_id'])) {
+ $blocks[$config]['config_id'] = $config;
+ }
+ }
+ usort($blocks, array($this, 'sort'));
+ foreach ($blocks as $config) {
+ $conf['regions'][$config['region']][$config['config_id']] = array();
+ }
+ return $this->manager->createInstance('default_layout:bartik__bartik', $conf);
+ }
+ }
+
+ function sort($a, $b) {
+ // Sort by weight.
+ $weight = $a['weight'] - $b['weight'];
+ if ($weight) {
+ return $weight;
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/Type/LayoutManager.php b/core/modules/layout/lib/Drupal/layout/Plugin/Type/LayoutManager.php
new file mode 100644
index 0000000..181edfc
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/Type/LayoutManager.php
@@ -0,0 +1,26 @@
+ 'Drupal\layout\Plugin\layout\layout\DefaultLayout'
+ );
+
+ public function __construct() {
+ $this->discovery = new DerivativeDiscoveryDecorator(new AnnotatedClassDiscovery('layout', 'layout'));
+ $this->factory = new ReflectionFactory($this);
+ $this->mapper = new LayoutMapper($this);
+ }
+}
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/block/block/LayoutBlock.php b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/LayoutBlock.php
new file mode 100644
index 0000000..542f7e6
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/LayoutBlock.php
@@ -0,0 +1,31 @@
+createInstance('default_layout:layout__twocol', $this->configuration['layout']);
+ return array(
+ '#children' => $layout->renderLayout()
+ );
+ }
+}
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageActions.php b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageActions.php
new file mode 100644
index 0000000..e0e6345
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageActions.php
@@ -0,0 +1,30 @@
+ theme('breadcrumb', array('breadcrumb' => drupal_get_breadcrumb())),
+ );
+ }
+}
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageMessages.php b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageMessages.php
new file mode 100644
index 0000000..ec73515
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageMessages.php
@@ -0,0 +1,30 @@
+ theme('status_messages'),
+ );
+ }
+}
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PagePrimaryLinks.php b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PagePrimaryLinks.php
new file mode 100644
index 0000000..58f352d
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PagePrimaryLinks.php
@@ -0,0 +1,30 @@
+ theme('links', array('links' => menu_main_menu(), 'attributes' => array('class' => 'links primary-links'))),
+ );
+ }
+}
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageSecondaryLinks.php b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageSecondaryLinks.php
new file mode 100644
index 0000000..ab56df7
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageSecondaryLinks.php
@@ -0,0 +1,30 @@
+ theme('links', array('links' => menu_secondary_menu(), 'attributes' => array('class' => 'links secondary-links'))),
+ );
+ }
+}
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageSiteLogo.php b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageSiteLogo.php
new file mode 100644
index 0000000..13d4925
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageSiteLogo.php
@@ -0,0 +1,34 @@
+';
+ return array(
+ '#children' => l($image, '', array('html' => TRUE, 'attributes' => array('rel' => 'home', 'id' => 'logo', 'title' => t('Home')))),
+ );
+ }
+ }
+}
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageSiteName.php b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageSiteName.php
new file mode 100644
index 0000000..3697e4c
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageSiteName.php
@@ -0,0 +1,30 @@
+ filter_xss_admin(config('system.site')->get('name')),
+ );
+ }
+}
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageSiteSlogan.php b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageSiteSlogan.php
new file mode 100644
index 0000000..890d44a
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/block/block/PageSiteSlogan.php
@@ -0,0 +1,35 @@
+get('slogan');
+ if (!empty($slogan)) {
+ return array(
+ '#children' => filter_xss_admin($slogan),
+ );
+ }
+ }
+ }
+}
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/layout/layout/DefaultLayout.php b/core/modules/layout/lib/Drupal/layout/Plugin/layout/layout/DefaultLayout.php
new file mode 100644
index 0000000..1fce65e
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/layout/layout/DefaultLayout.php
@@ -0,0 +1,115 @@
+getDefinition($plugin_id);
+ foreach ($definition['regions'] as $region => $title) {
+ if (!isset($configuration['regions'][$region])) {
+ $configuration['regions'][$region] = array();
+ }
+ }
+ parent::__construct($configuration, $plugin_id, $discovery);
+ }
+
+ /**
+ * Overrides Drupal\layout\Plugin\LayoutInterface::getRegions().
+ */
+ public function getRegions() {
+ $definition = $this->getDefinition();
+ return $definition['regions'];
+ }
+
+ /**
+ * Add the CSS files associated with this layout to the page.
+ */
+ public function addCss() {
+ $definition = $this->getDefinition();
+ drupal_add_css($definition['path'] . '/' . $definition['css']);
+ }
+
+ /**
+ * Add the administrative CSS files associated with this layout to the page.
+ */
+ public function addAdminCss() {
+ $definition = $this->getDefinition();
+ $css = isset($definition['admin css']) ? $definition['admin css'] : $definition['css'];
+ drupal_add_css($definition['path'] . '/' . $css);
+ }
+
+ /**
+ * Add the JS files associated with this layout to the page.
+ */
+ public function addJs() {
+ $definition = $this->getDefinition();
+ if (isset($definition['js'])) {
+ drupal_add_js($definition['path'] . '/' . $definition['js']);
+ }
+ }
+
+ /**
+ * Overrides Drupal\layout\Plugin\LayoutInterface::renderLayout().
+ *
+ * @todo
+ * The $regions parameter is here only temporarily. It allows the caller
+ * to pass already rendered regions, while layout/block configuration code
+ * is still in progress.
+ */
+ public function renderLayout($admin = FALSE) {
+ $definition = $this->getDefinition();
+
+ // Render all regions not already rendered by the caller.
+ foreach ($this->getRegions() as $region => $title) {
+ if (!isset($regions[$region]) && isset($this->configuration['regions'][$region])) {
+ foreach ($this->configuration['regions'][$region] as $block_id => $configuration) {
+ $block = block_load($block_id, $configuration);
+ if ($block->access()) {
+ // Need to check the caching method on the block to determine exactly
+ // how we're going to get it. Should probably be abstracted out of
+ // this code so that the renderer worries about it instead.
+ $block->setConfig('region', $region);
+ $build = $block->build();
+ if ($build) {
+ $regions[$region][] = array(
+ '#block' => $block,
+ '#theme_wrappers' => array('block'),
+ $build,
+ );
+ }
+ }
+ }
+ $regions[$region] = drupal_render($regions[$region]);
+ }
+ }
+
+ if (!$admin) {
+ $this->addCss();
+ $this->addJs();
+ }
+ else {
+ $this->addAdminCss();
+ }
+
+ $template = $definition['path'] . '/' . $definition['template'] . '.tpl.php';
+ $output = theme_render_template($template, array('content' => $regions));
+
+ return $output;
+ }
+}
diff --git a/core/themes/bartik/layout/bartik/bartik--bartik.tpl.php b/core/themes/bartik/layout/bartik/bartik--bartik.tpl.php
new file mode 100644
index 0000000..87cc199
--- /dev/null
+++ b/core/themes/bartik/layout/bartik/bartik--bartik.tpl.php
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/themes/bartik/layout/bartik/bartik.yml b/core/themes/bartik/layout/bartik/bartik.yml
new file mode 100644
index 0000000..7ed50bb
--- /dev/null
+++ b/core/themes/bartik/layout/bartik/bartik.yml
@@ -0,0 +1,20 @@
+title: Bartik page
+category: Other
+icon: page.png
+css: page.css
+regions:
+ header: 'Header'
+ help: 'Help'
+ highlighted: 'Highlighted'
+ featured: 'Featured'
+ content: 'Content'
+ sidebar_first: 'Sidebar first'
+ sidebar_second: 'Sidebar second'
+ triptych_first: 'Triptych first'
+ triptych_middle: 'Triptych middle'
+ triptych_last: 'Triptych last'
+ footer_firstcolumn: 'Footer first column'
+ footer_secondcolumn: 'Footer second column'
+ footer_thirdcolumn: 'Footer third column'
+ footer_fourthcolumn: 'Footer fourth column'
+ footer: 'Footer'
diff --git a/core/themes/bartik/lib/Drupal/bartik/blocks/PrimaryLinks.php b/core/themes/bartik/lib/Drupal/bartik/blocks/PrimaryLinks.php
new file mode 100644
index 0000000..05f97a7
--- /dev/null
+++ b/core/themes/bartik/lib/Drupal/bartik/blocks/PrimaryLinks.php
@@ -0,0 +1,30 @@
+ '',
+ '#suffix' => '
',
+ '#children' => theme('links__system_main_menu', array(
+ 'links' => menu_main_menu(),
+ 'attributes' => array(
+ 'id' => 'main-menu-links',
+ 'class' => array('links', 'clearfix'),
+ ),
+ 'heading' => array(
+ 'text' => t('Main menu'),
+ 'level' => 'h2',
+ 'class' => array('element-invisible'),
+ ),
+ )),
+ );
+ }
+}
diff --git a/core/themes/bartik/lib/Drupal/bartik/blocks/SecondaryLinks.php b/core/themes/bartik/lib/Drupal/bartik/blocks/SecondaryLinks.php
new file mode 100644
index 0000000..1ada2f1
--- /dev/null
+++ b/core/themes/bartik/lib/Drupal/bartik/blocks/SecondaryLinks.php
@@ -0,0 +1,30 @@
+ '',
+ '#children' => theme('links__system_secondary_menu', array(
+ 'links' => menu_secondary_menu(),
+ 'attributes' => array(
+ 'id' => 'secondary-menu-links',
+ 'class' => array('links', 'inline', 'clearfix'),
+ ),
+ 'heading' => array(
+ 'text' => t('Secondary menu'),
+ 'level' => 'h2',
+ 'class' => array('element-invisible'),
+ ),
+ )),
+ );
+ }
+}
diff --git a/core/themes/bartik/template.php b/core/themes/bartik/template.php
index 5373c92..d4facdc 100644
--- a/core/themes/bartik/template.php
+++ b/core/themes/bartik/template.php
@@ -151,3 +151,12 @@ function bartik_field__taxonomy_term_reference($variables) {
return $output;
}
+
+/**
+ * Implements hook_block_alter().
+ */
+function bartik_block_alter(&$definitions) {
+ $definitions['page_primary_links']['class'] = 'Drupal\\bartik\\blocks\\PrimaryLinks';
+ $definitions['page_secondary_links']['class'] = 'Drupal\\bartik\\blocks\\SecondaryLinks';
+}
+