1<?php
2
3namespace Drupal\Core\Plugin;
4
5use Drupal\Core\StringTranslation\StringTranslationTrait;
6
7/**
8 * Provides a trait for the CategorizingPluginManagerInterface.
9 *
10 * The trait provides methods for categorizing plugin definitions based on a
11 * 'category' key. The plugin manager should make sure there is a default
12 * category. For that the trait's processDefinitionCategory() method can be
13 * invoked from the processDefinition() method.
14 *
15 * @see \Drupal\Component\Plugin\CategorizingPluginManagerInterface
16 */
17trait CategorizingPluginManagerTrait {
18
19  use StringTranslationTrait;
20
21  /**
22   * Processes a plugin definition to ensure there is a category.
23   *
24   * If the definition lacks a category, it defaults to the providing module.
25   *
26   * @param array $definition
27   *   The plugin definition.
28   */
29  protected function processDefinitionCategory(&$definition) {
30    // Ensure that every plugin has a category.
31    if (empty($definition['category'])) {
32      // Default to the human readable module name if the provider is a module;
33      // otherwise the provider machine name is used.
34      $definition['category'] = $this->getProviderName($definition['provider']);
35    }
36  }
37
38  /**
39   * Gets the name of a provider.
40   *
41   * @param string $provider
42   *   The machine name of a plugin provider.
43   *
44   * @return string
45   *   The human-readable module name if it exists, otherwise the
46   *   machine-readable name passed.
47   */
48  protected function getProviderName($provider) {
49    $list = $this->getModuleHandler()->getModuleList();
50    // If the module exists, return its human-readable name.
51    if (isset($list[$provider])) {
52      return $this->getModuleHandler()->getName($provider);
53    }
54    // Otherwise, return the machine name.
55    return $provider;
56  }
57
58  /**
59   * Returns the module handler used.
60   *
61   * @return \Drupal\Core\Extension\ModuleHandlerInterface
62   *   The module handler.
63   */
64  public function getModuleHandler() {
65    // If the class has an injected module handler, use it. Otherwise fall back
66    // to fetch it from the service container.
67    if (isset($this->moduleHandler)) {
68      return $this->moduleHandler;
69    }
70    return \Drupal::moduleHandler();
71  }
72
73  /**
74   * {@inheritdoc}
75   */
76  public function getCategories() {
77    /** @var \Drupal\Core\Plugin\CategorizingPluginManagerTrait|\Drupal\Component\Plugin\PluginManagerInterface $this */
78    // Fetch all categories from definitions and remove duplicates.
79    $categories = array_unique(array_values(array_map(function ($definition) {
80      return $definition['category'];
81    }, $this->getDefinitions())));
82    natcasesort($categories);
83    return $categories;
84  }
85
86  /**
87   * {@inheritdoc}
88   */
89  public function getSortedDefinitions(array $definitions = NULL, $label_key = 'label') {
90    // Sort the plugins first by category, then by label.
91    /** @var \Drupal\Core\Plugin\CategorizingPluginManagerTrait|\Drupal\Component\Plugin\PluginManagerInterface $this */
92    $definitions = isset($definitions) ? $definitions : $this->getDefinitions();
93    uasort($definitions, function ($a, $b) use ($label_key) {
94      if ($a['category'] != $b['category']) {
95        return strnatcasecmp($a['category'], $b['category']);
96      }
97      return strnatcasecmp($a[$label_key], $b[$label_key]);
98    });
99    return $definitions;
100  }
101
102  /**
103   * {@inheritdoc}
104   */
105  public function getGroupedDefinitions(array $definitions = NULL, $label_key = 'label') {
106    /** @var \Drupal\Core\Plugin\CategorizingPluginManagerTrait|\Drupal\Component\Plugin\PluginManagerInterface $this */
107    $definitions = $this->getSortedDefinitions(isset($definitions) ? $definitions : $this->getDefinitions(), $label_key);
108    $grouped_definitions = [];
109    foreach ($definitions as $id => $definition) {
110      $grouped_definitions[(string) $definition['category']][$id] = $definition;
111    }
112    return $grouped_definitions;
113  }
114
115}
116