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