You are here

class ContextManager in Context 8.4

Same name and namespace in other branches
  1. 8 src/ContextManager.php \Drupal\context\ContextManager
  2. 8.0 src/ContextManager.php \Drupal\context\ContextManager

This is the manager service for the context module.

It should not be confused with the built in contexts in Drupal.

Hierarchy

Expanded class hierarchy of ContextManager

16 files declare their use of ContextManager
BlockDeleteForm.php in src/Reaction/Blocks/Form/BlockDeleteForm.php
BlockFormBase.php in src/Reaction/Blocks/Form/BlockFormBase.php
BlockPageDisplayVariantSubscriber.php in src/EventSubscriber/BlockPageDisplayVariantSubscriber.php
ConditionDeleteForm.php in modules/context_ui/src/Form/ConditionDeleteForm.php
ContextAll.php in src/Plugin/Condition/ContextAll.php

... See full list

1 string reference to 'ContextManager'
context.services.yml in ./context.services.yml
context.services.yml
1 service uses ContextManager
context.manager in ./context.services.yml
Drupal\context\ContextManager

File

src/ContextManager.php, line 24

Namespace

Drupal\context
View source
class ContextManager {
  use ConditionAccessResolverTrait;
  use StringTranslationTrait;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The context repository service.
   *
   * @var \Drupal\Core\Plugin\Context\ContextRepositoryInterface
   */
  protected $contextRepository;

  /**
   * Wraps the context handler.
   *
   * @var \Drupal\Core\Plugin\Context\ContextHandlerInterface
   */
  protected $contextHandler;

  /**
   * The context conditions evaluate.
   *
   * If the context conditions has been evaluated then this is set to TRUE
   * otherwise FALSE.
   *
   * @var bool
   */
  protected $contextConditionsEvaluated = FALSE;

  /**
   * An array of all contexts.
   *
   * @var \Drupal\Context\ContextInterface[]
   */
  protected $contexts = [];

  /**
   * An array of contexts that have been evaluated and are active.
   *
   * @var array
   */
  protected $activeContexts = [];

  /**
   * The entity form builder.
   *
   * @var \Drupal\Core\Entity\EntityFormBuilderInterface
   */
  private $entityFormBuilder;

  /**
   * The theme manager.
   *
   * @var \Drupal\Core\Theme\ThemeManagerInterface
   */
  protected $themeManager;

  /** The route match service.
   *
   * @var \Drupal\Core\Routing\RouteMatchInterface
   */
  protected $currentRouteMatch;

  /**
   * Construct.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The Drupal entity manager service.
   * @param \Drupal\context\Entity\ContextRepositoryInterface $contextRepository
   *   The drupal context repository service.
   * @param \Drupal\context\Entity\ContextHandlerInterface $contextHandler
   *   The Drupal context handler service.
   * @param \Drupal\Core\Entity\EntityFormBuilderInterface $entityFormBuilder
   *   The Drupal EntityFormBuilder service.
   * @param \Drupal\Core\Theme\ThemeManagerInterface $themeManager
   *   The Drupal theme manager service.
   */
  public function __construct(EntityTypeManagerInterface $entityTypeManager, ContextRepositoryInterface $contextRepository, ContextHandlerInterface $contextHandler, EntityFormBuilderInterface $entityFormBuilder, ThemeManagerInterface $themeManager, CurrentRouteMatch $currentRouteMatch) {
    $this->entityTypeManager = $entityTypeManager;
    $this->contextRepository = $contextRepository;
    $this->contextHandler = $contextHandler;
    $this->entityFormBuilder = $entityFormBuilder;
    $this->themeManager = $themeManager;
    $this->currentRouteMatch = $currentRouteMatch;
  }

  /**
   * Get all contexts.
   *
   * @return \Drupal\context\ContextInterface[]
   *   List of contexts, keyed by id.
   */
  public function getContexts() {
    if (!empty($this->contexts)) {
      return $this->contexts;
    }
    $this->contexts = $this->entityTypeManager
      ->getStorage('context')
      ->loadByProperties();

    // Sort the contexts by their weight.
    uasort($this->contexts, [
      $this,
      'sortContextsByWeight',
    ]);
    return $this->contexts;
  }

  /**
   * Get a single context by id.
   *
   * @param string $id
   *   The context id.
   *
   * @return array|\Drupal\context\ContextInterface
   *   The context object if found, NULL otherwise.
   */
  public function getContext($id) {
    $contexts = $this
      ->getContexts();
    $currentContext = $this->currentRouteMatch
      ->getParameter('context') ? $this->currentRouteMatch
      ->getParameter('context')
      ->id() : '';
    $ids = [];
    if ($id) {
      if (strpos($id, '*') !== FALSE) {
        $id = preg_quote($id);
        $id = str_replace('\\*', '.*', $id);
        foreach ($contexts as $context) {
          if (preg_match('/^' . $id . '$/i', $context
            ->getName())) {
            if ($currentContext !== $context
              ->getName()) {
              $ids[$context
                ->getName()] = $context;
            }
          }
        }
        return $ids;
      }
      else {
        if (array_key_exists($id, $contexts)) {
          return $contexts[$id];
        }
      }
    }
  }

