diff --git a/config_translation.services.yml b/config_translation.services.yml index 4041b48..d5c8d59 100644 --- a/config_translation.services.yml +++ b/config_translation.services.yml @@ -1,5 +1,5 @@ services: - config_translation.subscriber: + config_translation.route_subscriber: class: Drupal\config_translation\Routing\RouteSubscriber arguments: ['@plugin.manager.config_translation'] tags: @@ -10,10 +10,4 @@ services: - { name: access_check } plugin.manager.config_translation: class: Drupal\config_translation\ConfigMapperManager - arguments: - - '@cache.cache' - - '@language_manager' - - '@module_handler' - - '@entity.manager' - - '@database' - - '@string_translation' + arguments: ['@service_container'] diff --git a/lib/Drupal/config_translation/ConfigMapperManager.php b/lib/Drupal/config_translation/ConfigMapperManager.php index ffe8a00..c5d3a48 100644 --- a/lib/Drupal/config_translation/ConfigMapperManager.php +++ b/lib/Drupal/config_translation/ConfigMapperManager.php @@ -7,14 +7,13 @@ namespace Drupal\config_translation; use Drupal\Component\Utility\Unicode; -use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Database\Connection; use Drupal\Core\Entity\EntityManager; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Language\LanguageManager; +use Drupal\Core\Form\ConfigFormInterface; use Drupal\Core\Plugin\DefaultPluginManager; use Drupal\Core\Plugin\Factory\ContainerFactory; use Drupal\Core\StringTranslation\TranslationInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Manages plugins for configuration translation mappers. @@ -22,6 +21,16 @@ use Drupal\Core\StringTranslation\TranslationInterface; class ConfigMapperManager extends DefaultPluginManager { /** + * The dependency injection container. + * + * This is needed to instantiate form objects from the '_form' definition of + * routes. + * + * @var \Symfony\Component\DependencyInjection\ContainerInterface + */ + protected $container; + + /** * The entity manager. * * @var \Drupal\Core\Entity\EntityManager @@ -52,16 +61,18 @@ class ConfigMapperManager extends DefaultPluginManager { 'add_edit_tab' => '0', ); - public function __construct(CacheBackendInterface $cache_backend, LanguageManager $language_manager, ModuleHandlerInterface $module_handler, EntityManager $entity_manager, Connection $connection, TranslationInterface $translation_manager) { - $this->entityManager = $entity_manager; - $this->connection = $connection; - $this->translationManager = $translation_manager; + public function __construct(ContainerInterface $container) { + $this->container = $container; + + $this->entityManager = $this->container->get('entity.manager'); + $this->connection = $this->container->get('database'); + $this->translationManager = $this->container->get('string_translation'); $this->factory = new ContainerFactory($this); // Let others alter definitions with hook_config_translation_info_alter(). - $this->alterInfo($module_handler, 'config_translation_info'); - $this->setCacheBackend($cache_backend, $language_manager, 'config_translation_info'); + $this->alterInfo($this->container->get('module_handler'), 'config_translation_info'); + $this->setCacheBackend($this->container->get('cache.cache'), $this->container->get('language_manager'), 'config_translation_info'); } /** @@ -151,14 +162,36 @@ class ConfigMapperManager extends DefaultPluginManager { foreach ($routes as $route_name => $route) { /** @var \Symfony\Component\Routing\Route $route */ - // @todo The route defaults are not set yet. - if (!$route->hasDefault('_form') || !$route->hasDefault('config_names')) { + if (!$route->hasDefault('_form')) { + continue; + } + + $form_definition = $route->getDefault('_form'); + // See \Drupal\Core\Controller\HtmlFormController::getFormObject() + // If this is a class, instantiate it. + if (class_exists($form_definition)) { + $interfaces = class_implements($form_definition); + $implements = in_array('Drupal\Core\DependencyInjection\ContainerInjectionInterface', class_implements($form_definition)); + if (in_array('Drupal\Core\DependencyInjection\ContainerInjectionInterface', class_implements($form_definition))) { + $form = $form_definition::create($this->container); + } + else { + $form = new $form_definition(); + } + } + // Otherwise, it is a service. + else { + $form = $this->container->get($form_definition); + } + + if (!($form instanceof ConfigFormInterface)) { continue; } - // Second we find whether the configuration contains translatable keys + $config_names = $form->getConfigNames(); + + // Check whether the configuration contains translatable keys // by checking the configuration schema. - $config_names = $route->getDefault('config_names'); $config_names = array_filter($config_names, 'config_translation_has_translatable'); if (empty($config_names)) { @@ -168,36 +201,22 @@ class ConfigMapperManager extends DefaultPluginManager { // \Drupal\Core\Controller\TitleResolver requires a request, so we // cannot use it to generate the title. We check the static '_title' as // a best effort. - + // Should there be a FormInterface::getTitle()? if ($route->hasDefault('_title')) { $title = $route->getDefault('_title'); } else { - $title = $this->t('Configuration form for @config_names', array('@config_names' => implode(', ', $config_names))); + $title = $this->t('Translation form for @config_names', array('@config_names' => implode(', ', $config_names))); } - // It would seem natural to use the form ID as part of the mapper ID. - // This, however, would need an instantiated form object to call - // getFormId() on. Having an instantiated form object we could skip - // storing the config_names on the route and could call getConfigNames() - // directly. In order to instantiate a form object we would have to - // duplicate large parts of \Drupal\Core\Controller\HtmlFormController. - // I see following solutions to this problem: - // 1. Do not use the form ID as part of the mapper ID. The only sensible - // other thing I can think of is the route name. (This is the - // approach in the current patch.) - // 2. Duplicate large parts of - // \Drupal\Core\Controller\HtmlFormController, instantiate the form - // object and don't store the config names on the route. - // 3. Same as 2., but factor the necessary code out of - // \Drupal\Core\Controller\HtmlFormController instead of duplicating - // it. It is not clear how and in which scope this is possible. - $definitions['form_route.' . $route_name] = array( + + $definitions['form_route.' . $form->getFormId()] = array( 'class' => '\Drupal\config_translation\ConfigNamesMapper', 'base_path' => $route->getPath(), 'title' => $title, 'names' => $config_names, ); } + return $definitions; } @@ -209,4 +228,5 @@ class ConfigMapperManager extends DefaultPluginManager { protected function t($string, array $args = array(), array $options = array()) { return $this->translationManager->translate($string, $args, $options); } + } diff --git a/lib/Drupal/config_translation/ConfigNamesMapper.php b/lib/Drupal/config_translation/ConfigNamesMapper.php index b974de6..796c1bf 100644 --- a/lib/Drupal/config_translation/ConfigNamesMapper.php +++ b/lib/Drupal/config_translation/ConfigNamesMapper.php @@ -284,11 +284,11 @@ class ConfigNamesMapper extends DependencySerialization implements ConfigMapperI $name = $this->getRouteName(); return array( $name => new Route($path . '/translate', array( - '_controller' => '\Drupal\config_translation\Controller\ConfigTranslationController::itemPage', - 'mapper' => $this, - ),array( + '_controller' => '\Drupal\config_translation\Controller\ConfigTranslationController::itemPage', + 'mapper' => $this, + ), array( '_config_translation_config_name_access' => 'TRUE', - )) + )), ); }