Mercurial > hg > isophonics-drupal-site
comparison core/modules/config_translation/src/ConfigMapperManager.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\config_translation; | |
4 | |
5 use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException; | |
6 use Drupal\Core\Cache\CacheBackendInterface; | |
7 use Drupal\Core\Config\TypedConfigManagerInterface; | |
8 use Drupal\Core\Extension\ModuleHandlerInterface; | |
9 use Drupal\Core\Extension\ThemeHandlerInterface; | |
10 use Drupal\Core\Language\LanguageManagerInterface; | |
11 use Drupal\Core\Plugin\DefaultPluginManager; | |
12 use Drupal\Core\Plugin\Discovery\InfoHookDecorator; | |
13 use Drupal\Core\Plugin\Discovery\YamlDiscovery; | |
14 use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator; | |
15 use Drupal\Core\Plugin\Factory\ContainerFactory; | |
16 use Drupal\Core\TypedData\TraversableTypedDataInterface; | |
17 use Drupal\Core\TypedData\TypedDataInterface; | |
18 use Symfony\Component\Routing\RouteCollection; | |
19 | |
20 /** | |
21 * Manages plugins for configuration translation mappers. | |
22 */ | |
23 class ConfigMapperManager extends DefaultPluginManager implements ConfigMapperManagerInterface { | |
24 | |
25 /** | |
26 * The typed config manager. | |
27 * | |
28 * @var \Drupal\Core\Config\TypedConfigManagerInterface | |
29 */ | |
30 protected $typedConfigManager; | |
31 | |
32 /** | |
33 * The theme handler. | |
34 * | |
35 * @var \Drupal\Core\Extension\ThemeHandlerInterface | |
36 */ | |
37 protected $themeHandler; | |
38 | |
39 /** | |
40 * {@inheritdoc} | |
41 */ | |
42 protected $defaults = [ | |
43 'title' => '', | |
44 'names' => [], | |
45 'weight' => 20, | |
46 'class' => '\Drupal\config_translation\ConfigNamesMapper', | |
47 ]; | |
48 | |
49 /** | |
50 * Constructs a ConfigMapperManager. | |
51 * | |
52 * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend | |
53 * The cache backend. | |
54 * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager | |
55 * The language manager. | |
56 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler | |
57 * The module handler. | |
58 * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager | |
59 * The typed config manager. | |
60 * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler | |
61 * The theme handler. | |
62 */ | |
63 public function __construct(CacheBackendInterface $cache_backend, LanguageManagerInterface $language_manager, ModuleHandlerInterface $module_handler, TypedConfigManagerInterface $typed_config_manager, ThemeHandlerInterface $theme_handler) { | |
64 $this->typedConfigManager = $typed_config_manager; | |
65 | |
66 $this->factory = new ContainerFactory($this, '\Drupal\config_translation\ConfigMapperInterface'); | |
67 | |
68 // Let others alter definitions with hook_config_translation_info_alter(). | |
69 $this->moduleHandler = $module_handler; | |
70 $this->themeHandler = $theme_handler; | |
71 | |
72 $this->alterInfo('config_translation_info'); | |
73 // Config translation only uses an info hook discovery, cache by language. | |
74 $cache_key = 'config_translation_info_plugins' . ':' . $language_manager->getCurrentLanguage()->getId(); | |
75 $this->setCacheBackend($cache_backend, $cache_key, ['config_translation_info_plugins']); | |
76 } | |
77 | |
78 /** | |
79 * {@inheritdoc} | |
80 */ | |
81 protected function getDiscovery() { | |
82 if (!isset($this->discovery)) { | |
83 // Look at all themes and modules. | |
84 // @todo If the list of installed modules and themes is changed, new | |
85 // definitions are not picked up immediately and obsolete definitions | |
86 // are not removed, because the list of search directories is only | |
87 // compiled once in this constructor. The current code only works due to | |
88 // coincidence: The request that installs (for instance, a new theme) | |
89 // does not instantiate this plugin manager at the beginning of the | |
90 // request; when routes are being rebuilt at the end of the request, | |
91 // this service only happens to get instantiated with the updated list | |
92 // of installed themes. | |
93 $directories = []; | |
94 foreach ($this->moduleHandler->getModuleList() as $name => $module) { | |
95 $directories[$name] = $module->getPath(); | |
96 } | |
97 foreach ($this->themeHandler->listInfo() as $theme) { | |
98 $directories[$theme->getName()] = $theme->getPath(); | |
99 } | |
100 | |
101 // Check for files named MODULE.config_translation.yml and | |
102 // THEME.config_translation.yml in module/theme roots. | |
103 $this->discovery = new YamlDiscovery('config_translation', $directories); | |
104 $this->discovery = new InfoHookDecorator($this->discovery, 'config_translation_info'); | |
105 $this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery); | |
106 } | |
107 return $this->discovery; | |
108 } | |
109 | |
110 /** | |
111 * {@inheritdoc} | |
112 */ | |
113 public function getMappers(RouteCollection $collection = NULL) { | |
114 $mappers = []; | |
115 foreach ($this->getDefinitions() as $id => $definition) { | |
116 $mappers[$id] = $this->createInstance($id); | |
117 if ($collection) { | |
118 $mappers[$id]->setRouteCollection($collection); | |
119 } | |
120 } | |
121 | |
122 return $mappers; | |
123 } | |
124 | |
125 /** | |
126 * {@inheritdoc} | |
127 */ | |
128 public function processDefinition(&$definition, $plugin_id) { | |
129 parent::processDefinition($definition, $plugin_id); | |
130 | |
131 if (!isset($definition['base_route_name'])) { | |
132 throw new InvalidPluginDefinitionException($plugin_id, "The plugin definition of the mapper '$plugin_id' does not contain a base_route_name."); | |
133 } | |
134 } | |
135 | |
136 /** | |
137 * {@inheritdoc} | |
138 */ | |
139 public function buildDataDefinition(array $definition, $value = NULL, $name = NULL, $parent = NULL) { | |
140 return $this->typedConfigManager->buildDataDefinition($definition, $value, $name, $parent); | |
141 } | |
142 | |
143 /** | |
144 * {@inheritdoc} | |
145 */ | |
146 protected function findDefinitions() { | |
147 $definitions = $this->getDiscovery()->getDefinitions(); | |
148 foreach ($definitions as $plugin_id => &$definition) { | |
149 $this->processDefinition($definition, $plugin_id); | |
150 } | |
151 if ($this->alterHook) { | |
152 $this->moduleHandler->alter($this->alterHook, $definitions); | |
153 } | |
154 | |
155 // If this plugin was provided by a module that does not exist, remove the | |
156 // plugin definition. | |
157 foreach ($definitions as $plugin_id => $plugin_definition) { | |
158 if (isset($plugin_definition['provider']) && !in_array($plugin_definition['provider'], ['core', 'component']) && (!$this->moduleHandler->moduleExists($plugin_definition['provider']) && !in_array($plugin_definition['provider'], array_keys($this->themeHandler->listInfo())))) { | |
159 unset($definitions[$plugin_id]); | |
160 } | |
161 } | |
162 return $definitions; | |
163 } | |
164 | |
165 /** | |
166 * {@inheritdoc} | |
167 */ | |
168 public function hasTranslatable($name) { | |
169 return $this->findTranslatable($this->typedConfigManager->get($name)); | |
170 } | |
171 | |
172 /** | |
173 * Returns TRUE if at least one translatable element is found. | |
174 * | |
175 * @param \Drupal\Core\TypedData\TypedDataInterface $element | |
176 * Configuration schema element. | |
177 * | |
178 * @return bool | |
179 * A boolean indicating if there is at least one translatable element. | |
180 */ | |
181 protected function findTranslatable(TypedDataInterface $element) { | |
182 // In case this is a sequence or a mapping check whether any child element | |
183 // is translatable. | |
184 if ($element instanceof TraversableTypedDataInterface) { | |
185 foreach ($element as $child_element) { | |
186 if ($this->findTranslatable($child_element)) { | |
187 return TRUE; | |
188 } | |
189 } | |
190 // If none of the child elements are translatable, return FALSE. | |
191 return FALSE; | |
192 } | |
193 else { | |
194 $definition = $element->getDataDefinition(); | |
195 return isset($definition['translatable']) && $definition['translatable']; | |
196 } | |
197 } | |
198 | |
199 } |