  /**
   * Get all contexts sorted by their group.
   *
   * It also sort the contexts by their weight inside of each group.
   *
   * @return array
   *   An array with all contexts by group.
   */
  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
   *   TRUE on context name already exist, FALSE on context name not exist.
   */
  public function contextExists($name) {
    $entity = $this->entityTypeManager
      ->getStorage('context')
      ->loadByProperties([
      'name' => $name,
    ]);
    return (bool) $entity;
  }

  /**
   * Check to see if context conditions has been evaluated.
   *
   * @return bool
   *   TRUE if context was already evaluated, FALSE if context was not.
   */
  public function conditionsHasBeenEvaluated() {
    return $this->contextConditionsEvaluated;
  }

  /**
   * Get the evaluated and active contexts.
   *
   * @return \Drupal\context\ContextInterface[]
   *   An array with the evaluated and active contexts.
   */
  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 \Drupal\context\Entity\ContextReactionInterface[]
   *   An array with all active reactions or reactions of a certain type.
   */
  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 (isset($block
                ->getConfiguration()['theme']) && $block
                ->getConfiguration()['theme'] == $current_theme) {
                $reactions[] = $reaction;
                break;
              }
            }
            if (empty($blocks
              ->getConfiguration())) {
              $reactions[] = $reaction;
            }
          }
          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 \Drupal\context\Entity\ContextInterface $context
   *   The context to evaluate conditions for.
   *
   * @return bool
   *   Whether these conditions grant or deny access.
   */
  public function evaluateContextConditions(ContextInterface $context) {
    $conditions = $context
      ->getConditions();

    // Apply context to any context aware conditions.
    // Abort if the application of contexts has been unsuccessful
    // similarly to BlockAccessControlHandler::checkAccess().
    if (!$this
      ->applyContexts($conditions)) {
      return FALSE;
    }

    // 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 \Drupal\Core\Condition\ConditionPluginCollection $conditions
   *   A collection of conditions to apply context to.
   *
   * @return bool
   *   TRUE if context was applied and FALSE if context
   *   is provided but has no value.
   */
  protected function applyContexts(ConditionPluginCollection &$conditions) {

    // If no contexts to check, the return should be TRUE.
    // For example, empty is the same as sitewide condition.
    if (count($conditions) === 0) {
      return TRUE;
    }
    $passed = FALSE;
    foreach ($conditions as $condition) {
      if ($condition instanceof ContextAwarePluginInterface) {
        try {
          $contexts = $this->contextRepository
            ->getRuntimeContexts(array_values($condition
            ->getContextMapping()));
          $this->contextHandler
            ->applyContextMapping($condition, $contexts);
          $passed = TRUE;
        } catch (ContextException $e) {
          continue;
        }
      }
    }
    return $passed;
  }

  /**
   * Get a rendered form for the context.
   *
   * @param \Drupal\context\ContextInterface $context
   *   The entity to be created or edited.
   * @param string $formType
   *   The operation identifying the form variation to be returned.
   * @param array $form_state_additions
   *   An associative array used to build the current state of the form.
   *
   * @return array
   *   The processed form for the given entity and operation.
   */
  public function getForm(ContextInterface $context, $formType = 'edit', array $form_state_additions = []) {
    return $this->entityFormBuilder
      ->getForm($context, $formType, $form_state_additions);
  }

  /**
   * Sorts an array of context entities by their weight.
   *
   * Callback for uasort().
   *
   * @param \Drupal\context\Entity\ContextInterface $a
   *   First item for comparison.
   * @param \Drupal\context\Entity\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();
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ConditionAccessResolverTrait::resolveConditions protected function Resolves the given conditions based on the condition logic ('and'/'or').
ContextManager::$activeContexts protected property An array of contexts that have been evaluated and are active.
ContextManager::$contextConditionsEvaluated protected property The context conditions evaluate.
ContextManager::$contextHandler protected property Wraps the context handler.
ContextManager::$contextRepository protected property The context repository service.
ContextManager::$contexts protected property An array of all contexts.
ContextManager::$currentRouteMatch protected property The route match service.
ContextManager::$entityFormBuilder private property The entity form builder.
ContextManager::$entityTypeManager protected property The entity type manager.
ContextManager::$themeManager protected property The theme manager.
ContextManager::applyContexts protected function Apply context to all the context aware conditions in the collection.
ContextManager::conditionsHasBeenEvaluated public function Check to see if context conditions has been evaluated.
ContextManager::contextExists public function Check to validate that the context name does not already exist.
ContextManager::evaluateContextConditions public function Evaluate a contexts conditions.
ContextManager::evaluateContexts public function Evaluate all context conditions.
ContextManager::getActiveContexts public function Get the evaluated and active contexts.
ContextManager::getActiveReactions public function Get all active reactions or reactions of a certain type.
ContextManager::getContext public function Get a single context by id.
ContextManager::getContexts public function Get all contexts.
ContextManager::getContextsByGroup public function Get all contexts sorted by their group.
ContextManager::getCurrentTheme private function Get current active theme.
ContextManager::getForm public function Get a rendered form for the context.
ContextManager::sortContextsByWeight public function Sorts an array of context entities by their weight.
ContextManager::__construct public function Construct.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.