LanguageNegotiator   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 8
dl 0
loc 110
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getLanguage() 0 4 1
A __construct() 0 4 1
A usePath() 0 6 1
D __invoke() 0 46 10
1
<?php
2
3
namespace Psr7Middlewares\Middleware;
4
5
use Psr7Middlewares\Utils;
6
use Negotiation\LanguageNegotiator as Negotiator;
7
use Psr\Http\Message\ServerRequestInterface;
8
use Psr\Http\Message\ResponseInterface;
9
10
/**
11
 * Middleware returns the client preferred language.
12
 */
13
class LanguageNegotiator
14
{
15
    use Utils\NegotiateTrait;
16
    use Utils\RedirectTrait;
17
    use Utils\AttributeTrait;
18
19
    const KEY = 'LANGUAGE';
20
21
    /**
22
     * @var array Allowed languages
23
     */
24
    private $languages = [];
25
26
    /**
27
     * @var bool Use the path to detect the language
28
     */
29
    private $usePath = false;
30
31
    /**
32
     * Returns the language.
33
     *
34
     * @param ServerRequestInterface $request
35
     *
36
     * @return string|null
37
     */
38
    public static function getLanguage(ServerRequestInterface $request)
39
    {
40
        return self::getAttribute($request, self::KEY);
41
    }
42
43
    /**
44
     * Define de available languages.
45
     *
46
     * @param array $languages
47
     */
48
    public function __construct(array $languages)
49
    {
50
        $this->languages = $languages;
51
    }
52
53
    /**
54
     * Use the base path to detect the current language.
55
     *
56
     * @param bool $usePath
57
     *
58
     * @return self
59
     */
60
    public function usePath($usePath = true)
61
    {
62
        $this->usePath = $usePath;
63
64
        return $this;
65
    }
66
67
    /**
68
     * Execute the middleware.
69
     *
70
     * @param ServerRequestInterface $request
71
     * @param ResponseInterface      $response
72
     * @param callable               $next
73
     *
74
     * @return ResponseInterface
75
     */
76
    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
77
    {
78
        $language = null;
79
        $uri = $request->getUri();
80
81
        //Use path
82
        if ($this->usePath) {
83
            $path = ltrim($uri->getPath(), '/');
84
            $dirs = explode('/', $path, 2);
85
            $first = strtolower(array_shift($dirs));
86
87
            if (!empty($first) && in_array($first, $this->languages, true)) {
88
                $language = $first;
89
90
                //remove the language in the path
91
                $request = $request->withUri($uri->withPath('/'.array_shift($dirs)));
92
            }
93
        }
94
95
        //Use http headers
96
        if ($language === null) {
97
            $language = $this->negotiateHeader($request->getHeaderLine('Accept-Language'), new Negotiator(), $this->languages);
98
99
            if (empty($language)) {
100
                $language = isset($this->languages[0]) ? $this->languages[0] : '';
101
            }
102
103
            //Redirect to a path with the language
104
            if ($this->redirectStatus !== false && $this->usePath) {
105
                $path = Utils\Helpers::joinPath($language, $uri->getPath());
106
107
                return $this->getRedirectResponse($request, $uri->withPath($path), $response);
108
            }
109
        }
110
111
        $response = $next(
112
            self::setAttribute($request, self::KEY, $language),
113
            $response->withHeader('Content-Language', $language)
114
        );
115
116
        if (!$response->hasHeader('Content-Language')) {
117
            $response = $response->withHeader('Content-Language', $language);
118
        }
119
120
        return $response;
121
    }
122
}
123