Skip to content
This repository was archived by the owner on May 3, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions modules/context_layout/context_layout.info.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: Context Layout
type: module
description: 'Block Page Reaction (with Layout plugin integration)'
core: 8.x
package: Context
dependencies:
- context
- layout_plugin
5 changes: 5 additions & 0 deletions modules/context_layout/context_layout.links.menu.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
context_layout.admin_settings:
title: 'Context Layout settings'
description: 'Configure context layout reactions.'
route_name: context_layout.admin_settings
parent: 'system.admin_config_development'
5 changes: 5 additions & 0 deletions modules/context_layout/context_layout.links.task.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
context_layout.admin_settings:
title: 'Settings'
route_name: context_layout.admin_settings
base_route: context_layout.admin_settings
weight: 0
53 changes: 53 additions & 0 deletions modules/context_layout/context_layout.routing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
context_layout.admin_settings:
path: '/admin/config/development/context_layout'
defaults:
_form: '\Drupal\context_layout\Form\SettingsForm'
_title: 'Context Layout'
requirements:
_permission: 'administer site configuration'

context.reaction.layouts.theme_select:
path: '/admin/structure/context/{context}/reaction/layouts/theme'
defaults:
_controller: '\Drupal\context_layout\Reaction\Layouts\Controller\ContextReactionLayoutsController::themeSelect'
requirements:
_entity_access: 'context.update'

context.reaction.layouts.layout_select:
path: '/admin/structure/context/{context}/reaction/layouts/layout'
defaults:
_controller: '\Drupal\context_layout\Reaction\Layouts\Controller\ContextReactionLayoutsController::layoutSelect'
requirements:
_permission: 'administer contexts'

context.reaction.layouts.library:
path: '/admin/structure/context/{context}/reaction/layouts/{reaction_id}/library'
defaults:
_title: 'Add block'
_controller: '\Drupal\context_layout\Reaction\Layouts\Controller\ContextReactionLayoutsController::blocksLibrary'
requirements:
_entity_access: 'context.update'

context.reaction.layouts.block_delete:
path: '/admin/structure/context/{context}/reaction/layouts/delete/{block_id}'
defaults:
_form: '\Drupal\context_layout\Reaction\Layouts\Form\LayoutBlockDeleteForm'
_title: 'Delete block'
requirements:
_entity_access: 'context.update'

context.reaction.layouts.block_add:
path: '/admin/structure/context/{context}/reaction/layouts/{reaction_id}/add/{block_id}'
defaults:
_form: '\Drupal\context_layout\Reaction\Layouts\Form\LayoutBlockAddForm'
_title: 'Add block'
requirements:
_entity_access: 'context.update'

context.reaction.layouts.block_edit:
path: '/admin/structure/context/{context}/reaction/layouts/{reaction_id}/edit/{block_id}'
defaults:
_form: '\Drupal\context_layout\Reaction\Layouts\Form\LayoutBlockEditForm'
_title: 'Edit block'
requirements:
_entity_access: 'context.update'
9 changes: 9 additions & 0 deletions modules/context_layout/context_layout.services.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
services:
context_layout.layout_page_display_variant_subscriber:
class: Drupal\context_layout\EventSubscriber\LayoutPageDisplayVariantSubscriber
arguments: ['@context.manager']
tags:
- { name: event_subscriber }
plugin.manager.context_layout:
class: Drupal\context_layout\Plugin\ContextLayout\ContextLayoutManager
arguments: ['@container.namespaces', '@cache.discovery', '@module_handler', '@theme_handler']
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

namespace Drupal\context_layout\EventSubscriber;

use Drupal\context\ContextManager;
use Drupal\context_layout\Plugin\ContextReaction\Layouts;
use Drupal\Core\Render\RenderEvents;
use Drupal\Core\Render\PageDisplayVariantSelectionEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* Selects the layout page display variant.
*
* @see \Drupal\block\Plugin\DisplayVariant\BlockPageVariant
*/
class LayoutPageDisplayVariantSubscriber implements EventSubscriberInterface {

/**
* Context Manager.
*
* @var \Drupal\context\ContextManager
*/
private $contextManager;

/**
* Constructs a LayoutPageDisplayVariantSubscriber object.
*
* @param \Drupal\context\ContextManager $contextManager
* Context manager service.
*/
public function __construct(ContextManager $contextManager) {
$this->contextManager = $contextManager;
}

/**
* Selects the context layout page display variant.
*
* @param \Drupal\Core\Render\PageDisplayVariantSelectionEvent $event
* The event to process.
*/
public function onSelectPageDisplayVariant(PageDisplayVariantSelectionEvent $event) {
// Exit if on admin route and context_layout.settings.admin_allow is true.
$admin = \Drupal::service('router.admin_context')->isAdminRoute();
$allow = \Drupal::config('context_layout.settings')
->get('admin_allow');
if ($admin && !$allow) {
return;
}
// Activate the context block page display variant if any of the reactions
// is a blocks reaction.
foreach ($this->contextManager->getActiveReactions() as $reaction) {
if ($reaction instanceof Layouts) {
$event->setPluginId('context_layout_page');
break;
}
}
}

/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[RenderEvents::SELECT_PAGE_DISPLAY_VARIANT][] = array('onSelectPageDisplayVariant');
return $events;
}

}
100 changes: 100 additions & 0 deletions modules/context_layout/src/Form/SettingsForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

