annotate core/modules/config_translation/src/ConfigNamesMapper.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents af1871eacc83
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\config_translation;
Chris@0 4
Chris@17 5 use Drupal\config_translation\Event\ConfigMapperPopulateEvent;
Chris@17 6 use Drupal\config_translation\Event\ConfigTranslationEvents;
Chris@0 7 use Drupal\config_translation\Exception\ConfigMapperLanguageException;
Chris@0 8 use Drupal\Core\Config\ConfigFactoryInterface;
Chris@0 9 use Drupal\Core\Config\TypedConfigManagerInterface;
Chris@0 10 use Drupal\Core\Language\LanguageInterface;
Chris@0 11 use Drupal\Core\Language\LanguageManagerInterface;
Chris@0 12 use Drupal\Core\Plugin\PluginBase;
Chris@0 13 use Drupal\Core\Routing\RouteMatchInterface;
Chris@0 14 use Drupal\Core\Routing\RouteProviderInterface;
Chris@0 15 use Drupal\Core\StringTranslation\TranslationInterface;
Chris@0 16 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
Chris@0 17 use Drupal\Core\Url;
Chris@0 18 use Drupal\locale\LocaleConfigManager;
Chris@0 19 use Symfony\Component\DependencyInjection\ContainerInterface;
Chris@17 20 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
Chris@0 21 use Symfony\Component\Routing\Route;
Chris@0 22 use Symfony\Component\Routing\RouteCollection;
Chris@0 23
Chris@0 24 /**
Chris@0 25 * Configuration mapper base implementation.
Chris@0 26 */
Chris@0 27 class ConfigNamesMapper extends PluginBase implements ConfigMapperInterface, ContainerFactoryPluginInterface {
Chris@0 28
Chris@0 29 /**
Chris@0 30 * The configuration factory.
Chris@0 31 *
Chris@0 32 * @var \Drupal\Core\Config\ConfigFactoryInterface
Chris@0 33 */
Chris@0 34 protected $configFactory;
Chris@0 35
Chris@0 36 /**
Chris@0 37 * The typed config manager.
Chris@0 38 *
Chris@0 39 * @var \Drupal\Core\Config\TypedConfigManagerInterface
Chris@0 40 */
Chris@0 41 protected $typedConfigManager;
Chris@0 42
Chris@0 43 /**
Chris@0 44 * The typed configuration manager.
Chris@0 45 *
Chris@0 46 * @var \Drupal\locale\LocaleConfigManager
Chris@0 47 */
Chris@0 48 protected $localeConfigManager;
Chris@0 49
Chris@0 50 /**
Chris@0 51 * The mapper plugin discovery service.
Chris@0 52 *
Chris@0 53 * @var \Drupal\config_translation\ConfigMapperManagerInterface
Chris@0 54 */
Chris@0 55 protected $configMapperManager;
Chris@0 56
Chris@0 57 /**
Chris@0 58 * The route provider.
Chris@0 59 *
Chris@0 60 * @var \Drupal\Core\Routing\RouteProviderInterface
Chris@0 61 */
Chris@0 62 protected $routeProvider;
Chris@0 63
Chris@0 64 /**
Chris@0 65 * The base route object that the mapper is attached to.
Chris@0 66 *
Chris@12 67 * @var \Symfony\Component\Routing\Route
Chris@0 68 */
Chris@0 69 protected $baseRoute;
Chris@0 70
Chris@0 71 /**
Chris@0 72 * The available routes.
Chris@0 73 *
Chris@0 74 * @var \Symfony\Component\Routing\RouteCollection
Chris@0 75 */
Chris@0 76 protected $routeCollection;
Chris@0 77
Chris@0 78 /**
Chris@0 79 * The language code of the language this mapper, if any.
Chris@0 80 *
Chris@0 81 * @var string|null
Chris@0 82 */
Chris@0 83 protected $langcode = NULL;
Chris@0 84
Chris@0 85 /**
Chris@0 86 * The language manager.
Chris@0 87 *
Chris@0 88 * @var \Drupal\Core\Language\LanguageManagerInterface
Chris@0 89 */
Chris@0 90 protected $languageManager;
Chris@0 91
Chris@0 92 /**
Chris@17 93 * The event dispatcher.
Chris@17 94 *
Chris@17 95 * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
Chris@17 96 */
Chris@17 97 protected $eventDispatcher;
Chris@17 98
Chris@17 99 /**
Chris@0 100 * Constructs a ConfigNamesMapper.
Chris@0 101 *
Chris@0 102 * @param $plugin_id
Chris@0 103 * The config mapper plugin ID.
Chris@0 104 * @param mixed $plugin_definition
Chris@0 105 * An array of plugin information with the following keys:
Chris@0 106 * - title: The title of the mapper, used for generating page titles.
Chris@0 107 * - base_route_name: The route name of the base route this mapper is
Chris@0 108 * attached to.
Chris@0 109 * - names: (optional) An array of configuration names.
Chris@0 110 * - weight: (optional) The weight of this mapper, used in mapper listings.
Chris@0 111 * Defaults to 20.
Chris@0 112 * - list_controller: (optional) Class name for list controller used to
Chris@0 113 * generate lists of this type of configuration.
Chris@0 114 * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
Chris@0 115 * The configuration factory.
Chris@0 116 * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config
Chris@0 117 * The typed configuration manager.
Chris@0 118 * @param \Drupal\locale\LocaleConfigManager $locale_config_manager
Chris@0 119 * The locale configuration manager.
Chris@0 120 * @param \Drupal\config_translation\ConfigMapperManagerInterface $config_mapper_manager
Chris@0 121 * The mapper plugin discovery service.
Chris@0 122 * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
Chris@0 123 * The route provider.
Chris@0 124 * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
Chris@0 125 * The string translation manager.
Chris@0 126 * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
Chris@0 127 * The language manager.
Chris@17 128 * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
Chris@17 129 * (optional) The event dispatcher.
Chris@0 130 *
Chris@0 131 * @throws \Symfony\Component\Routing\Exception\RouteNotFoundException
Chris@0 132 * Throws an exception if the route specified by the 'base_route_name' in
Chris@0 133 * the plugin definition could not be found by the route provider.
Chris@0 134 */
Chris@17 135 public function __construct($plugin_id, $plugin_definition, ConfigFactoryInterface $config_factory, TypedConfigManagerInterface $typed_config, LocaleConfigManager $locale_config_manager, ConfigMapperManagerInterface $config_mapper_manager, RouteProviderInterface $route_provider, TranslationInterface $string_translation, LanguageManagerInterface $language_manager, EventDispatcherInterface $event_dispatcher = NULL) {
Chris@0 136 $this->pluginId = $plugin_id;
Chris@0 137 $this->pluginDefinition = $plugin_definition;
Chris@0 138 $this->routeProvider = $route_provider;
Chris@0 139
Chris@0 140 $this->configFactory = $config_factory;
Chris@0 141 $this->typedConfigManager = $typed_config;
Chris@0 142 $this->localeConfigManager = $locale_config_manager;
Chris@0 143 $this->configMapperManager = $config_mapper_manager;
Chris@0 144
Chris@0 145 $this->stringTranslation = $string_translation;
Chris@0 146 $this->languageManager = $language_manager;
Chris@17 147 $this->eventDispatcher = $event_dispatcher ?: \Drupal::service('event_dispatcher');
Chris@0 148 }
Chris@0 149
Chris@0 150 /**
Chris@0 151 * {@inheritdoc}
Chris@0 152 */
Chris@0 153 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
Chris@0 154 // Note that we ignore the plugin $configuration because mappers have
Chris@0 155 // nothing to configure in themselves.
Chris@18 156 return new static(
Chris@0 157 $plugin_id,
Chris@0 158 $plugin_definition,
Chris@0 159 $container->get('config.factory'),
Chris@0 160 $container->get('config.typed'),
Chris@0 161 $container->get('locale.config_manager'),
Chris@0 162 $container->get('plugin.manager.config_translation.mapper'),
Chris@0 163 $container->get('router.route_provider'),
Chris@0 164 $container->get('string_translation'),
Chris@17 165 $container->get('language_manager'),
Chris@17 166 $container->get('event_dispatcher')
Chris@0 167 );
Chris@0 168 }
Chris@0 169
Chris@0 170 /**
Chris@0 171 * {@inheritdoc}
Chris@0 172 */
Chris@0 173 public function setRouteCollection(RouteCollection $collection) {
Chris@0 174 $this->routeCollection = $collection;
Chris@0 175 }
Chris@0 176
Chris@0 177 /**
Chris@0 178 * {@inheritdoc}
Chris@0 179 */
Chris@0 180 public function getTitle() {
Chris@0 181 // A title from a *.config_translation.yml. Should be translated for
Chris@0 182 // display in the current page language.
Chris@0 183 return $this->t($this->pluginDefinition['title']);
Chris@0 184 }
Chris@0 185
Chris@0 186 /**
Chris@0 187 * {@inheritdoc}
Chris@0 188 */
Chris@0 189 public function getBaseRouteName() {
Chris@0 190 return $this->pluginDefinition['base_route_name'];
Chris@0 191 }
Chris@0 192
Chris@0 193 /**
Chris@0 194 * {@inheritdoc}
Chris@0 195 */
Chris@0 196 public function getBaseRouteParameters() {
Chris@0 197 return [];
Chris@0 198 }
Chris@0 199
Chris@0 200 /**
Chris@0 201 * {@inheritdoc}
Chris@0 202 */
Chris@0 203 public function getBaseRoute() {
Chris@0 204 if ($this->routeCollection) {
Chris@0 205 return $this->routeCollection->get($this->getBaseRouteName());
Chris@0 206 }
Chris@0 207 else {
Chris@0 208 return $this->routeProvider->getRouteByName($this->getBaseRouteName());
Chris@0 209 }
Chris@0 210 }
Chris@0 211
Chris@0 212 /**
Chris@0 213 * Allows to process all config translation routes.
Chris@0 214 *
Chris@0 215 * @param \Symfony\Component\Routing\Route $route
Chris@0 216 * The route object to process.
Chris@0 217 */
Chris@0 218 protected function processRoute(Route $route) {
Chris@0 219 }
Chris@0 220
Chris@0 221 /**
Chris@0 222 * {@inheritdoc}
Chris@0 223 */
Chris@0 224 public function getBasePath() {
Chris@0 225 return Url::fromRoute($this->getBaseRouteName(), $this->getBaseRouteParameters())->getInternalPath();
Chris@0 226 }
Chris@0 227
Chris@0 228 /**
Chris@0 229 * {@inheritdoc}
Chris@0 230 */
Chris@0 231 public function getOverviewRouteName() {
Chris@0 232 return 'config_translation.item.overview.' . $this->getBaseRouteName();
Chris@0 233 }
Chris@0 234
Chris@0 235 /**
Chris@0 236 * {@inheritdoc}
Chris@0 237 */
Chris@0 238 public function getOverviewRouteParameters() {
Chris@0 239 return $this->getBaseRouteParameters();
Chris@0 240 }
Chris@0 241
Chris@0 242 /**
Chris@0 243 * {@inheritdoc}
Chris@0 244 */
Chris@0 245 public function getOverviewRoute() {
Chris@0 246 $route = new Route(
Chris@0 247 $this->getBaseRoute()->getPath() . '/translate',
Chris@0 248 [
Chris@0 249 '_controller' => '\Drupal\config_translation\Controller\ConfigTranslationController::itemPage',
Chris@0 250 'plugin_id' => $this->getPluginId(),
Chris@0 251 ],
Chris@0 252 ['_config_translation_overview_access' => 'TRUE']
Chris@0 253 );
Chris@0 254 $this->processRoute($route);
Chris@0 255 return $route;
Chris@0 256 }
Chris@0 257
Chris@0 258 /**
Chris@0 259 * {@inheritdoc}
Chris@0 260 */
Chris@0 261 public function getOverviewPath() {
Chris@0 262 return Url::fromRoute($this->getOverviewRouteName(), $this->getOverviewRouteParameters())->getInternalPath();
Chris@0 263 }
Chris@0 264
Chris@0 265 /**
Chris@0 266 * {@inheritdoc}
Chris@0 267 */
Chris@0 268 public function getAddRouteName() {
Chris@0 269 return 'config_translation.item.add.' . $this->getBaseRouteName();
Chris@0 270 }
Chris@0 271
Chris@0 272 /**
Chris@0 273 * {@inheritdoc}
Chris@0 274 */
Chris@0 275 public function getAddRouteParameters() {
Chris@0 276 // If sub-classes provide route parameters in getBaseRouteParameters(), they
Chris@0 277 // probably also want to provide those for the add, edit, and delete forms.
Chris@0 278 $parameters = $this->getBaseRouteParameters();
Chris@0 279 $parameters['langcode'] = $this->langcode;
Chris@0 280 return $parameters;
Chris@0 281 }
Chris@0 282
Chris@0 283 /**
Chris@0 284 * {@inheritdoc}
Chris@0 285 */
Chris@0 286 public function getAddRoute() {
Chris@0 287 $route = new Route(
Chris@0 288 $this->getBaseRoute()->getPath() . '/translate/{langcode}/add',
Chris@0 289 [
Chris@0 290 '_form' => '\Drupal\config_translation\Form\ConfigTranslationAddForm',
Chris@0 291 'plugin_id' => $this->getPluginId(),
Chris@0 292 ],
Chris@0 293 ['_config_translation_form_access' => 'TRUE']
Chris@0 294 );
Chris@0 295 $this->processRoute($route);
Chris@0 296 return $route;
Chris@0 297 }
Chris@0 298
Chris@0 299 /**
Chris@0 300 * {@inheritdoc}
Chris@0 301 */
Chris@0 302 public function getEditRouteName() {
Chris@0 303 return 'config_translation.item.edit.' . $this->getBaseRouteName();
Chris@0 304 }
Chris@0 305
Chris@0 306 /**
Chris@0 307 * {@inheritdoc}
Chris@0 308 */
Chris@0 309 public function getEditRouteParameters() {
Chris@0 310 return $this->getAddRouteParameters();
Chris@0 311 }
Chris@0 312
Chris@0 313 /**
Chris@0 314 * {@inheritdoc}
Chris@0 315 */
Chris@0 316 public function getEditRoute() {
Chris@0 317 $route = new Route(
Chris@0 318 $this->getBaseRoute()->getPath() . '/translate/{langcode}/edit',
Chris@0 319 [
Chris@0 320 '_form' => '\Drupal\config_translation\Form\ConfigTranslationEditForm',
Chris@0 321 'plugin_id' => $this->getPluginId(),
Chris@0 322 ],
Chris@0 323 ['_config_translation_form_access' => 'TRUE']
Chris@0 324 );
Chris@0 325 $this->processRoute($route);
Chris@0 326 return $route;
Chris@0 327 }
Chris@0 328
Chris@0 329 /**
Chris@0 330 * {@inheritdoc}
Chris@0 331 */
Chris@0 332 public function getDeleteRouteName() {
Chris@0 333 return 'config_translation.item.delete.' . $this->getBaseRouteName();
Chris@0 334 }
Chris@0 335
Chris@0 336 /**
Chris@0 337 * {@inheritdoc}
Chris@0 338 */
Chris@0 339 public function getDeleteRouteParameters() {
Chris@0 340 return $this->getAddRouteParameters();
Chris@0 341 }
Chris@0 342
Chris@0 343 /**
Chris@0 344 * {@inheritdoc}
Chris@0 345 */
Chris@0 346 public function getDeleteRoute() {
Chris@0 347 $route = new Route(
Chris@0 348 $this->getBaseRoute()->getPath() . '/translate/{langcode}/delete',
Chris@0 349 [
Chris@0 350 '_form' => '\Drupal\config_translation\Form\ConfigTranslationDeleteForm',
Chris@0 351 'plugin_id' => $this->getPluginId(),
Chris@0 352 ],
Chris@0 353 ['_config_translation_form_access' => 'TRUE']
Chris@0 354 );
Chris@0 355 $this->processRoute($route);
Chris@0 356 return $route;
Chris@0 357 }
Chris@0 358
Chris@0 359 /**
Chris@0 360 * {@inheritdoc}
Chris@0 361 */
Chris@0 362 public function getConfigNames() {
Chris@0 363 return $this->pluginDefinition['names'];
Chris@0 364 }
Chris@0 365
Chris@0 366 /**
Chris@0 367 * {@inheritdoc}
Chris@0 368 */
Chris@0 369 public function addConfigName($name) {
Chris@0 370 $this->pluginDefinition['names'][] = $name;
Chris@0 371 }
Chris@0 372
Chris@0 373 /**
Chris@0 374 * {@inheritdoc}
Chris@0 375 */
Chris@0 376 public function getWeight() {
Chris@0 377 return $this->pluginDefinition['weight'];
Chris@0 378 }
Chris@0 379
Chris@0 380 /**
Chris@0 381 * {@inheritdoc}
Chris@0 382 */
Chris@0 383 public function populateFromRouteMatch(RouteMatchInterface $route_match) {
Chris@0 384 $this->langcode = $route_match->getParameter('langcode');
Chris@17 385
Chris@17 386 $event = new ConfigMapperPopulateEvent($this, $route_match);
Chris@17 387 $this->eventDispatcher->dispatch(ConfigTranslationEvents::POPULATE_MAPPER, $event);
Chris@0 388 }
Chris@0 389
Chris@0 390 /**
Chris@0 391 * {@inheritdoc}
Chris@0 392 */
Chris@0 393 public function getTypeLabel() {
Chris@0 394 return $this->getTitle();
Chris@0 395 }
Chris@0 396
Chris@0 397 /**
Chris@0 398 * {@inheritdoc}
Chris@0 399 */
Chris@0 400 public function getLangcode() {
Chris@0 401 $langcodes = array_map([$this, 'getLangcodeFromConfig'], $this->getConfigNames());
Chris@0 402
Chris@0 403 if (count(array_unique($langcodes)) > 1) {
Chris@0 404 throw new ConfigMapperLanguageException('A config mapper can only contain configuration for a single language.');
Chris@0 405 }
Chris@0 406
Chris@0 407 return reset($langcodes);
Chris@0 408 }
Chris@0 409
Chris@0 410 /**
Chris@0 411 * {@inheritdoc}
Chris@0 412 */
Chris@0 413 public function getLangcodeFromConfig($config_name) {
Chris@0 414 // Default to English if no language code was provided in the file.
Chris@0 415 // Although it is a best practice to include a language code, if the
Chris@0 416 // developer did not think about a multilingual use case, we fall back
Chris@0 417 // on assuming the file is English.
Chris@0 418 return $this->configFactory->get($config_name)->get('langcode') ?: 'en';
Chris@0 419 }
Chris@0 420
Chris@0 421 /**
Chris@0 422 * {@inheritdoc}
Chris@0 423 */
Chris@0 424 public function setLangcode($langcode) {
Chris@0 425 $this->langcode = $langcode;
Chris@0 426 return $this;
Chris@0 427 }
Chris@0 428
Chris@0 429 /**
Chris@0 430 * {@inheritdoc}
Chris@0 431 */
Chris@0 432 public function getConfigData() {
Chris@0 433 $config_data = [];
Chris@0 434 foreach ($this->getConfigNames() as $name) {
Chris@0 435 $config_data[$name] = $this->configFactory->getEditable($name)->get();
Chris@0 436 }
Chris@0 437 return $config_data;
Chris@0 438 }
Chris@0 439
Chris@0 440 /**
Chris@0 441 * {@inheritdoc}
Chris@0 442 */
Chris@0 443 public function hasSchema() {
Chris@0 444 foreach ($this->getConfigNames() as $name) {
Chris@0 445 if (!$this->typedConfigManager->hasConfigSchema($name)) {
Chris@0 446 return FALSE;
Chris@0 447 }
Chris@0 448 }
Chris@0 449 return TRUE;
Chris@0 450 }
Chris@0 451
Chris@0 452 /**
Chris@0 453 * {@inheritdoc}
Chris@0 454 */
Chris@0 455 public function hasTranslatable() {
Chris@0 456 foreach ($this->getConfigNames() as $name) {
Chris@0 457 if ($this->configMapperManager->hasTranslatable($name)) {
Chris@0 458 return TRUE;
Chris@0 459 }
Chris@0 460 }
Chris@0 461 return FALSE;
Chris@0 462 }
Chris@0 463
Chris@0 464 /**
Chris@0 465 * {@inheritdoc}
Chris@0 466 */
Chris@0 467 public function hasTranslation(LanguageInterface $language) {
Chris@0 468 foreach ($this->getConfigNames() as $name) {
Chris@0 469 if ($this->localeConfigManager->hasTranslation($name, $language->getId())) {
Chris@0 470 return TRUE;
Chris@0 471 }
Chris@0 472 }
Chris@0 473 return FALSE;
Chris@0 474 }
Chris@0 475
Chris@0 476 /**
Chris@0 477 * {@inheritdoc}
Chris@0 478 */
Chris@0 479 public function getTypeName() {
Chris@0 480 return $this->t('Settings');
Chris@0 481 }
Chris@0 482
Chris@0 483 /**
Chris@0 484 * {@inheritdoc}
Chris@0 485 */
Chris@0 486 public function getOperations() {
Chris@0 487 return [
Chris@0 488 'translate' => [
Chris@0 489 'title' => $this->t('Translate'),
Chris@0 490 'url' => Url::fromRoute($this->getOverviewRouteName(), $this->getOverviewRouteParameters()),
Chris@0 491 ],
Chris@0 492 ];
Chris@0 493 }
Chris@0 494
Chris@0 495 /**
Chris@0 496 * {@inheritdoc}
Chris@0 497 */
Chris@0 498 public function getContextualLinkGroup() {
Chris@0 499 return NULL;
Chris@0 500 }
Chris@0 501
Chris@0 502 }