summaryrefslogtreecommitdiffstatshomepage
path: root/core/modules/language/src/EventSubscriber/ConfigSubscriber.php
blob: ff35d9b6d6a14f3dda2fdd280f844d121783e51d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<?php

namespace Drupal\language\EventSubscriber;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageDefault;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents;
use Drupal\language\ConfigurableLanguageManager;
use Drupal\language\HttpKernel\PathProcessorLanguage;
use Drupal\language\LanguageNegotiatorInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Deletes the container if default language has changed.
 */
class ConfigSubscriber implements EventSubscriberInterface {

  /**
   * The language manager.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * The default language.
   *
   * @var \Drupal\Core\Language\LanguageDefault
   */
  protected $languageDefault;

  /**
   * The configuration factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The language negotiator.
   *
   * @var \Drupal\language\LanguageNegotiatorInterface
   */
  protected $languageNegotiator;

  /**
   * The language path processor.
   *
   * @var \Drupal\language\HttpKernel\PathProcessorLanguage
   */
  protected $pathProcessorLanguage;

  /**
   * Constructs a new class object.
   *
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   The language manager.
   * @param \Drupal\Core\Language\LanguageDefault $language_default
   *   The default language.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The configuration factory.
   * @param \Drupal\language\LanguageNegotiatorInterface $language_negotiator
   *   The language negotiator.
   */
  public function __construct(LanguageManagerInterface $language_manager, LanguageDefault $language_default, ConfigFactoryInterface $config_factory, LanguageNegotiatorInterface $language_negotiator) {
    $this->languageManager = $language_manager;
    $this->languageDefault = $language_default;
    $this->configFactory = $config_factory;
    $this->languageNegotiator = $language_negotiator;
  }

  /**
   * Causes the container to be rebuilt on the next request.
   *
   * This event subscriber assumes that the new default langcode and old default
   * langcode are valid langcodes. If the schema definition of either
   * system.site:default_langcode or language.negotiation::url.prefixes changes
   * then this event must be changed to work with both the old and new schema
   * definition so this event is update safe.
   *
   * @param \Drupal\Core\Config\ConfigCrudEvent $event
   *   The configuration event.
   */
  public function onConfigSave(ConfigCrudEvent $event) {
    $saved_config = $event->getConfig();
    if ($saved_config->getName() == 'system.site' && $event->isChanged('default_langcode')) {
      $new_default_langcode = $saved_config->get('default_langcode');
      $default_language = $this->configFactory->get('language.entity.' . $new_default_langcode);
      // During an import the language might not exist yet.
      if (!$default_language->isNew()) {
        $this->languageDefault->set(new Language($default_language->get()));
        $this->languageManager->reset();

        // Directly update language negotiation settings instead of calling
        // language_negotiation_url_prefixes_update() to ensure that the code
        // obeys the hook_update_N() restrictions.
        $negotiation_config = $this->configFactory->getEditable('language.negotiation');
        $negotiation_changed = FALSE;
        $url_prefixes = $negotiation_config->get('url.prefixes');
        $old_default_langcode = $saved_config->getOriginal('default_langcode');
        if (empty($url_prefixes[$old_default_langcode])) {
          $negotiation_config->set('url.prefixes.' . $old_default_langcode, $old_default_langcode);
          $negotiation_changed = TRUE;
        }
        if (empty($url_prefixes[$new_default_langcode])) {
          $negotiation_config->set('url.prefixes.' . $new_default_langcode, '');
          $negotiation_changed = TRUE;
        }
        if ($negotiation_changed) {
          $negotiation_config->save(TRUE);
        }
      }
      // Trigger a container rebuild on the next request by invalidating it.
      ConfigurableLanguageManager::rebuildServices();
    }
    elseif ($saved_config->getName() == 'language.types' && $event->isChanged('negotiation')) {
      // If the negotiation configuration changed the language negotiator and
      // the language path processor have to be reset so that they regenerate
      // the method instances and also sort them accordingly to the new config.
      $this->languageNegotiator->reset();
      if (isset($this->pathProcessorLanguage)) {
        $this->pathProcessorLanguage->reset();
      }
    }
  }

  /**
   * Injects the language path processors on multilingual site configuration.
   *
   * @param \Drupal\language\HttpKernel\PathProcessorLanguage $path_processor_language
   *   The language path processor.
   */
  public function setPathProcessorLanguage(PathProcessorLanguage $path_processor_language) {
    $this->pathProcessorLanguage = $path_processor_language;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    $events[ConfigEvents::SAVE][] = ['onConfigSave', 0];
    return $events;
  }

}