namespace Drupal\context_layout\Form;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\layout_plugin\Plugin\Layout\LayoutPluginManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* Manage module configuration form.
*/
class SettingsForm extends ConfigFormBase {

/**
* Constructs SettingsForm object.
*
* @param \Drupal\layout_plugin\Plugin\Layout\LayoutPluginManagerInterface $contextLayoutManager
* Context layout manager service.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* Config factory service.
*/
public function __construct(LayoutPluginManagerInterface $contextLayoutManager, ConfigFactoryInterface $config_factory) {
$this->contextLayoutManager = $contextLayoutManager;
parent::__construct($config_factory);
}

/**
* {@inheritdoc}
*/
public function getFormId() {
return 'context_layout_settings';
}

/**
* Inject dependencies to constructor.
*
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
* The current service container.
*
* @return static
* Dependencies for injection.
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('plugin.manager.context_layout'),
$container->get('config.factory')
);
}

/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
// Module settings.
$config = $this->config('context_layout.settings');

// Default layout for layout reactions.
$form['default_layout'] = [
'#title' => t('Default Layout'),
'#description' => t('Select a default layout for layout reactions'),
'#type' => 'select',
'#options' => [0 => '---'] + $this->contextLayoutManager->getLayoutOptions(
['group_by_category' => TRUE]
),
'#default_value' => $config->get('default_layout'),
];

// Exclude layout displays on admin routes.
$form['admin_allow'] = [
'#title' => t('Allow Admin Routes'),
'#description' => t('Check to allow Context Layout reactions on admin routes, eg: admin/structure.'),
'#type' => 'checkbox',
'#default_value' => $config->get('admin_allow'),
];

return parent::buildForm($form, $form_state);
}

/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$values = $form_state->getValues();
$this->config('context_layout.settings')
->set('default_layout', $values['default_layout'])
->set('admin_allow', $values['admin_allow'])
->save();
parent::submitForm($form, $form_state);
}

/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return ['context_layout.settings'];
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php

namespace Drupal\context_layout\Plugin\ContextLayout;

use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Extension\ThemeHandlerInterface;
use Drupal\layout_plugin\Plugin\Layout\LayoutPluginManager;

/**
* Provides an interface for the discovery and instantiation of context layouts.
*/
class ContextLayoutManager extends LayoutPluginManager {

/**
* {@inheritdoc}
*/
public function getLayoutOptions(array $params = []) {
$type = 'full';
$group_by_category = !empty($params['group_by_category']);
$plugins = $this->getDefinitions();
$options = array();
// Sort the plugins first by category, then by label.
foreach ($plugins as $id => $plugin) {
// Only layouts of type 'full' are allowed.
if ($type != $plugin['type']) {
continue;
}
if ($group_by_category) {
$category = isset($plugin['category']) ? (string) $plugin['category'] : 'default';
if (!isset($options[$category])) {
$options[$category] = array();
}
$options[$category][$id] = $plugin['label'];
}
else {
$options[$id] = $plugin['label'];
}
}
return $options;
}

/**
* Returns a Drupal\layout_plugin\Layout instance.
*
* @param string $layout
* Layout ID (machine name).
* @param bool|false $fallback
* Whether to return a fallback layout if default doesn't exist.
*
* @return object
* Drupal\layout_plugin\Layout instance.
*/
public function loadLayout($layout, $fallback = FALSE) {
// We want to return the correct layout if 'default' is passed.
if ('default' == $layout) {
$layout = $this->createInstance($this->getDefaultLayout($fallback));
}
else {
$layout = $this->createInstance($layout);
}
return $layout;
}

/**
* Returns default Drupal\layout_plugin\Layout instance.
*
* @param bool|false $fallback
* Whether to return a fallback layout if default doesn't exist.
*
* @return string
* Layout ID (machine name).
*/
public function getDefaultLayout($fallback = FALSE) {
$layout = \Drupal::config('context_layout.settings')
->get('default_layout');
if ($fallback && !$layout) {
// Get the first available layout.
$layout = array_keys(
$this->getLayoutOptions()
)[0];
}
return $layout;
}

/**
* Return available layout regions.
*
* @param array $regions
* Region ID's.
* @param string $layout_id
* Layout ID (machine name).
*
* @return array
* Available layout region ID's.
*/
public function filterLayoutRegions($regions, $layout_id) {
$layout = \Drupal::service('plugin.manager.context_layout')
->loadLayout($layout_id);
$layout_regions = array_keys($layout->getRegionDefinitions());
foreach ($regions as $region_id => $region) {
if (!in_array($region_id, $layout_regions)) {
unset($regions[$region_id]);
}
}
return $regions;
}

}
Loading