footer elements are almost displayed
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context;
|
||||
|
||||
use Drupal\Core\Condition\ConditionInterface;
|
||||
use Drupal\Core\Condition\ConditionPluginCollection;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
use Drupal\context\Plugin\ContextReactionPluginCollection;
|
||||
use Drupal\Core\Entity\EntityWithPluginCollectionInterface;
|
||||
|
||||
interface ContextInterface extends ConfigEntityInterface, EntityWithPluginCollectionInterface {
|
||||
|
||||
/**
|
||||
* The default value for a context that is not assigned to a group.
|
||||
*/
|
||||
const CONTEXT_GROUP_NONE = NULL;
|
||||
|
||||
/**
|
||||
* Get the ID of the context.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function id();
|
||||
|
||||
/**
|
||||
* Get the machine name of the context.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Set the machine name of the context.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setName($name);
|
||||
|
||||
/**
|
||||
* Get the context label.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLabel();
|
||||
|
||||
/**
|
||||
* Set the context label.
|
||||
*
|
||||
* @param string $label
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setLabel($label);
|
||||
|
||||
/**
|
||||
* Get the context description.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription();
|
||||
|
||||
/**
|
||||
* Set the context description.
|
||||
*
|
||||
* @param string $description
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDescription($description);
|
||||
|
||||
/**
|
||||
* Get the group this context belongs to.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getGroup();
|
||||
|
||||
/**
|
||||
* Set the group this context should belong to.
|
||||
*
|
||||
* @param null|string $group
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setGroup($group);
|
||||
|
||||
/**
|
||||
* Get the weight for this context.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getWeight();
|
||||
|
||||
/**
|
||||
* Set the weight for this context.
|
||||
*
|
||||
* @param int $weight
|
||||
* The weight to set for this context.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setWeight($weight);
|
||||
|
||||
/**
|
||||
* If the context requires all conditions to validate.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function requiresAllConditions();
|
||||
|
||||
/**
|
||||
* Set if all conditions should be required for this context to validate.
|
||||
*
|
||||
* @param bool $require
|
||||
* If a condition is required or not.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRequireAllConditions($require);
|
||||
|
||||
/**
|
||||
* Get a list of all conditions.
|
||||
*
|
||||
* @return ConditionInterface[]|ConditionPluginCollection
|
||||
*/
|
||||
public function getConditions();
|
||||
|
||||
/**
|
||||
* Get a condition with the specified ID.
|
||||
*
|
||||
* @param string $condition_id
|
||||
* The condition to get.
|
||||
*
|
||||
* @return \Drupal\Core\Condition\ConditionInterface
|
||||
*/
|
||||
public function getCondition($condition_id);
|
||||
|
||||
/**
|
||||
* Set the conditions.
|
||||
*
|
||||
* @param array $configuration
|
||||
* The configuration for the condition plugin.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function addCondition(array $configuration);
|
||||
|
||||
/**
|
||||
* Remove the specified condition.
|
||||
*
|
||||
* @param string $condition_id
|
||||
* The id of the condition to remove.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeCondition($condition_id);
|
||||
|
||||
/**
|
||||
* Check to see if the context has the specified condition.
|
||||
*
|
||||
* @param string $condition_id
|
||||
* The ID of the condition to check for.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasCondition($condition_id);
|
||||
|
||||
/**
|
||||
* Get a list of all the reactions.
|
||||
*
|
||||
* @return ContextReactionInterface[]|ContextReactionPluginCollection
|
||||
*/
|
||||
public function getReactions();
|
||||
|
||||
/**
|
||||
* Get a reaction with the specified ID.
|
||||
*
|
||||
* @param string $reaction_id
|
||||
* The ID of the reaction to get.
|
||||
*
|
||||
* @return ContextReactionInterface
|
||||
*/
|
||||
public function getReaction($reaction_id);
|
||||
|
||||
/**
|
||||
* Add a context reaction.
|
||||
*
|
||||
* @param array $configuration
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function addReaction(array $configuration);
|
||||
|
||||
/**
|
||||
* Remove the specified reaction.
|
||||
*
|
||||
* @param string $reaction_id
|
||||
* The id of the reaction to remove.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function removeReaction($reaction_id);
|
||||
|
||||
/**
|
||||
* Check to see if the context has the specified reaction.
|
||||
*
|
||||
* @param string $reaction_id
|
||||
* The ID of the reaction to check for.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasReaction($reaction_id);
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context;
|
||||
|
||||
use Drupal\context\Entity\Context;
|
||||
use Drupal\context\Plugin\ContextReaction\Blocks;
|
||||
use Drupal\Core\Entity\Query\QueryFactory;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityFormBuilderInterface;
|
||||
use Drupal\Core\Plugin\ContextAwarePluginInterface;
|
||||
use Drupal\Core\Condition\ConditionPluginCollection;
|
||||
use Drupal\Component\Plugin\Exception\ContextException;
|
||||
use Drupal\Core\Condition\ConditionAccessResolverTrait;
|
||||
use Drupal\Core\Plugin\Context\ContextHandlerInterface;
|
||||
use Drupal\Core\Plugin\Context\ContextRepositoryInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\Theme\ThemeManagerInterface;
|
||||
|
||||
/**
|
||||
* This is the manager service for the context module and should not be
|
||||
* confused with the built in contexts in Drupal.
|
||||
*/
|
||||
class ContextManager {
|
||||
|
||||
use ConditionAccessResolverTrait;
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Entity\Query\QueryFactory
|
||||
*/
|
||||
protected $entityQuery;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Plugin\Context\ContextRepositoryInterface
|
||||
*/
|
||||
protected $contextRepository;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Plugin\Context\ContextHandlerInterface
|
||||
*/
|
||||
protected $contextHandler;
|
||||
|
||||
/**
|
||||
* If the context conditions has been evaluated then this is set to TRUE
|
||||
* otherwise FALSE.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $contextConditionsEvaluated = FALSE;
|
||||
|
||||
/**
|
||||
* An array of contexts that have been evaluated and are active.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $activeContexts = [];
|
||||
/**
|
||||
* @var \Drupal\Core\Entity\EntityFormBuilderInterface
|
||||
*/
|
||||
private $entityFormBuilder;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Theme\ThemeManagerInterface;
|
||||
*/
|
||||
protected $themeManager;
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @param QueryFactory $entityQuery
|
||||
* The Drupal entity query service.
|
||||
*
|
||||
* @param EntityManagerInterface $entityManager
|
||||
* The Drupal entity manager service.
|
||||
*
|
||||
* @param ContextRepositoryInterface $contextRepository
|
||||
* The drupal context repository service.
|
||||
*
|
||||
* @param ContextHandlerInterface $contextHandler
|
||||
* The Drupal context handler service.
|
||||
*
|
||||
* @param ThemeManagerInterface $themeManager
|
||||
* The Drupal theme manager service.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityFormBuilderInterface $entityFormBuilder
|
||||
*/
|
||||
function __construct(
|
||||
QueryFactory $entityQuery,
|
||||
EntityManagerInterface $entityManager,
|
||||
ContextRepositoryInterface $contextRepository,
|
||||
ContextHandlerInterface $contextHandler,
|
||||
EntityFormBuilderInterface $entityFormBuilder,
|
||||
ThemeManagerInterface $themeManager
|
||||
)
|
||||
{
|
||||
$this->entityQuery = $entityQuery;
|
||||
$this->entityManager = $entityManager;
|
||||
$this->contextRepository = $contextRepository;
|
||||
$this->contextHandler = $contextHandler;
|
||||
$this->entityFormBuilder = $entityFormBuilder;
|
||||
$this->themeManager = $themeManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all contexts.
|
||||
*
|
||||
* @return Context[]
|
||||
*/
|
||||
public function getContexts() {
|
||||
$contextIds = $this->entityQuery
|
||||
->get('context')
|
||||
->execute();
|
||||
|
||||
$contexts = $this->entityManager
|
||||
->getStorage('context')
|
||||
->loadMultiple($contextIds);
|
||||
|
||||
// Sort the contexts by their weight.
|
||||
uasort($contexts, [$this, 'sortContextsByWeight']);
|
||||
|
||||
return $contexts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all contexts sorted by their group and sorted by their weight inside
|
||||
* of each group.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getContextsByGroup() {
|
||||
$contexts = $this->getContexts();
|
||||
|
||||
$groups = [];
|
||||
|
||||
// Add each context to their respective groups.
|
||||
foreach ($contexts as $context_id => $context) {
|
||||
$group = $context->getGroup();
|
||||
|
||||
if ($group === Context::CONTEXT_GROUP_NONE) {
|
||||
$group = 'not_grouped';
|
||||
}
|
||||
|
||||
$groups[$group][$context_id] = $context;
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to validate that the context name does not already exist.
|
||||
*
|
||||
* @param string $name
|
||||
* The machine name of the context to validate.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function contextExists($name) {
|
||||
$entity = $this->entityQuery->get('context')
|
||||
->condition('name', $name)
|
||||
->execute();
|
||||
|
||||
return (bool) $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if context conditions has been evaluated.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function conditionsHasBeenEvaluated() {
|
||||
return $this->contextConditionsEvaluated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the evaluated and active contexts.
|
||||
*
|
||||
* @return \Drupal\context\ContextInterface[]
|
||||
*/
|
||||
public function getActiveContexts() {
|
||||
if ($this->conditionsHasBeenEvaluated()) {
|
||||
return $this->activeContexts;
|
||||
}
|
||||
|
||||
$this->evaluateContexts();
|
||||
|
||||
return $this->activeContexts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate all context conditions.
|
||||
*/
|
||||
public function evaluateContexts() {
|
||||
|
||||
/** @var \Drupal\context\ContextInterface $context */
|
||||
foreach ($this->getContexts() as $context) {
|
||||
if ($this->evaluateContextConditions($context) && !$context->disabled()) {
|
||||
$this->activeContexts[] = $context;
|
||||
}
|
||||
}
|
||||
|
||||
$this->contextConditionsEvaluated = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all active reactions or reactions of a certain type.
|
||||
*
|
||||
* @param string $reactionType
|
||||
* Either the reaction class name or the id of the reaction type to get.
|
||||
*
|
||||
* @return ContextReactionInterface[]
|
||||
*/
|
||||
public function getActiveReactions($reactionType = NULL) {
|
||||
$reactions = [];
|
||||
|
||||
foreach ($this->getActiveContexts() as $context) {
|
||||
|
||||
// If no reaction type has been specified then add all reactions and
|
||||
// continue to the next context.
|
||||
if (is_null($reactionType)) {
|
||||
foreach ($context->getReactions() as $reaction) {
|
||||
// Only return block reaction if there is a block applied to the current theme.
|
||||
if ($reaction instanceof Blocks) {
|
||||
$blocks = $reaction->getBlocks();
|
||||
$current_theme = $this->getCurrentTheme();
|
||||
foreach ($blocks as $block) {
|
||||
if ($block->getConfiguration()['theme'] == $current_theme) {
|
||||
$reactions[] = $reaction;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$reactions[] = $reaction;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$contextReactions = $context->getReactions();
|
||||
|
||||
// Filter the reactions based on the reaction type.
|
||||
foreach ($contextReactions as $reaction) {
|
||||
|
||||
if (class_exists($reactionType) && $reaction instanceof $reactionType) {
|
||||
$reactions[] = $reaction;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($reaction->getPluginId() === $reactionType) {
|
||||
$reactions[] = $reaction;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $reactions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a contexts conditions.
|
||||
*
|
||||
* @param ContextInterface $context
|
||||
* The context to evaluate conditions for.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function evaluateContextConditions(ContextInterface $context) {
|
||||
$conditions = $context->getConditions();
|
||||
|
||||
// Apply context to any context aware conditions.
|
||||
$this->applyContexts($conditions);
|
||||
|
||||
// Set the logic to use when validating the conditions.
|
||||
$logic = $context->requiresAllConditions()
|
||||
? 'and'
|
||||
: 'or';
|
||||
|
||||
// Of there are no conditions then the context will be
|
||||
// applied as a site wide context.
|
||||
if (!count($conditions)) {
|
||||
$logic = 'and';
|
||||
}
|
||||
|
||||
return $this->resolveConditions($conditions, $logic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply context to all the context aware conditions in the collection.
|
||||
*
|
||||
* @param ConditionPluginCollection $conditions
|
||||
* A collection of conditions to apply context to.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function applyContexts(ConditionPluginCollection &$conditions) {
|
||||
|
||||
foreach ($conditions as $condition) {
|
||||
if ($condition instanceof ContextAwarePluginInterface) {
|
||||
try {
|
||||
$contexts = $this->contextRepository->getRuntimeContexts(array_values($condition->getContextMapping()));
|
||||
$this->contextHandler->applyContextMapping($condition, $contexts);
|
||||
}
|
||||
catch (ContextException $e) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a rendered form for the context.
|
||||
* @param \Drupal\context\ContextInterface $context
|
||||
* @param string $formType
|
||||
* @param array $form_state_additions
|
||||
* @return array
|
||||
*/
|
||||
public function getForm(ContextInterface $context, $formType = 'edit', array $form_state_additions = array()) {
|
||||
return $this->entityFormBuilder->getForm($context, $formType, $form_state_additions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts an array of context entities by their weight.
|
||||
*
|
||||
* Callback for uasort().
|
||||
*
|
||||
* @param ContextInterface $a
|
||||
* First item for comparison.
|
||||
*
|
||||
* @param ContextInterface $b
|
||||
* Second item for comparison.
|
||||
*
|
||||
* @return int
|
||||
* The comparison result for uasort().
|
||||
*/
|
||||
public function sortContextsByWeight(ContextInterface $a, ContextInterface $b) {
|
||||
if ($a->getWeight() == $b->getWeight()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ($a->getWeight() < $b->getWeight()) ? -1 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current active theme.
|
||||
*
|
||||
* @return string
|
||||
* Current active theme name.
|
||||
*/
|
||||
private function getCurrentTheme() {
|
||||
return $this->themeManager->getActiveTheme()->getName();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context;
|
||||
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Lock\LockBackendInterface;
|
||||
use Drupal\Core\Menu\MenuActiveTrail;
|
||||
use Drupal\Core\Menu\MenuLinkManagerInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\menu_link_content\Entity\MenuLinkContent;
|
||||
|
||||
/**
|
||||
* Extend the MenuActiveTrail class.
|
||||
*/
|
||||
class ContextMenuActiveTrail extends MenuActiveTrail {
|
||||
|
||||
/**
|
||||
* @var \Drupal\context\ContextManager.
|
||||
*/
|
||||
protected $contextManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(MenuLinkManagerInterface $menu_link_manager, RouteMatchInterface $route_match, CacheBackendInterface $cache, LockBackendInterface $lock, ContextManager $context_manager) {
|
||||
parent::__construct($menu_link_manager, $route_match, $cache, $lock);
|
||||
$this->contextManager = $context_manager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getActiveLink($menu_name = NULL) {
|
||||
$found = parent::getActiveLink($menu_name);
|
||||
|
||||
// Get active reaction of Menu type.
|
||||
foreach($this->contextManager->getActiveReactions('menu') as $reaction) {
|
||||
$menu_items = $reaction->execute();
|
||||
foreach ($menu_items as $menu_link_content) {
|
||||
$menu = strtok($menu_link_content, ':');
|
||||
if ($menu == $menu_name) {
|
||||
$plugin_id = substr($menu_link_content, strlen($menu) + 1);
|
||||
return $this->menuLinkManager->createInstance($plugin_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $found;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context;
|
||||
|
||||
use Drupal\Core\Executable\ExecutableInterface;
|
||||
use Drupal\Component\Plugin\PluginInspectionInterface;
|
||||
use Drupal\Component\Plugin\ConfigurablePluginInterface;
|
||||
use Drupal\Core\Plugin\PluginFormInterface;
|
||||
|
||||
interface ContextReactionInterface extends ConfigurablePluginInterface, PluginFormInterface, PluginInspectionInterface, ExecutableInterface {
|
||||
|
||||
/**
|
||||
* Get the unique ID of this context reaction.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getId();
|
||||
|
||||
/**
|
||||
* Provides a human readable summary of the condition's configuration.
|
||||
*
|
||||
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
*/
|
||||
public function summary();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context;
|
||||
|
||||
use Traversable;
|
||||
use Drupal\Core\Plugin\DefaultPluginManager;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
|
||||
class ContextReactionManager extends DefaultPluginManager {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
|
||||
parent::__construct('Plugin/ContextReaction', $namespaces, $module_handler, 'Drupal\context\ContextReactionInterface', 'Drupal\context\Reaction\Annotation\ContextReaction');
|
||||
|
||||
$this->alterInfo('context_condition_info');
|
||||
$this->setCacheBackend($cache_backend, 'context_condition_plugins');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context;
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\PluginBase;
|
||||
|
||||
abstract class ContextReactionPluginBase extends PluginBase implements ContextReactionInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->setConfiguration($configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getId() {
|
||||
if (isset($this->getConfiguration()['id'])) {
|
||||
return $this->getConfiguration()['id'];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfiguration() {
|
||||
return [
|
||||
'id' => $this->getPluginId(),
|
||||
] + $this->configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setConfiguration(array $configuration) {
|
||||
$this->configuration = $configuration + $this->defaultConfiguration();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form validation handler is optional.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
return [
|
||||
'saved' => FALSE,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function calculateDependencies() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\DependencyInjection\ServiceProviderBase;
|
||||
|
||||
/**
|
||||
* Alter the service container to use a custom class.
|
||||
*/
|
||||
class ContextServiceProvider extends ServiceProviderBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alter(ContainerBuilder $container) {
|
||||
// Override the menu active trail with a new class.
|
||||
$definition = $container->getDefinition('menu.active_trail');
|
||||
$definition->setClass('Drupal\context\ContextMenuActiveTrail');
|
||||
$definition->addArgument($container->getDefinition('context.manager'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context\Entity;
|
||||
|
||||
use Drupal;
|
||||
use InvalidArgumentException;
|
||||
use Drupal\context\ContextInterface;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityBase;
|
||||
use Drupal\Core\Condition\ConditionPluginCollection;
|
||||
use Drupal\context\Plugin\ContextReactionPluginCollection;
|
||||
|
||||
/**
|
||||
* Defines the Context entity.
|
||||
*
|
||||
* @ConfigEntityType(
|
||||
* id = "context",
|
||||
* label = @Translation("Context"),
|
||||
* handlers = {
|
||||
* "access" = "Drupal\context\Entity\ContextAccess",
|
||||
* "list_builder" = "Drupal\context_ui\ContextListBuilder",
|
||||
* "form" = {
|
||||
* "add" = "Drupal\context_ui\Form\ContextAddForm",
|
||||
* "edit" = "Drupal\context_ui\Form\ContextEditForm",
|
||||
* "delete" = "Drupal\context_ui\Form\ContextDeleteForm",
|
||||
* "disable" = "Drupal\context_ui\Form\ContextDisableForm",
|
||||
* }
|
||||
* },
|
||||
* links = {
|
||||
* "edit-form" = "/admin/structure/context/{context}",
|
||||
* "delete-form" = "/admin/structure/context/{context}/delete",
|
||||
* "disable-form" = "/admin/structure/context/{context}/disable",
|
||||
* "collection" = "/admin/structure/context",
|
||||
* },
|
||||
* admin_permission = "administer contexts",
|
||||
* entity_keys = {
|
||||
* "id" = "name",
|
||||
* "label" = "label",
|
||||
* },
|
||||
* config_export = {
|
||||
* "name",
|
||||
* "label",
|
||||
* "group",
|
||||
* "description",
|
||||
* "requireAllConditions",
|
||||
* "disabled",
|
||||
* "conditions",
|
||||
* "reactions",
|
||||
* "weight",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class Context extends ConfigEntityBase implements ContextInterface {
|
||||
|
||||
/**
|
||||
* The machine name of the context.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* The label of the context.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $label;
|
||||
|
||||
/**
|
||||
* A description for this context.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '';
|
||||
|
||||
/**
|
||||
* The group this context belongs to.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $group = self::CONTEXT_GROUP_NONE;
|
||||
|
||||
/**
|
||||
* If all conditions must validate for this context.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $requireAllConditions = FALSE;
|
||||
|
||||
/**
|
||||
* The context conditions as a collection.
|
||||
*
|
||||
* @var ConditionPluginCollection
|
||||
*/
|
||||
protected $conditionsCollection;
|
||||
|
||||
/**
|
||||
* The context reactions as a collection.
|
||||
*
|
||||
* @var ContextReactionPluginCollection
|
||||
*/
|
||||
protected $reactionsCollection;
|
||||
|
||||
/**
|
||||
* A list of conditions this context should react to.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $conditions = [];
|
||||
|
||||
/**
|
||||
* A list of reactions that should be taken when conditions match.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $reactions = [];
|
||||
|
||||
/**
|
||||
* If the context is disabled or not.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $disabled = FALSE;
|
||||
|
||||
/**
|
||||
* The weight for this context.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $weight = 0;
|
||||
|
||||
/**
|
||||
* Returns the ID of the context. The ID is the unique machine name of the
|
||||
* context.
|
||||
*/
|
||||
public function id() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setName($name) {
|
||||
|
||||
if (!is_string($name)) {
|
||||
throw new InvalidArgumentException('The context name must be a string.');
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLabel() {
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setLabel($label) {
|
||||
|
||||
if (!is_string($label)) {
|
||||
throw new InvalidArgumentException('The context label must be a string.');
|
||||
}
|
||||
|
||||
$this->label = $label;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDescription() {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDescription($description) {
|
||||
|
||||
if (!is_string($description)) {
|
||||
throw new InvalidArgumentException('The context description must be a string.');
|
||||
}
|
||||
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getGroup() {
|
||||
return $this->group;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setGroup($group) {
|
||||
$this->group = (is_string($group) && !empty($group)) ? $group : self::CONTEXT_GROUP_NONE;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getWeight() {
|
||||
return $this->weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setWeight($weight) {
|
||||
$this->weight = (int) $weight;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function requiresAllConditions() {
|
||||
return $this->requireAllConditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRequireAllConditions($require) {
|
||||
$this->requireAllConditions = (bool) $require;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConditions() {
|
||||
if (!$this->conditionsCollection) {
|
||||
$conditionManager = Drupal::service('plugin.manager.condition');
|
||||
$this->conditionsCollection = new ConditionPluginCollection($conditionManager, $this->conditions);
|
||||
}
|
||||
|
||||
return $this->conditionsCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCondition($condition_id) {
|
||||
return $this->getConditions()->get($condition_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addCondition(array $configuration) {
|
||||
// Add an UUID to the condition to make sure the configuration is saved
|
||||
// since the configuration export from the conditions collection wont
|
||||
// export configuration that has not been "configured".
|
||||
$configuration['uuid'] = $this->uuidGenerator()->generate();
|
||||
|
||||
$this->getConditions()->addInstanceId($configuration['id'], $configuration);
|
||||
|
||||
return $configuration['id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function removeCondition($condition_id) {
|
||||
$this->getConditions()->removeInstanceId($condition_id);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasCondition($condition_id) {
|
||||
return $this->getConditions()->has($condition_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getReactions() {
|
||||
if (!$this->reactionsCollection) {
|
||||
$reactionManager = Drupal::service('plugin.manager.context_reaction');
|
||||
$this->reactionsCollection = new ContextReactionPluginCollection($reactionManager, $this->reactions);
|
||||
}
|
||||
|
||||
return $this->reactionsCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getReaction($reaction_id) {
|
||||
return $this->getReactions()->get($reaction_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addReaction(array $configuration) {
|
||||
// Add an UUID to the condition to make sure the configuration is saved
|
||||
// since the configuration export from the conditions collection wont
|
||||
// export configuration that has not been "configured".
|
||||
$configuration['uuid'] = $this->uuidGenerator()->generate();
|
||||
|
||||
$this->getReactions()->addInstanceId($configuration['id'], $configuration);
|
||||
|
||||
return $configuration['id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function removeReaction($reaction_id) {
|
||||
$this->getReactions()->removeInstanceId($reaction_id);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasReaction($reaction_id) {
|
||||
return $this->getReactions()->has($reaction_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the plugin collections used by this entity.
|
||||
*
|
||||
* @return \Drupal\Component\Plugin\LazyPluginCollection[]
|
||||
* An array of plugin collections, keyed by the property name they use to
|
||||
* store their configuration.
|
||||
*/
|
||||
public function getPluginCollections() {
|
||||
return [
|
||||
'reactions' => $this->getReactions(),
|
||||
'conditions' => $this->getConditions(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable context.
|
||||
*/
|
||||
public function disable() {
|
||||
$this->disabled = !$this->disabled();
|
||||
$this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function disabled() {
|
||||
return $this->disabled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\context\Entity\ContextAccess.
|
||||
*/
|
||||
|
||||
namespace Drupal\context\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Entity\EntityHandlerInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Defines the access control handler for the page entity type.
|
||||
*/
|
||||
class ContextAccess extends EntityAccessControlHandler implements EntityHandlerInterface {
|
||||
|
||||
/**
|
||||
* Constructs an access control handler instance.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type definition.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type) {
|
||||
parent::__construct($entity_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
|
||||
return new static($entity_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
return parent::checkAccess($entity, $operation, $account);
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\context\EventSubscriber\BlockPageDisplayVariantSubscriber.
|
||||
*/
|
||||
|
||||
namespace Drupal\context\EventSubscriber;
|
||||
|
||||
use Drupal\context\ContextManager;
|
||||
use Drupal\Core\Render\RenderEvents;
|
||||
use Drupal\context\Plugin\ContextReaction\Blocks;
|
||||
use Drupal\Core\Render\PageDisplayVariantSelectionEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Selects the block page display variant.
|
||||
*
|
||||
* @see \Drupal\block\Plugin\DisplayVariant\BlockPageVariant
|
||||
*/
|
||||
class BlockPageDisplayVariantSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* @var \Drupal\context\ContextManager
|
||||
*/
|
||||
private $contextManager;
|
||||
|
||||
/**
|
||||
* @param \Drupal\context\ContextManager $contextManager
|
||||
*/
|
||||
function __construct(ContextManager $contextManager) {
|
||||
$this->contextManager = $contextManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the context block page display variant.
|
||||
*
|
||||
* @param \Drupal\Core\Render\PageDisplayVariantSelectionEvent $event
|
||||
* The event to process.
|
||||
*/
|
||||
public function onSelectPageDisplayVariant(PageDisplayVariantSelectionEvent $event) {
|
||||
// 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 Blocks) {
|
||||
$event->setPluginId('context_block_page');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
static function getSubscribedEvents() {
|
||||
$events[RenderEvents::SELECT_PAGE_DISPLAY_VARIANT][] = array('onSelectPageDisplayVariant');
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\context\Form\AjaxFormTrait.
|
||||
*/
|
||||
|
||||
namespace Drupal\context\Form;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
|
||||
/**
|
||||
* Provides helper methods for using an AJAX modal. This is a copy of the
|
||||
* ctools AjaxFormTrait.
|
||||
*/
|
||||
trait AjaxFormTrait {
|
||||
|
||||
/**
|
||||
* Gets attributes for use with an AJAX modal.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAjaxAttributes() {
|
||||
return [
|
||||
'class' => ['use-ajax'],
|
||||
'data-dialog-type' => 'modal',
|
||||
'data-dialog-options' => Json::encode([
|
||||
'width' => 1000,
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets attributes for use with an add button AJAX modal.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAjaxButtonAttributes() {
|
||||
return NestedArray::mergeDeep(AjaxFormTrait::getAjaxAttributes(), [
|
||||
'class' => [
|
||||
'button',
|
||||
'button--small',
|
||||
'button-action',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
namespace Drupal\context\Plugin\Condition;
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\system\Plugin\Condition\RequestPath;
|
||||
|
||||
/**
|
||||
* Provides a 'Request path exclusion' condition.
|
||||
*
|
||||
* @Condition(
|
||||
* id = "request_path_exclusion",
|
||||
* label = @Translation("Request path exclusion"),
|
||||
* context = {
|
||||
* "request_path_exclusion" = @ContextDefinition("request_path_exclusion", label = @Translation("Request path exclusion"))
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class RequestPathExclusion extends RequestPath implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$form = parent::buildConfigurationForm($form, $form_state);
|
||||
unset($form['negate']);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function evaluate() {
|
||||
return !parent::evaluate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,681 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context\Plugin\ContextReaction;
|
||||
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Core\Form\FormState;
|
||||
use Drupal\Core\Render\Element;
|
||||
use Drupal\context\ContextInterface;
|
||||
use Drupal\context\Form\AjaxFormTrait;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Component\Uuid\UuidInterface;
|
||||
use Drupal\Core\Block\BlockPluginInterface;
|
||||
use Drupal\Core\Theme\ThemeManagerInterface;
|
||||
use Drupal\context\ContextReactionPluginBase;
|
||||
use Drupal\Core\Block\TitleBlockPluginInterface;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Drupal\context\Reaction\Blocks\BlockCollection;
|
||||
use Drupal\Core\Plugin\ContextAwarePluginInterface;
|
||||
use Drupal\Core\Block\MainContentBlockPluginInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Plugin\Context\ContextHandlerInterface;
|
||||
use Drupal\Core\Plugin\Context\ContextRepositoryInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a content reaction that will let you place blocks in the current
|
||||
* themes regions.
|
||||
*
|
||||
* @ContextReaction(
|
||||
* id = "blocks",
|
||||
* label = @Translation("Blocks")
|
||||
* )
|
||||
*/
|
||||
class Blocks extends ContextReactionPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
use AjaxFormTrait;
|
||||
|
||||
/**
|
||||
* An array of blocks to be displayed with this reaction.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $blocks = [];
|
||||
|
||||
/**
|
||||
* Contains a temporary collection of blocks.
|
||||
*
|
||||
* @var BlockCollection
|
||||
*/
|
||||
protected $blocksCollection;
|
||||
|
||||
/**
|
||||
* The Drupal UUID service.
|
||||
*
|
||||
* @var \Drupal\Component\Uuid\UuidInterface
|
||||
*/
|
||||
protected $uuid;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Theme\ThemeManagerInterface
|
||||
*/
|
||||
protected $themeManager;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* @var ContextRepositoryInterface
|
||||
*/
|
||||
protected $contextRepository;
|
||||
|
||||
/**
|
||||
* @var ContextHandlerInterface
|
||||
*/
|
||||
protected $contextHandler;
|
||||
|
||||
/**
|
||||
* @var AccountInterface
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function __construct(
|
||||
array $configuration,
|
||||
$pluginId,
|
||||
$pluginDefinition,
|
||||
UuidInterface $uuid,
|
||||
ThemeManagerInterface $themeManager,
|
||||
ThemeHandlerInterface $themeHandler,
|
||||
ContextRepositoryInterface $contextRepository,
|
||||
ContextHandlerInterface $contextHandler,
|
||||
AccountInterface $account
|
||||
) {
|
||||
parent::__construct($configuration, $pluginId, $pluginDefinition);
|
||||
|
||||
$this->uuid = $uuid;
|
||||
$this->themeManager = $themeManager;
|
||||
$this->themeHandler = $themeHandler;
|
||||
$this->contextRepository = $contextRepository;
|
||||
$this->contextHandler = $contextHandler;
|
||||
$this->account = $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $pluginId, $pluginDefinition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$pluginId,
|
||||
$pluginDefinition,
|
||||
$container->get('uuid'),
|
||||
$container->get('theme.manager'),
|
||||
$container->get('theme_handler'),
|
||||
$container->get('context.repository'),
|
||||
$container->get('context.handler'),
|
||||
$container->get('current_user')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the plugin.
|
||||
*
|
||||
* @param array $build
|
||||
* The current build of the page.
|
||||
*
|
||||
* @param string|null $title
|
||||
* The page title.
|
||||
*
|
||||
* @param string|null $main_content
|
||||
* The main page content.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function execute(array $build = array(), $title = NULL, $main_content = NULL) {
|
||||
|
||||
$cacheability = CacheableMetadata::createFromRenderArray($build);
|
||||
|
||||
// Use the currently active theme to fetch blocks.
|
||||
$theme = $this->themeManager->getActiveTheme()->getName();
|
||||
|
||||
$regions = $this->getBlocks()->getAllByRegion($theme);
|
||||
|
||||
// Add each block to the page build.
|
||||
foreach ($regions as $region => $blocks) {
|
||||
|
||||
/** @var $blocks BlockPluginInterface[] */
|
||||
foreach ($blocks as $block_id => $block) {
|
||||
$configuration = $block->getConfiguration();
|
||||
|
||||
$block_placement_key = $this->blockShouldBePlacedUniquely($block)
|
||||
? $block_id
|
||||
: $block->getConfiguration()['id'];
|
||||
|
||||
if ($block instanceof MainContentBlockPluginInterface) {
|
||||
if (isset($build['content']['system_main'])) {
|
||||
unset($build['content']['system_main']);
|
||||
}
|
||||
$block->setMainContent($main_content);
|
||||
}
|
||||
|
||||
// Make sure the user is allowed to view the block.
|
||||
$access = $block->access($this->account, TRUE);
|
||||
$cacheability->addCacheableDependency($access);
|
||||
|
||||
// If the user is not allowed then do not render the block.
|
||||
if (!$access->isAllowed()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($block instanceof TitleBlockPluginInterface) {
|
||||
if (isset($build['content']['messages'])) {
|
||||
unset($build['content']['messages']);
|
||||
}
|
||||
$block->setTitle($title);
|
||||
}
|
||||
|
||||
// Inject runtime contexts.
|
||||
if ($block instanceof ContextAwarePluginInterface) {
|
||||
$contexts = $this->contextRepository->getRuntimeContexts($block->getContextMapping());
|
||||
$this->contextHandler->applyContextMapping($block, $contexts);
|
||||
}
|
||||
|
||||
// Create the render array for the block as a whole.
|
||||
// @see template_preprocess_block().
|
||||
$blockBuild = [
|
||||
'#theme' => 'block',
|
||||
'#attributes' => [
|
||||
'class' => [$block->getConfiguration()['css_class']]
|
||||
],
|
||||
'#configuration' => $configuration,
|
||||
'#plugin_id' => $block->getPluginId(),
|
||||
'#base_plugin_id' => $block->getBaseId(),
|
||||
'#derivative_plugin_id' => $block->getDerivativeId(),
|
||||
'#block_plugin' => $block,
|
||||
'#pre_render' => [[$this, 'preRenderBlock']],
|
||||
'#cache' => [
|
||||
'keys' => ['context_blocks_reaction', 'block', $block_placement_key],
|
||||
'tags' => $block->getCacheTags(),
|
||||
'contexts' => $block->getCacheContexts(),
|
||||
'max-age' => $block->getCacheMaxAge(),
|
||||
],
|
||||
];
|
||||
|
||||
// Add contextual links to block.
|
||||
$content = $block->build();
|
||||
if (isset($content['#contextual_links'])) {
|
||||
$blockBuild['#contextual_links'] = $content['#contextual_links'];
|
||||
}
|
||||
|
||||
// Add additional contextual link, for editing block configuration.
|
||||
$blockBuild['#contextual_links']['context_block'] = [
|
||||
'route_parameters' => [
|
||||
'context' => $configuration['context_id'],
|
||||
'reaction_id' => 'blocks',
|
||||
'block_id' => $block->getConfiguration()['uuid'],
|
||||
],
|
||||
];
|
||||
|
||||
if (array_key_exists('weight', $configuration)) {
|
||||
$blockBuild['#weight'] = $configuration['weight'];
|
||||
}
|
||||
|
||||
$build[$region][$block_placement_key] = $blockBuild;
|
||||
|
||||
// After merging with blocks from Block layout, we want to sort all of
|
||||
// them again.
|
||||
$build[$region]['#sorted'] = FALSE;
|
||||
|
||||
// The main content block cannot be cached: it is a placeholder for the
|
||||
// render array returned by the controller. It should be rendered as-is,
|
||||
// with other placed blocks "decorating" it. Analogous reasoning for the
|
||||
// title block.
|
||||
if ($block instanceof MainContentBlockPluginInterface || $block instanceof TitleBlockPluginInterface) {
|
||||
unset($build[$region][$block_placement_key]['#cache']['keys']);
|
||||
}
|
||||
|
||||
$cacheability->addCacheableDependency($block);
|
||||
}
|
||||
}
|
||||
|
||||
$cacheability->applyTo($build);
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the content using the provided block plugin.
|
||||
*
|
||||
* @param array $build
|
||||
* @return array
|
||||
*/
|
||||
public function preRenderBlock($build) {
|
||||
|
||||
$content = $build['#block_plugin']->build();
|
||||
|
||||
unset($build['#block_plugin']);
|
||||
|
||||
// Abort rendering: render as the empty string and ensure this block is
|
||||
// render cached, so we can avoid the work of having to repeatedly
|
||||
// determine whether the block is empty. E.g. modifying or adding entities
|
||||
// could cause the block to no longer be empty.
|
||||
if (is_null($content) || Element::isEmpty($content)) {
|
||||
$build = [
|
||||
'#markup' => '',
|
||||
'#cache' => $build['#cache'],
|
||||
];
|
||||
|
||||
// If $content is not empty, then it contains cacheability metadata, and
|
||||
// we must merge it with the existing cacheability metadata. This allows
|
||||
// blocks to be empty, yet still bubble cacheability metadata, to indicate
|
||||
// why they are empty.
|
||||
if (!empty($content)) {
|
||||
CacheableMetadata::createFromRenderArray($build)
|
||||
->merge(CacheableMetadata::createFromRenderArray($content))
|
||||
->applyTo($build);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$build['content'] = $content;
|
||||
}
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
return [
|
||||
'blocks' => []
|
||||
] + parent::defaultConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setConfiguration(array $configuration) {
|
||||
$this->configuration = $configuration + $this->defaultConfiguration();
|
||||
|
||||
if (isset($configuration['blocks'])) {
|
||||
$this->blocks = $configuration['blocks'];
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfiguration() {
|
||||
return [
|
||||
'blocks' => $this->getBlocks()->getConfiguration(),
|
||||
] + parent::getConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function summary() {
|
||||
return $this->t('Lets you add blocks to the selected themes regions');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all blocks as a collection.
|
||||
*
|
||||
* @return BlockPluginInterface[]|BlockCollection
|
||||
*/
|
||||
public function getBlocks() {
|
||||
if (!$this->blocksCollection) {
|
||||
$blockManager = \Drupal::service('plugin.manager.block');
|
||||
$this->blocksCollection = new BlockCollection($blockManager, $this->blocks);
|
||||
}
|
||||
|
||||
return $this->blocksCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a block by id.
|
||||
*
|
||||
* @param string $blockId
|
||||
* The ID of the block to get.
|
||||
*
|
||||
* @return BlockPluginInterface
|
||||
*/
|
||||
public function getBlock($blockId) {
|
||||
return $this->getBlocks()->get($blockId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new block.
|
||||
*
|
||||
* @param array $configuration
|
||||
*/
|
||||
public function addBlock(array $configuration) {
|
||||
$configuration['uuid'] = $this->uuid->generate();
|
||||
|
||||
$this->getBlocks()->addInstanceId($configuration['uuid'], $configuration);
|
||||
|
||||
return $configuration['uuid'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing blocks configuration.
|
||||
*
|
||||
* @param string $blockId
|
||||
* The ID of the block to update.
|
||||
*
|
||||
* @param $configuration
|
||||
* The updated configuration for the block.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function updateBlock($blockId, array $configuration) {
|
||||
$existingConfiguration = $this->getBlock($blockId)->getConfiguration();
|
||||
|
||||
$this->getBlocks()->setInstanceConfiguration($blockId, $configuration + $existingConfiguration);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $blockId
|
||||
* @return $this
|
||||
*/
|
||||
public function removeBlock($blockId) {
|
||||
$this->getBlocks()->removeInstanceId($blockId);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state, ContextInterface $context = NULL) {
|
||||
$form['#attached']['library'][] = 'block/drupal.block';
|
||||
|
||||
$themes = $this->themeHandler->listInfo();
|
||||
|
||||
$default_theme = $this->themeHandler->getDefault();
|
||||
|
||||
// Select list for changing themes.
|
||||
$form['theme'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Theme'),
|
||||
'#options' => [],
|
||||
'#description' => $this->t('Select the theme you want to display regions for.'),
|
||||
'#default_value' => $form_state->getValue('theme', $default_theme),
|
||||
'#ajax' => [
|
||||
'url' => Url::fromRoute('context.reaction.blocks.regions', [
|
||||
'context' => $context->id(),
|
||||
]),
|
||||
],
|
||||
];
|
||||
|
||||
// Add each theme to the theme select.
|
||||
foreach ($themes as $theme_id => $theme) {
|
||||
if ($theme_id === $default_theme) {
|
||||
$form['theme']['#options'][$theme_id] = $this->t('%theme (Default)', [
|
||||
'%theme' => $theme->info['name'],
|
||||
]);
|
||||
}
|
||||
else {
|
||||
$form['theme']['#options'][$theme_id] = $theme->info['name'];
|
||||
}
|
||||
}
|
||||
|
||||
$form['blocks'] = [
|
||||
'#type' => 'container',
|
||||
'#attributes' => [
|
||||
'id' => 'context-reaction-blocks-container',
|
||||
],
|
||||
];
|
||||
|
||||
$form['blocks']['include_default_blocks'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Include blocks from Block layout'),
|
||||
'#description' => $this->t('if checked, all blocks from default Block layout will also be included in page build.'),
|
||||
'#weight' => -10,
|
||||
'#default_value' => isset($this->getConfiguration()['include_default_blocks']) ? $this->getConfiguration()['include_default_blocks'] : FALSE,
|
||||
];
|
||||
|
||||
|
||||
$form['blocks']['block_add'] = [
|
||||
'#type' => 'link',
|
||||
'#title' => $this->t('Place block'),
|
||||
'#attributes' => [
|
||||
'id' => 'context-reaction-blocks-region-add',
|
||||
] + $this->getAjaxButtonAttributes(),
|
||||
'#url' => Url::fromRoute('context.reaction.blocks.library', [
|
||||
'context' => $context->id(),
|
||||
'reaction_id' => $this->getPluginId(),
|
||||
], [
|
||||
'query' => [
|
||||
'theme' => $form_state->getValue('theme', $default_theme),
|
||||
],
|
||||
]),
|
||||
];
|
||||
|
||||
$form['blocks']['blocks'] = [
|
||||
'#type' => 'table',
|
||||
'#header' => [
|
||||
$this->t('Block'),
|
||||
$this->t('Category'),
|
||||
$this->t('Unique'),
|
||||
$this->t('Region'),
|
||||
$this->t('Weight'),
|
||||
$this->t('Operations'),
|
||||
],
|
||||
'#empty' => $this->t('No regions available to place blocks in.'),
|
||||
'#attributes' => [
|
||||
'id' => 'blocks',
|
||||
],
|
||||
];
|
||||
|
||||
// If a theme has been selected use that to get the regions otherwise use
|
||||
// the default theme.
|
||||
$theme = $form_state->getValue('theme', $default_theme);
|
||||
|
||||
// Get all blocks by their regions.
|
||||
$blocks = $this->getBlocks()->getAllByRegion($theme);
|
||||
|
||||
// Get regions of the selected theme.
|
||||
$regions = $this->getSystemRegionList($theme);
|
||||
|
||||
// Add each region.
|
||||
foreach ($regions as $region => $title) {
|
||||
|
||||
// Add the tabledrag details for this region.
|
||||
$form['blocks']['blocks']['#tabledrag'][] = [
|
||||
'action' => 'match',
|
||||
'relationship' => 'sibling',
|
||||
'group' => 'block-region-select',
|
||||
'subgroup' => 'block-region-' . $region,
|
||||
'hidden' => FALSE,
|
||||
];
|
||||
|
||||
$form['blocks']['blocks']['#tabledrag'][] = [
|
||||
'action' => 'order',
|
||||
'relationship' => 'sibling',
|
||||
'group' => 'block-weight',
|
||||
'subgroup' => 'block-weight-' . $region,
|
||||
];
|
||||
|
||||
// Add the theme region.
|
||||
$form['blocks']['blocks']['region-' . $region] = [
|
||||
'#attributes' => [
|
||||
'class' => ['region-title'],
|
||||
],
|
||||
'title' => [
|
||||
'#markup' => $title,
|
||||
'#wrapper_attributes' => [
|
||||
'colspan' => 6,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$regionEmptyClass = empty($blocks[$region])
|
||||
? 'region-empty'
|
||||
: 'region-populated';
|
||||
|
||||
$form['blocks']['blocks']['region-' . $region . '-message'] = [
|
||||
'#attributes' => [
|
||||
'class' => ['region-message', 'region-' . $region . '-message', $regionEmptyClass],
|
||||
],
|
||||
'message' => [
|
||||
'#markup' => '<em>' . $this->t('No blocks in this region') . '</em>',
|
||||
'#wrapper_attributes' => [
|
||||
'colspan' => 6,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Add each block specified for the region if there are any.
|
||||
if (isset($blocks[$region])) {
|
||||
/** @var BlockPluginInterface $block */
|
||||
foreach ($blocks[$region] as $block_id => $block) {
|
||||
$configuration = $block->getConfiguration();
|
||||
|
||||
$operations = [
|
||||
'edit' => [
|
||||
'title' => $this->t('Edit'),
|
||||
'url' => Url::fromRoute('context.reaction.blocks.block_edit', [
|
||||
'context' => $context->id(),
|
||||
'reaction_id' => $this->getPluginId(),
|
||||
'block_id' => $block_id,
|
||||
], [
|
||||
'query' => [
|
||||
'theme' => $theme,
|
||||
],
|
||||
]),
|
||||
'attributes' => $this->getAjaxAttributes(),
|
||||
],
|
||||
'delete' => [
|
||||
'title' => $this->t('Delete'),
|
||||
'url' => Url::fromRoute('context.reaction.blocks.block_delete', [
|
||||
'context' => $context->id(),
|
||||
'block_id' => $block_id,
|
||||
]),
|
||||
'attributes' => $this->getAjaxAttributes(),
|
||||
],
|
||||
];
|
||||
|
||||
$form['blocks']['blocks'][$block_id] = [
|
||||
'#attributes' => [
|
||||
'class' => ['draggable'],
|
||||
],
|
||||
'label' => [
|
||||
'#markup' => $block->label(),
|
||||
],
|
||||
'category' => [
|
||||
'#markup' => $block->getPluginDefinition()['category'],
|
||||
],
|
||||
'unique' => [
|
||||
'#markup' => $this->blockShouldBePlacedUniquely($block) ? $this->t('Yes') : $this->t('No'),
|
||||
],
|
||||
'region' => [
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Region for @block block', ['@block' => $block->label()]),
|
||||
'#title_display' => 'invisible',
|
||||
'#default_value' => $region,
|
||||
'#options' => $regions,
|
||||
'#attributes' => [
|
||||
'class' => ['block-region-select', 'block-region-' . $region],
|
||||
],
|
||||
],
|
||||
'weight' => [
|
||||
'#type' => 'weight',
|
||||
'#default_value' => isset($configuration['weight']) ? $configuration['weight'] : 0,
|
||||
'#title' => $this->t('Weight for @block block', ['@block' => $block->label()]),
|
||||
'#title_display' => 'invisible',
|
||||
'#attributes' => [
|
||||
'class' => ['block-weight', 'block-weight-' . $region],
|
||||
],
|
||||
],
|
||||
'operations' => [
|
||||
'#type' => 'operations',
|
||||
'#links' => $operations,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the block should be uniquely placed.
|
||||
*
|
||||
* @param BlockPluginInterface $block
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function blockShouldBePlacedUniquely(BlockPluginInterface $block) {
|
||||
$configuration = $block->getConfiguration();
|
||||
return (isset($configuration['unique']) && $configuration['unique']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
$blocks = $form_state->getValue(['blocks', 'blocks'], []);
|
||||
|
||||
// Save configuration for including default blocks.
|
||||
$config = $this->getConfiguration();
|
||||
$config['include_default_blocks'] = $form_state->getValue(['blocks', 'include_default_blocks'], FALSE);
|
||||
$this->setConfiguration($config);
|
||||
|
||||
if (is_array($blocks)) {
|
||||
foreach ($blocks as $block_id => $configuration) {
|
||||
$block = $this->getBlock($block_id);
|
||||
$configuration += $block->getConfiguration();
|
||||
|
||||
$block_state = (new FormState())->setValues($configuration);
|
||||
$block->submitConfigurationForm($form, $block_state);
|
||||
|
||||
// If the block is context aware then add context mapping to the block.
|
||||
if ($block instanceof ContextAwarePluginInterface) {
|
||||
$block->setContextMapping($block_state->getValue('context_mapping', []));
|
||||
}
|
||||
|
||||
$this->updateBlock($block_id, $block_state->getValues());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should reaction include default blocks from Block layout.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function includeDefaultBlocks() {
|
||||
$config = $this->getConfiguration();
|
||||
return isset($config['include_default_blocks']) ? $config['include_default_blocks'] : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps system_region_list().
|
||||
*
|
||||
* @param string $theme
|
||||
* The theme to get a list of regions for.
|
||||
*
|
||||
* @param string $show
|
||||
* What type of regions that should be returned, defaults to all regions.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @todo This could be moved to a service since we use it in a couple of places.
|
||||
*/
|
||||
protected function getSystemRegionList($theme, $show = REGIONS_ALL) {
|
||||
return system_region_list($theme, $show);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context\Plugin\ContextReaction;
|
||||
|
||||
use Drupal\context\ContextReactionPluginBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Provides a content reaction that adds a new css class.
|
||||
*
|
||||
* @ContextReaction(
|
||||
* id = "body_class",
|
||||
* label = @Translation("Body class")
|
||||
* )
|
||||
*/
|
||||
class BodyClass extends ContextReactionPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
return parent::defaultConfiguration() + [
|
||||
'body_class' => '',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function summary() {
|
||||
return $this->getConfiguration()['body_class'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute(array &$vars = []) {
|
||||
return [
|
||||
'class' => explode(' ', $this->getConfiguration()['body_class']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$form['body_class'] = [
|
||||
'#title' => $this->t('Section class'),
|
||||
'#type' => 'textfield',
|
||||
'#description' => $this->t('Provides this text as additional body class in the html.html.twig.'),
|
||||
'#default_value' => $this->getConfiguration()['body_class'],
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
$this->setConfiguration([
|
||||
'body_class' => $form_state->getValue('body_class'),
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context\Plugin\ContextReaction;
|
||||
|
||||
use Drupal\context\ContextReactionPluginBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Menu\MenuParentFormSelectorInterface;
|
||||
use Drupal\Core\Menu\MenuTreeParameters;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a content reaction that adds a css 'active' class to menu item.
|
||||
*
|
||||
* @ContextReaction(
|
||||
* id = "menu",
|
||||
* label = @Translation("Menu")
|
||||
* )
|
||||
*/
|
||||
class Menu extends ContextReactionPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Menu\MenuParentFormSelector
|
||||
*/
|
||||
protected $menuParentFormSelector;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, MenuParentFormSelectorInterface $menu_parent_form_selector) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->menuParentFormSelector = $menu_parent_form_selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('menu.parent_form_selector')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function summary() {
|
||||
return $this->t('Set active menu item based on conditions.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute(array &$vars = []) {
|
||||
$config = $this->getConfiguration();
|
||||
return $config['menu'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$parent_element = $this->menuParentFormSelector->parentSelectElement('main:');
|
||||
$config = $this->getConfiguration();
|
||||
$form['menu_items'] = [
|
||||
'#title' => $this->t('Menu'),
|
||||
'#type' => 'select',
|
||||
'#options' => $parent_element['#options'],
|
||||
'#multiple' => TRUE,
|
||||
'#default_value' => isset($config['menu']) ? $config['menu'] : '',
|
||||
'#size' => 15,
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
$values = array_keys($form_state->getValue('menu_items'));
|
||||
|
||||
$this->setConfiguration([
|
||||
'menu' => $values,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
namespace Drupal\context\Plugin\ContextReaction;
|
||||
|
||||
use Drupal\context\ContextReactionPluginBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Provides a content reaction that will let you change theme.
|
||||
*
|
||||
* @ContextReaction(
|
||||
* id = "page_template_suggestions",
|
||||
* label = @Translation("Page template suggestions")
|
||||
* )
|
||||
*/
|
||||
class PageTemplateSuggestions extends ContextReactionPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function summary() {
|
||||
return $this->t('Gives you ability to add template suggestions.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the plugin.
|
||||
*/
|
||||
public function execute() {
|
||||
$config = $this->getConfiguration();
|
||||
return $config['suggestions'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$config = $this->getConfiguration();
|
||||
|
||||
$form['suggestions'] = [
|
||||
'#type' => 'textarea',
|
||||
'#title' => $this->t('Page template suggestions'),
|
||||
'#default_value' => isset($config['suggestions']) ? $config['suggestions'] : '',
|
||||
'#description' => $this->t('Enter page template suggestions such as "page__front", one per line, in order of preference (using underscores instead of hyphens). Entered template suggestions will override page.html.twig template.'),
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
$config['suggestions'] = str_replace("\r\n", "\n", $form_state->getValue('suggestions'));
|
||||
$this->setConfiguration($config);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
namespace Drupal\context\Plugin\ContextReaction;
|
||||
|
||||
use Drupal\context\ContextReactionPluginBase;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Drupal\Core\Form\FormState;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Theme\ThemeManagerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a content reaction that will let you disable regions.
|
||||
*
|
||||
* @ContextReaction(
|
||||
* id = "regions",
|
||||
* label = @Translation("Regions")
|
||||
* )
|
||||
*/
|
||||
class Regions extends ContextReactionPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* An array of regions to be disabled with this reaction.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $regions = [];
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Theme\ThemeManagerInterface
|
||||
*/
|
||||
protected $themeManager;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function __construct(
|
||||
array $configuration,
|
||||
$pluginId,
|
||||
$pluginDefinition,
|
||||
ThemeManagerInterface $themeManager,
|
||||
ThemeHandlerInterface $themeHandler
|
||||
) {
|
||||
parent::__construct($configuration, $pluginId, $pluginDefinition);
|
||||
$this->themeManager = $themeManager;
|
||||
$this->themeHandler = $themeHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $pluginId, $pluginDefinition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$pluginId,
|
||||
$pluginDefinition,
|
||||
$container->get('theme.manager'),
|
||||
$container->get('theme_handler')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function summary() {
|
||||
return $this->t('Lets you remove regions from selected theme.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the plugin.
|
||||
*/
|
||||
public function execute() {
|
||||
// TODO: Implement execute() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
|
||||
$themes = $this->themeHandler->listInfo();
|
||||
$default_theme = $this->themeHandler->getDefault();
|
||||
|
||||
// Build configuration form for each installed theme.
|
||||
foreach ($themes as $theme_id => $theme) {
|
||||
if ($theme_id == $default_theme) {
|
||||
$title = $this->t('Disable Regions in %theme (Default)', [
|
||||
'%theme' => $theme->info['name'],
|
||||
]);
|
||||
}
|
||||
else {
|
||||
$title = $this->t('Disable Regions in %theme', [
|
||||
'%theme' => $theme->info['name'],
|
||||
]);
|
||||
}
|
||||
|
||||
$form[$theme_id] = [
|
||||
'#type' => 'details',
|
||||
'#title' => $title,
|
||||
'#weight' => 5,
|
||||
'#open' => FALSE,
|
||||
];
|
||||
|
||||
// Get regions of the theme.
|
||||
$regions = $this->getSystemRegionList($theme_id);
|
||||
|
||||
// Get disabled regions.
|
||||
$disabled_regions = $this->getDisabledRegions();
|
||||
|
||||
$form[$theme_id]['regions'] = [
|
||||
'#type' => 'checkboxes',
|
||||
'#options' => $regions,
|
||||
'#title' => $this->t('Disable the following'),
|
||||
'#default_value' => isset($disabled_regions[$theme_id]) ? $disabled_regions[$theme_id] : [],
|
||||
];
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
$themes = $form_state->getValues();
|
||||
if (is_array($themes)) {
|
||||
foreach ($themes as $theme_name => $region) {
|
||||
$disabled_regions = array_keys(array_filter($region['regions']));
|
||||
if (!empty($disabled_regions)) {
|
||||
$configuration['regions'][$theme_name] = $disabled_regions;
|
||||
$configuration += $this->getConfiguration();
|
||||
}
|
||||
else {
|
||||
$configuration['regions'][$theme_name] = [];
|
||||
$configuration += $this->getConfiguration();
|
||||
}
|
||||
$this->setConfiguration($configuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps system_region_list().
|
||||
*
|
||||
* @param string $theme
|
||||
* The theme to get a list of regions for.
|
||||
*
|
||||
* @param string $show
|
||||
* What type of regions that should be returned, defaults to all regions.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @todo This could be moved to a service since we use it in a couple of places.
|
||||
*/
|
||||
protected function getSystemRegionList($theme, $show = REGIONS_ALL) {
|
||||
return system_region_list($theme, $show);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get disabled regions.
|
||||
*/
|
||||
protected function getDisabledRegions() {
|
||||
$configurations = $this->getConfiguration();
|
||||
return isset($configurations['regions']) ? $configurations['regions'] : [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
namespace Drupal\context\Plugin\ContextReaction;
|
||||
|
||||
use Drupal\context\ContextReactionPluginBase;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Theme\ThemeManagerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a content reaction that will let you change theme.
|
||||
*
|
||||
* @ContextReaction(
|
||||
* id = "theme",
|
||||
* label = @Translation("Theme")
|
||||
* )
|
||||
*/
|
||||
class Theme extends ContextReactionPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Theme\ThemeManagerInterface
|
||||
*/
|
||||
protected $themeManager;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function __construct(
|
||||
array $configuration,
|
||||
$pluginId,
|
||||
$pluginDefinition,
|
||||
ThemeManagerInterface $themeManager,
|
||||
ThemeHandlerInterface $themeHandler
|
||||
) {
|
||||
parent::__construct($configuration, $pluginId, $pluginDefinition);
|
||||
$this->themeManager = $themeManager;
|
||||
$this->themeHandler = $themeHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $pluginId, $pluginDefinition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$pluginId,
|
||||
$pluginDefinition,
|
||||
$container->get('theme.manager'),
|
||||
$container->get('theme_handler')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function summary() {
|
||||
return $this->t('Gives you ability to change theme.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the plugin.
|
||||
*/
|
||||
public function execute() {
|
||||
// TODO: Implement execute() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
|
||||
$themes = $this->themeHandler->listInfo();
|
||||
$default_theme = $this->themeHandler->getDefault();
|
||||
|
||||
$theme_options = [];
|
||||
foreach ($themes as $theme_id => $theme) {
|
||||
$theme_options[$theme_id] = $theme->info['name'];
|
||||
}
|
||||
$configuration = $this->getConfiguration();
|
||||
|
||||
$form['theme'] = [
|
||||
'#type' => 'radios',
|
||||
'#options' => $theme_options,
|
||||
'#title' => $this->t('Select theme'),
|
||||
'#default_value' => isset($configuration['theme']) ? $configuration['theme'] : $default_theme,
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
$configuration['theme'] = $form_state->getValue('theme');
|
||||
$configuration += $this->getConfiguration();
|
||||
$this->setConfiguration($configuration);
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context\Plugin;
|
||||
|
||||
use Drupal\Core\Plugin\DefaultLazyPluginCollection;
|
||||
|
||||
class ContextReactionPluginCollection extends DefaultLazyPluginCollection {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return \Drupal\context\ContextReactionInterface
|
||||
*/
|
||||
public function &get($instance_id) {
|
||||
return parent::get($instance_id);
|
||||
}
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context\Plugin\DisplayVariant;
|
||||
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\context\ContextManager;
|
||||
use Drupal\Core\Display\VariantBase;
|
||||
use Drupal\Core\Display\PageVariantInterface;
|
||||
use Drupal\Core\Display\VariantManager;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a page display variant that decorates the main content with blocks.
|
||||
*
|
||||
* @see \Drupal\Core\Block\MainContentBlockPluginInterface
|
||||
* @see \Drupal\Core\Block\MessagesBlockPluginInterface
|
||||
*
|
||||
* @PageDisplayVariant(
|
||||
* id = "context_block_page",
|
||||
* admin_label = @Translation("Page with blocks")
|
||||
* )
|
||||
*/
|
||||
class ContextBlockPageVariant extends VariantBase implements PageVariantInterface, ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* @var ContextManager
|
||||
*/
|
||||
protected $contextManager;
|
||||
|
||||
/**
|
||||
* The render array representing the main page content.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $mainContent = [];
|
||||
|
||||
/**
|
||||
* The page title: a string (plain title) or a render array (formatted title).
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
protected $title = '';
|
||||
|
||||
/**
|
||||
* Constructs a new ContextBlockPageVariant.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
*
|
||||
* @param string $plugin_id
|
||||
* The plugin ID for the plugin instance.
|
||||
*
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
*
|
||||
* @param ContextManager $contextManager
|
||||
* The context module manager.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, ContextManager $contextManager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->contextManager = $contextManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('context.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setMainContent(array $main_content) {
|
||||
$this->mainContent = $main_content;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setTitle($title) {
|
||||
$this->title = $title;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
$build = [
|
||||
'#cache' => [
|
||||
'tags' => ['context_block_page', $this->getPluginId()],
|
||||
],
|
||||
];
|
||||
|
||||
// Place main content block, it will be removed by the reactions if a main
|
||||
// content block has been manually placed.
|
||||
$build['content']['system_main'] = $this->mainContent;
|
||||
|
||||
// Execute each block reaction and let them modify the page build.
|
||||
foreach ($this->contextManager->getActiveReactions('blocks') as $reaction) {
|
||||
$build = $reaction->execute($build, $this->title, $this->mainContent);
|
||||
}
|
||||
|
||||
// Execute each block reaction and check if default block should be included in page build.
|
||||
foreach ($this->contextManager->getActiveReactions('blocks') as $reaction) {
|
||||
if ($reaction->includeDefaultBlocks()) {
|
||||
$build = NestedArray::mergeDeep($this->getBuildFromBlockLayout(), $build);
|
||||
return $build;
|
||||
}
|
||||
}
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get build from Block layout.
|
||||
*/
|
||||
private function getBuildFromBlockLayout() {
|
||||
$plugin_manager = \Drupal::service('plugin.manager.display_variant');
|
||||
$display_variant = $plugin_manager->createInstance('block_page', $plugin_manager->getDefinition('block_page'));
|
||||
$display_variant->setTitle($this->title);
|
||||
|
||||
return $display_variant->build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\context\Reaction\Annotation\ContextReaction.
|
||||
*/
|
||||
|
||||
namespace Drupal\context\Reaction\Annotation;
|
||||
|
||||
use Drupal\Component\Annotation\Plugin;
|
||||
|
||||
/**
|
||||
* Defines an context reaction annotation object.
|
||||
*
|
||||
* Plugin Namespace: Plugin\ContextReaction
|
||||
*
|
||||
* @Annotation
|
||||
*/
|
||||
class ContextReaction extends Plugin {
|
||||
|
||||
/**
|
||||
* The plugin ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* The human-readable name of the context reaction.
|
||||
*
|
||||
* @ingroup plugin_translatable
|
||||
*
|
||||
* @var \Drupal\Core\Annotation\Translation
|
||||
*/
|
||||
public $label;
|
||||
|
||||
/**
|
||||
* A brief description of the context reaction.
|
||||
*
|
||||
* This will be shown when adding or configuring this context reaction.
|
||||
*
|
||||
* @ingroup plugin_translatable
|
||||
*
|
||||
* @var \Drupal\Core\Annotation\Translation (optional)
|
||||
*/
|
||||
public $description = '';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context\Reaction\Blocks;
|
||||
|
||||
use Drupal\Core\Block\BlockPluginInterface;
|
||||
use Drupal\Core\Plugin\DefaultLazyPluginCollection;
|
||||
|
||||
class BlockCollection extends DefaultLazyPluginCollection {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return BlockPluginInterface
|
||||
*/
|
||||
public function &get($instance_id) {
|
||||
return parent::get($instance_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all blocks keyed by their region. Base code from the ctools block
|
||||
* plugin collection.
|
||||
*
|
||||
* @param string $theme
|
||||
* The theme to get blocks for.
|
||||
*
|
||||
* @return BlockPluginInterface[]
|
||||
* An associative array keyed by region, containing an associative array of
|
||||
* block plugins.
|
||||
*/
|
||||
public function getAllByRegion($theme) {
|
||||
$region_assignments = [];
|
||||
|
||||
/** @var BlockPluginInterface[] $this */
|
||||
foreach ($this as $block_id => $block) {
|
||||
$configuration = $block->getConfiguration();
|
||||
|
||||
if ($configuration['theme'] !== $theme) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$region = isset($configuration['region'])
|
||||
? $configuration['region']
|
||||
: NULL;
|
||||
|
||||
$region_assignments[$region][$block_id] = $block;
|
||||
}
|
||||
|
||||
foreach ($region_assignments as $region => $region_assignment) {
|
||||
// @todo Determine the reason this needs error suppression.
|
||||
@uasort($region_assignment, function (BlockPluginInterface $a, BlockPluginInterface $b) {
|
||||
$a_config = $a->getConfiguration();
|
||||
$a_weight = isset($a_config['weight']) ? $a_config['weight'] : 0;
|
||||
|
||||
$b_config = $b->getConfiguration();
|
||||
$b_weight = isset($b_config['weight']) ? $b_config['weight'] : 0;
|
||||
|
||||
if ($a_weight == $b_weight) {
|
||||
return strcmp($a->label(), $b->label());
|
||||
}
|
||||
|
||||
return $a_weight > $b_weight ? 1 : -1;
|
||||
});
|
||||
|
||||
$region_assignments[$region] = $region_assignment;
|
||||
}
|
||||
|
||||
return $region_assignments;
|
||||
}
|
||||
}
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context\Reaction\Blocks\Controller;
|
||||
|
||||
use Drupal\context\ContextManager;
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Ajax\ReplaceCommand;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Drupal\Core\Form\FormState;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\context\ContextInterface;
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Block\BlockManagerInterface;
|
||||
use Drupal\Core\Plugin\Context\ContextRepositoryInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class ContextReactionBlocksController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Block\BlockManagerInterface
|
||||
*/
|
||||
protected $blockManager;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Plugin\Context\ContextRepositoryInterface
|
||||
*/
|
||||
protected $contextRepository;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* @var \Drupal\context\ContextManager
|
||||
*/
|
||||
protected $contextManager;
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @param \Drupal\Core\Block\BlockManagerInterface $blockManager
|
||||
* @param \Drupal\Core\Plugin\Context\ContextRepositoryInterface $contextRepository
|
||||
* @param \Drupal\Core\Extension\ThemeHandlerInterface $themeHandler
|
||||
* @param \Drupal\context\ContextManager $contextManager
|
||||
*/
|
||||
function __construct(
|
||||
BlockManagerInterface $blockManager,
|
||||
ContextRepositoryInterface $contextRepository,
|
||||
ThemeHandlerInterface $themeHandler,
|
||||
ContextManager $contextManager
|
||||
) {
|
||||
$this->blockManager = $blockManager;
|
||||
$this->contextRepository = $contextRepository;
|
||||
$this->themeHandler = $themeHandler;
|
||||
$this->contextManager = $contextManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('plugin.manager.block'),
|
||||
$container->get('context.repository'),
|
||||
$container->get('theme_handler'),
|
||||
$container->get('context.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a library of blocks that can be added to the context reaction.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The request object.
|
||||
*
|
||||
* @param \Drupal\context\ContextInterface $context
|
||||
* The context the blocks reaction belongs to.
|
||||
*
|
||||
* @param string $reaction_id
|
||||
* The ID of the blocks reaction that the selected block
|
||||
* should be added to.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function blocksLibrary(Request $request, ContextInterface $context, $reaction_id) {
|
||||
|
||||
// If a theme has been defined in the query string then use this for
|
||||
// the add block link, default back to the default theme.
|
||||
$theme = $request->query->get('theme', $this->themeHandler->getDefault());
|
||||
|
||||
// Only add blocks which work without any available context.
|
||||
$blocks = $this->blockManager->getDefinitionsForContexts($this->contextRepository->getAvailableContexts());
|
||||
|
||||
// Order by category, and then by admin label.
|
||||
$blocks = $this->blockManager->getSortedDefinitions($blocks);
|
||||
|
||||
$build['filter'] = [
|
||||
'#type' => 'search',
|
||||
'#title' => $this->t('Filter'),
|
||||
'#title_display' => 'invisible',
|
||||
'#size' => 30,
|
||||
'#placeholder' => $this->t('Filter by block name'),
|
||||
'#attributes' => [
|
||||
'class' => ['context-table-filter'],
|
||||
'data-element' => '.block-add-table',
|
||||
'title' => $this->t('Enter a part of the block name to filter by.'),
|
||||
],
|
||||
];
|
||||
|
||||
$headers = [
|
||||
$this->t('Block'),
|
||||
$this->t('Category'),
|
||||
$this->t('Operations'),
|
||||
];
|
||||
|
||||
$build['blocks'] = [
|
||||
'#type' => 'table',
|
||||
'#header' => $headers,
|
||||
'#rows' => [],
|
||||
'#empty' => $this->t('No blocks available.'),
|
||||
'#attributes' => [
|
||||
'class' => ['block-add-table'],
|
||||
],
|
||||
];
|
||||
|
||||
// Add each block definition to the table.
|
||||
foreach ($blocks as $block_id => $block) {
|
||||
$links = [
|
||||
'add' => [
|
||||
'title' => $this->t('Place block'),
|
||||
'url' => Url::fromRoute('context.reaction.blocks.block_add', [
|
||||
'context' => $context->id(),
|
||||
'reaction_id' => $reaction_id,
|
||||
'block_id' => $block_id,
|
||||
], [
|
||||
'query' => [
|
||||
'theme' => $theme,
|
||||
],
|
||||
]),
|
||||
'attributes' => [
|
||||
'class' => ['use-ajax'],
|
||||
'data-dialog-type' => 'modal',
|
||||
'data-dialog-options' => Json::encode([
|
||||
'width' => 700,
|
||||
]),
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$build['blocks']['#rows'][] = [
|
||||
'title' => [
|
||||
'data' => [
|
||||
'#type' => 'inline_template',
|
||||
'#template' => '<div class="context-table-filter-text-source">{{ label }}</div>',
|
||||
'#context' => [
|
||||
'label' => $block['admin_label'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'category' => [
|
||||
'data' => $block['category'],
|
||||
],
|
||||
'operations' => [
|
||||
'data' => [
|
||||
'#type' => 'operations',
|
||||
'#links' => $links,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$build['#attached']['library'][] = 'context_ui/admin';
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for the theme select list on the Context blocks reaction form.
|
||||
*
|
||||
* @param Request $request
|
||||
* The current request.
|
||||
*
|
||||
* @param ContextInterface $context
|
||||
* The context the block reaction is located on.
|
||||
*
|
||||
* @return \Drupal\Core\Ajax\AjaxResponse
|
||||
*/
|
||||
public function blocksFormThemeSelect(Request $request, ContextInterface $context) {
|
||||
$theme = $request->request->get('reactions[blocks][theme]', '', TRUE);
|
||||
|
||||
// Get the context form and supply it with the blocks theme value.
|
||||
$form = $this->contextManager->getForm($context, 'edit', [
|
||||
'reactions' => [
|
||||
'blocks' => [
|
||||
'theme' => $theme,
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$response = new AjaxResponse();
|
||||
|
||||
$response->addCommand(new ReplaceCommand('#context-reactions', $form['reactions']));
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context\Reaction\Blocks\Form;
|
||||
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
|
||||
class BlockAddForm extends BlockFormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'context_reaction_blocks_add_block_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getSubmitValue() {
|
||||
return $this->t('Add block');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function prepareBlock($block_id) {
|
||||
return $this->blockManager->createInstance($block_id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context\Reaction\Blocks\Form;
|
||||
|
||||
use Drupal\context\ContextInterface;
|
||||
use Drupal\context\ContextManager;
|
||||
use Drupal\context\Plugin\ContextReaction\Blocks;
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Ajax\CloseModalDialogCommand;
|
||||
use Drupal\Core\Ajax\ReplaceCommand;
|
||||
use Drupal\Core\Block\BlockPluginInterface;
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
class BlockDeleteForm extends ConfirmFormBase {
|
||||
|
||||
/**
|
||||
* The context that the block is being removed from.
|
||||
*
|
||||
* @var ContextInterface
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* The blocks reaction.
|
||||
*
|
||||
* @var Blocks
|
||||
*/
|
||||
protected $reaction;
|
||||
|
||||
/**
|
||||
* The block that is being removed.
|
||||
*
|
||||
* @var BlockPluginInterface
|
||||
*/
|
||||
protected $block;
|
||||
|
||||
/**
|
||||
* The Context module context manager.
|
||||
*
|
||||
* @var \Drupal\context\ContextManager
|
||||
*/
|
||||
protected $contextManager;
|
||||
|
||||
/**
|
||||
* Construct a condition delete form.
|
||||
*
|
||||
* @param ContextManager $contextManager
|
||||
*/
|
||||
public function __construct(ContextManager $contextManager) {
|
||||
$this->contextManager = $contextManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static (
|
||||
$container->get('context.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'context_reaction_blocks_delete_block_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the question to ask the user.
|
||||
*
|
||||
* @return string
|
||||
* The form question. The page title will be set to this value.
|
||||
*/
|
||||
public function getQuestion() {
|
||||
return $this->t('Are you sure you want to remove the %label block?', [
|
||||
'%label' => $this->block->getConfiguration()['label'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCancelUrl() {
|
||||
return $this->context->urlInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, ContextInterface $context = NULL, $block_id = NULL) {
|
||||
$this->context = $context;
|
||||
|
||||
$this->reaction = $this->context->getReaction('blocks');
|
||||
$this->block = $this->reaction->getBlock($block_id);
|
||||
|
||||
$form = parent::buildForm($form, $form_state);
|
||||
|
||||
// Remove the cancel button if this is an AJAX request since Drupals built
|
||||
// in modal dialogues does not handle buttons that are not a primary
|
||||
// button very well.
|
||||
if ($this->getRequest()->isXmlHttpRequest()) {
|
||||
unset($form['actions']['cancel']);
|
||||
}
|
||||
|
||||
// Submit the form with AJAX if possible.
|
||||
$form['actions']['submit']['#ajax'] = [
|
||||
'callback' => '::submitFormAjax'
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$configuration = $this->block->getConfiguration();
|
||||
|
||||
$this->reaction->removeBlock($configuration['uuid']);
|
||||
|
||||
$this->context->save();
|
||||
|
||||
// If this is not an AJAX request then redirect and show a message.
|
||||
if (!$this->getRequest()->isXmlHttpRequest()) {
|
||||
drupal_set_message($this->t('The %label block has been removed.', [
|
||||
'%label' => $configuration['label']]
|
||||
));
|
||||
|
||||
$form_state->setRedirectUrl($this->getCancelUrl());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle when the form is submitted trough AJAX.
|
||||
*
|
||||
* @return AjaxResponse
|
||||
*/
|
||||
public function submitFormAjax() {
|
||||
$contextForm = $this->contextManager->getForm($this->context, 'edit');
|
||||
|
||||
$response = new AjaxResponse();
|
||||
|
||||
$response->addCommand(new CloseModalDialogCommand());
|
||||
$response->addCommand(new ReplaceCommand('#context-reactions', $contextForm['reactions']));
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context\Reaction\Blocks\Form;
|
||||
|
||||
class BlockEditForm extends BlockFormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'context_reaction_blocks_edit_block_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getSubmitValue() {
|
||||
return $this->t('Update block');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function prepareBlock($block_id) {
|
||||
return $this->reaction->getBlock($block_id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context\Reaction\Blocks\Form;
|
||||
|
||||
use Drupal\context\ContextManager;
|
||||
use Drupal\context\ContextReactionManager;
|
||||
use Drupal\context\Form\AjaxFormTrait;
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Ajax\CloseModalDialogCommand;
|
||||
use Drupal\Core\Ajax\RemoveCommand;
|
||||
use Drupal\Core\Ajax\ReplaceCommand;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormBuilderInterface;
|
||||
use Drupal\Core\Form\FormState;
|
||||
use Drupal\context\ContextInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Component\Plugin\PluginManagerInterface;
|
||||
use Drupal\Core\Plugin\Context\ContextRepositoryInterface;
|
||||
use Drupal\Core\Plugin\ContextAwarePluginInterface;
|
||||
use Drupal\Core\Render\Element\StatusMessages;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
abstract class BlockFormBase extends FormBase {
|
||||
|
||||
use AjaxFormTrait;
|
||||
|
||||
/**
|
||||
* The plugin being configured.
|
||||
*
|
||||
* @var \Drupal\Core\Block\BlockPluginInterface
|
||||
*/
|
||||
protected $block;
|
||||
|
||||
/**
|
||||
* The context entity the reaction belongs to.
|
||||
*
|
||||
* @var ContextInterface
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* The blocks reaction this block should be added to.
|
||||
*
|
||||
* @var \Drupal\context\Plugin\ContextReaction\Blocks
|
||||
*/
|
||||
protected $reaction;
|
||||
|
||||
/**
|
||||
* The block manager.
|
||||
*
|
||||
* @var \Drupal\Component\Plugin\PluginManagerInterface
|
||||
*/
|
||||
protected $blockManager;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Plugin\Context\ContextRepositoryInterface
|
||||
*/
|
||||
protected $contextRepository;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Form\FormBuilderInterface
|
||||
*/
|
||||
protected $formBuilder;
|
||||
|
||||
/**
|
||||
* @var \Drupal\context\ContextReactionManager
|
||||
*/
|
||||
protected $contextReactionManager;
|
||||
|
||||
/**
|
||||
* @var \Drupal\context\ContextManager
|
||||
*/
|
||||
protected $contextManager;
|
||||
|
||||
/**
|
||||
* @var \Symfony\Component\HttpFoundation\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* Constructs a new VariantPluginFormBase.
|
||||
*
|
||||
* @param \Drupal\Component\Plugin\PluginManagerInterface $block_manager
|
||||
* The block manager.
|
||||
*
|
||||
* @param \Drupal\Core\Plugin\Context\ContextRepositoryInterface $contextRepository
|
||||
*
|
||||
* @param \Drupal\Core\Extension\ThemeHandlerInterface $themeHandler
|
||||
* @param \Drupal\Core\Form\FormBuilderInterface $formBuilder
|
||||
* @param \Drupal\context\ContextReactionManager $contextReactionManager
|
||||
* @param \Drupal\context\ContextManager $contextManager
|
||||
* @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
|
||||
*/
|
||||
public function __construct(
|
||||
PluginManagerInterface $block_manager,
|
||||
ContextRepositoryInterface $contextRepository,
|
||||
ThemeHandlerInterface $themeHandler,
|
||||
FormBuilderInterface $formBuilder,
|
||||
ContextReactionManager $contextReactionManager,
|
||||
ContextManager $contextManager,
|
||||
RequestStack $requestStack
|
||||
)
|
||||
{
|
||||
$this->blockManager = $block_manager;
|
||||
$this->contextRepository = $contextRepository;
|
||||
$this->themeHandler = $themeHandler;
|
||||
$this->formBuilder = $formBuilder;
|
||||
$this->contextReactionManager = $contextReactionManager;
|
||||
$this->contextManager = $contextManager;
|
||||
$this->request = $requestStack->getCurrentRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('plugin.manager.block'),
|
||||
$container->get('context.repository'),
|
||||
$container->get('theme_handler'),
|
||||
$container->get('form_builder'),
|
||||
$container->get('plugin.manager.context_reaction'),
|
||||
$container->get('context.manager'),
|
||||
$container->get('request_stack')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the block plugin based on the block ID.
|
||||
*
|
||||
* @param string $block_id
|
||||
* Either a block ID, or the plugin ID used to create a new block.
|
||||
*
|
||||
* @return \Drupal\Core\Block\BlockPluginInterface
|
||||
* The block plugin.
|
||||
*/
|
||||
abstract protected function prepareBlock($block_id);
|
||||
|
||||
/**
|
||||
* Get the value to use for the submit button.
|
||||
*
|
||||
* @return TranslatableMarkup
|
||||
*/
|
||||
abstract protected function getSubmitValue();
|
||||
|
||||
/**
|
||||
* Form constructor.
|
||||
*
|
||||
* @param array $form
|
||||
* An associative array containing the structure of the form.
|
||||
*
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
*
|
||||
* @param ContextInterface $context
|
||||
* The context the reaction belongs to.
|
||||
*
|
||||
* @param string|null $reaction_id
|
||||
* The ID of the blocks reaction the block should be added to.
|
||||
*
|
||||
* @param string|null $block_id
|
||||
* The ID of the block to show a configuration form for.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, ContextInterface $context = NULL, $reaction_id = NULL, $block_id = NULL) {
|
||||
$this->context = $context;
|
||||
|
||||
$this->reaction = $this->context->getReaction($reaction_id);
|
||||
$this->block = $this->prepareBlock($block_id);
|
||||
|
||||
// If a theme was defined in the query use this theme for the block
|
||||
// otherwise use the default theme.
|
||||
$theme = $this->getRequest()->query->get('theme', $this->themeHandler->getDefault());
|
||||
|
||||
// Some blocks require the theme name in the form state like Site Branding
|
||||
$form_state->set('block_theme', $theme);
|
||||
|
||||
// Some blocks require contexts, set a temporary value with gathered
|
||||
// contextual values.
|
||||
$form_state->setTemporaryValue('gathered_contexts', $this->contextRepository->getAvailableContexts());
|
||||
|
||||
$configuration = $this->block->getConfiguration();
|
||||
|
||||
$form['#tree'] = TRUE;
|
||||
|
||||
$form['settings'] = $this->block->buildConfigurationForm([], $form_state);
|
||||
|
||||
$form['settings']['id'] = [
|
||||
'#type' => 'value',
|
||||
'#value' => $this->block->getPluginId(),
|
||||
];
|
||||
|
||||
$form['region'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Region'),
|
||||
'#description' => $this->t('Select the region where this block should be displayed.'),
|
||||
'#options' => $this->getThemeRegionOptions($theme),
|
||||
'#default_value' => isset($configuration['region']) ? $configuration['region'] : '',
|
||||
];
|
||||
|
||||
$form['unique'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Unique'),
|
||||
'#description' => $this->t('Check if the block should be uniquely placed, this means that the block can not be overridden by other blocks of the same type in the selected region.'),
|
||||
'#default_value' => isset($configuration['unique']) ? $configuration['unique'] : FALSE,
|
||||
];
|
||||
|
||||
$form['theme'] = [
|
||||
'#type' => 'value',
|
||||
'#value' => $theme,
|
||||
];
|
||||
|
||||
$form['css_class'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Block Class'),
|
||||
'#default_value' => isset($configuration['css_class']) ? $configuration['css_class'] : '',
|
||||
];
|
||||
|
||||
$form['actions']['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->getSubmitValue(),
|
||||
'#button_type' => 'primary',
|
||||
'#ajax' => [
|
||||
'callback' => '::submitFormAjax'
|
||||
],
|
||||
];
|
||||
|
||||
// Remove ajax from submit, if this is not ajax request.
|
||||
if (!$this->request->isXmlHttpRequest()) {
|
||||
unset($form['actions']['submit']['#ajax']);
|
||||
}
|
||||
|
||||
// Disable cache on form to prevent ajax forms from failing.
|
||||
$form_state->disableCache();
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler.
|
||||
*
|
||||
* @param array $form
|
||||
* An associative array containing the structure of the form.
|
||||
*
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$settings = (new FormState())->setValues($form_state->getValue('settings'));
|
||||
|
||||
// Call the plugin submit handler.
|
||||
$this->block->submitConfigurationForm($form, $settings);
|
||||
|
||||
// Update the original form values.
|
||||
$form_state->setValue('settings', $settings->getValues());
|
||||
|
||||
// Add available contexts if this is a context aware block.
|
||||
if ($this->block instanceof ContextAwarePluginInterface) {
|
||||
$this->block->setContextMapping($form_state->getValue(['settings', 'context_mapping'], []));
|
||||
}
|
||||
|
||||
$configuration = array_merge($this->block->getConfiguration(), [
|
||||
'region' => $form_state->getValue('region'),
|
||||
'theme' => $form_state->getValue('theme'),
|
||||
'css_class' => $form_state->getValue('css_class'),
|
||||
'unique' => $form_state->getValue('unique'),
|
||||
'context_id' => $this->context->id(),
|
||||
]);
|
||||
|
||||
// Add/Update the block.
|
||||
if (!isset($configuration['uuid'])) {
|
||||
$this->reaction->addBlock($configuration);
|
||||
} else {
|
||||
$this->reaction->updateBlock($configuration['uuid'], $configuration);
|
||||
}
|
||||
|
||||
$this->context->save();
|
||||
|
||||
$form_state->setRedirectUrl(Url::fromRoute('entity.context.edit_form', [
|
||||
'context' => $this->context->id(),
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle when the form is submitted trough AJAX.
|
||||
*
|
||||
* @return AjaxResponse
|
||||
*/
|
||||
public function submitFormAjax(array &$form, FormStateInterface $form_state) {
|
||||
$response = new AjaxResponse();
|
||||
|
||||
if ($form_state->getErrors()) {
|
||||
$messages = StatusMessages::renderMessages(NULL);
|
||||
$output[] = $messages;
|
||||
$output[] = $form;
|
||||
$form_class = '.' . str_replace('_', '-', $form_state->getFormObject()->getFormId()) ;
|
||||
// Remove any previously added error messages.
|
||||
$response->addCommand(new RemoveCommand('#drupal-modal .messages--error'));
|
||||
// Replace old form with new one and with error message.
|
||||
$response->addCommand(new ReplaceCommand($form_class, $output));
|
||||
}
|
||||
else {
|
||||
$form = $this->contextManager->getForm($this->context, 'edit');
|
||||
$response->addCommand(new CloseModalDialogCommand());
|
||||
$response->addCommand(new ReplaceCommand('#context-reactions', $form['reactions']));
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of regions for the select list.
|
||||
*
|
||||
* @param string $theme
|
||||
* The theme to get a list of regions for.
|
||||
*
|
||||
* @param string $show
|
||||
* What type of regions that should be returned, defaults to all regions.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getThemeRegionOptions($theme, $show = REGIONS_ALL) {
|
||||
$regions = system_region_list($theme, $show);
|
||||
|
||||
foreach ($regions as $region => $title) {
|
||||
$regions[$region] = $title;
|
||||
}
|
||||
|
||||
return $regions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\context\Reaction;
|
||||
|
||||
use Drupal\context\ContextInterface;
|
||||
use Drupal\context\ContextReactionInterface;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
abstract class ContextReactionFormBase extends FormBase {
|
||||
|
||||
/**
|
||||
* @var ContextInterface
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* @var ContextReactionInterface
|
||||
*/
|
||||
protected $reaction;
|
||||
|
||||
/**
|
||||
* Form constructor.
|
||||
*
|
||||
* @param array $form
|
||||
* An associative array containing the structure of the form.
|
||||
*
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
*
|
||||
* @param \Drupal\context\ContextInterface $context
|
||||
* The context that contains the reaction.
|
||||
*
|
||||
* @param $reaction_id
|
||||
* The id of the reaction that is being configured.
|
||||
*
|
||||
* @return array The form structure.
|
||||
* The form structure.
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, ContextInterface $context = NULL, $reaction_id = NULL) {
|
||||
$this->context = $context;
|
||||
$this->reaction = $this->context->getReaction($reaction_id);
|
||||
|
||||
$form['reaction'] = [
|
||||
'#tree' => TRUE,
|
||||
];
|
||||
|
||||
$form['actions'] = [
|
||||
'#type' => 'actions'
|
||||
];
|
||||
|
||||
$form['actions']['submit'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Save'),
|
||||
'#button_type' => 'primary',
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$this->context->save();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\context\Theme\ThemeSwitcherNegotiator.
|
||||
*/
|
||||
|
||||
namespace Drupal\context\Theme;
|
||||
|
||||
use Drupal\context\Plugin\ContextReaction\Theme;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Theme\ThemeNegotiatorInterface;
|
||||
|
||||
class ThemeSwitcherNegotiator implements ThemeNegotiatorInterface {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $theme;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function applies(RouteMatchInterface $route_match) {
|
||||
$context_manager = \Drupal::service('context.manager');
|
||||
|
||||
// If there is no Theme reaction set, do not try to get active reactions,
|
||||
// since this causes infinite loop.
|
||||
$theme_reaction = FALSE;
|
||||
foreach ($context_manager->getContexts() as $context) {
|
||||
foreach ($context->getReactions() as $reaction) {
|
||||
if ($reaction instanceof Theme) {
|
||||
$theme_reaction = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($theme_reaction) {
|
||||
foreach($context_manager->getActiveReactions('theme') as $theme_reaction) {
|
||||
$configuration = $theme_reaction->getConfiguration();
|
||||
$this->theme = $configuration['theme'];
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function determineActiveTheme(RouteMatchInterface $route_match) {
|
||||
return $this->theme;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user