1<?php
2
3namespace Drupal\Core\Block;
4
5use Drupal\Component\Plugin\FallbackPluginManagerInterface;
6use Drupal\Core\Cache\CacheBackendInterface;
7use Drupal\Core\Extension\ModuleHandlerInterface;
8use Drupal\Core\Plugin\CategorizingPluginManagerTrait;
9use Drupal\Core\Plugin\DefaultPluginManager;
10use Drupal\Core\Plugin\FilteredPluginManagerTrait;
11use Psr\Log\LoggerInterface;
12
13/**
14 * Manages discovery and instantiation of block plugins.
15 *
16 * @todo Add documentation to this class.
17 *
18 * @see \Drupal\Core\Block\BlockPluginInterface
19 */
20class BlockManager extends DefaultPluginManager implements BlockManagerInterface, FallbackPluginManagerInterface {
21
22  use CategorizingPluginManagerTrait {
23    getSortedDefinitions as traitGetSortedDefinitions;
24  }
25  use FilteredPluginManagerTrait;
26
27  /**
28   * The logger.
29   *
30   * @var \Psr\Log\LoggerInterface
31   */
32  protected $logger;
33
34  /**
35   * Constructs a new \Drupal\Core\Block\BlockManager object.
36   *
37   * @param \Traversable $namespaces
38   *   An object that implements \Traversable which contains the root paths
39   *   keyed by the corresponding namespace to look for plugin implementations.
40   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
41   *   Cache backend instance to use.
42   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
43   *   The module handler to invoke the alter hook with.
44   * @param \Psr\Log\LoggerInterface $logger
45   *   The logger.
46   */
47  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, LoggerInterface $logger) {
48    parent::__construct('Plugin/Block', $namespaces, $module_handler, 'Drupal\Core\Block\BlockPluginInterface', 'Drupal\Core\Block\Annotation\Block');
49
50    $this->alterInfo($this->getType());
51    $this->setCacheBackend($cache_backend, 'block_plugins');
52    $this->logger = $logger;
53  }
54
55  /**
56   * {@inheritdoc}
57   */
58  protected function getType() {
59    return 'block';
60  }
61
62  /**
63   * {@inheritdoc}
64   */
65  public function processDefinition(&$definition, $plugin_id) {
66    parent::processDefinition($definition, $plugin_id);
67    $this->processDefinitionCategory($definition);
68  }
69
70  /**
71   * {@inheritdoc}
72   */
73  public function getSortedDefinitions(array $definitions = NULL) {
74    // Sort the plugins first by category, then by admin label.
75    $definitions = $this->traitGetSortedDefinitions($definitions, 'admin_label');
76    // Do not display the 'broken' plugin in the UI.
77    unset($definitions['broken']);
78    return $definitions;
79  }
80
81  /**
82   * {@inheritdoc}
83   */
84  public function getFallbackPluginId($plugin_id, array $configuration = []) {
85    return 'broken';
86  }
87
88  /**
89   * {@inheritdoc}
90   */
91  protected function handlePluginNotFound($plugin_id, array $configuration) {
92    $this->logger->warning('The "%plugin_id" was not found', ['%plugin_id' => $plugin_id]);
93    return parent::handlePluginNotFound($plugin_id, $configuration);
94  }
95
96}
97