LanguageNegotiationSession.php 5.2 KB
Newer Older
1
2
3
4
<?php

namespace Drupal\language\Plugin\LanguageNegotiation;

5
use Drupal\Core\Language\LanguageInterface;
6
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
7
use Drupal\Core\Render\BubbleableMetadata;
8
use Drupal\Core\Url;
9
10
11
12
13
14
15
use Drupal\language\LanguageNegotiationMethodBase;
use Drupal\language\LanguageSwitcherInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Identify language from a request/session parameter.
 *
16
 * @LanguageNegotiation(
17
18
19
20
 *   id = Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationSession::METHOD_ID,
 *   weight = -6,
 *   name = @Translation("Session"),
 *   description = @Translation("Language from a request/session parameter."),
21
 *   config_route_name = "language.negotiation_session"
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
 * )
 */
class LanguageNegotiationSession extends LanguageNegotiationMethodBase implements OutboundPathProcessorInterface, LanguageSwitcherInterface {

  /**
   * Flag used to determine whether query rewriting is active.
   *
   * @var bool
   */
  protected $queryRewrite;

  /**
   * The query parameter name to rewrite.
   *
   * @var string
   */
  protected $queryParam;

  /**
   * The query parameter value to be set.
   *
   * @var string
   */
  protected $queryValue;

  /**
   * The language negotiation method id.
   */
  const METHOD_ID = 'language-session';

  /**
   * {@inheritdoc}
   */
  public function getLangcode(Request $request = NULL) {
    $config = $this->config->get('language.negotiation')->get('session');
    $param = $config['parameter'];
    $langcode = $request && $request->query->get($param) ? $request->query->get($param) : NULL;
    if (!$langcode && isset($_SESSION[$param])) {
      $langcode = $_SESSION[$param];
    }
    return $langcode;
  }

  /**
   * {@inheritdoc}
   */
68
  public function persist(LanguageInterface $language) {
69
70
    // We need to update the session parameter with the request value only if we
    // have an authenticated user.
71
    $langcode = $language->getId();
72
73
74
75
76
77
78
79
80
81
82
83
    if ($langcode && $this->languageManager) {
      $languages = $this->languageManager->getLanguages();
      if ($this->currentUser->isAuthenticated() && isset($languages[$langcode])) {
        $config = $this->config->get('language.negotiation')->get('session');
        $_SESSION[$config['parameter']] = $langcode;
      }
    }
  }

  /**
   * {@inheritdoc}
   */
84
  public function processOutbound($path, &$options = [], Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
    if ($request) {
      // The following values are not supposed to change during a single page
      // request processing.
      if (!isset($this->queryRewrite)) {
        if ($this->currentUser->isAnonymous()) {
          $languages = $this->languageManager->getLanguages();
          $config = $this->config->get('language.negotiation')->get('session');
          $this->queryParam = $config['parameter'];
          $this->queryValue = $request->query->has($this->queryParam) ? $request->query->get($this->queryParam) : NULL;
          $this->queryRewrite = isset($languages[$this->queryValue]);
        }
        else {
          $this->queryRewrite = FALSE;
        }
      }

      // If the user is anonymous, the user language negotiation method is
      // enabled, and the corresponding option has been set, we must preserve
      // any explicit user language preference even with cookies disabled.
      if ($this->queryRewrite) {
        if (!isset($options['query'][$this->queryParam])) {
          $options['query'][$this->queryParam] = $this->queryValue;
        }
108
        if ($bubbleable_metadata) {
109
110
          // Cached URLs that have been processed by this outbound path
          // processor must be:
111
          $bubbleable_metadata
112
113
114
115
116
117
            // - invalidated when the language negotiation config changes, since
            //   another query parameter may be used to determine the language.
            ->addCacheTags($this->config->get('language.negotiation')->getCacheTags())
            // - varied by the configured query parameter.
            ->addCacheContexts(['url.query_args:' . $this->queryParam]);
        }
118
119
120
121
122
123
124
125
      }
    }
    return $path;
  }

  /**
   * {@inheritdoc}
   */
126
  public function getLanguageSwitchLinks(Request $request, $type, Url $url) {
127
    $links = [];
128
129
    $config = $this->config->get('language.negotiation')->get('session');
    $param = $config['parameter'];
130
    $language_query = isset($_SESSION[$param]) ? $_SESSION[$param] : $this->languageManager->getCurrentLanguage($type)->getId();
larowlan's avatar
larowlan committed
131
    $query = $request->query->all();
132

133
    foreach ($this->languageManager->getNativeLanguages() as $language) {
134
      $langcode = $language->getId();
135
      $links[$langcode] = [
136
137
138
        // We need to clone the $url object to avoid using the same one for all
        // links. When the links are rendered, options are set on the $url
        // object, so if we use the same one, they would be set for all links.
139
        'url' => clone $url,
140
        'title' => $language->getName(),
141
        'attributes' => ['class' => ['language-link']],
142
        'query' => $query,
143
      ];
144
145
146
147
148
149
150
151
152
153
154
155
      if ($language_query != $langcode) {
        $links[$langcode]['query'][$param] = $langcode;
      }
      else {
        $links[$langcode]['attributes']['class'][] = 'session-active';
      }
    }

    return $links;
  }

}