Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
40.91% covered (danger)
40.91%
9 / 22
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
LocaleDetectorFactory
40.91% covered (danger)
40.91%
9 / 22
50.00% covered (danger)
50.00%
1 / 2
13.43
0.00% covered (danger)
0.00%
0 / 1
 __invoke
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
12
 getStrategies
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3/**
4 * Locale Detector Delegator Factory
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2018,
9 *               Leipzig University Library <info@ub.uni-leipzig.de> 2018.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2,
13 * as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23 *
24 * @category VuFind
25 * @package  I18n\Locale
26 * @author   Demian Katz <demian.katz@villanova.edu>
27 * @author   Sebastian Kehr <kehr@ub.uni-leipzig.de>
28 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
29 * @link     https://vufind.org Main Site
30 */
31
32namespace VuFind\I18n\Locale;
33
34use Laminas\EventManager\EventInterface;
35use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
36use Laminas\ServiceManager\Exception\ServiceNotFoundException;
37use Laminas\ServiceManager\Factory\DelegatorFactoryInterface;
38use Psr\Container\ContainerExceptionInterface as ContainerException;
39use Psr\Container\ContainerInterface;
40use SlmLocale\LocaleEvent;
41use SlmLocale\Strategy\QueryStrategy;
42use VuFind\Cookie\CookieManager;
43
44use function call_user_func;
45
46/**
47 * Locale Detector Delegator Factory
48 *
49 * @category VuFind
50 * @package  I18n\Locale
51 * @author   Demian Katz <demian.katz@villanova.edu>
52 * @author   Sebastian Kehr <kehr@ub.uni-leipzig.de>
53 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
54 * @link     https://vufind.org Main Site
55 */
56class LocaleDetectorFactory implements DelegatorFactoryInterface
57{
58    /**
59     * A factory that creates delegates of a given service
60     *
61     * @param ContainerInterface $container Container
62     * @param string             $name      Service name
63     * @param callable           $callback  Primary factory
64     * @param null|array         $options   Options
65     *
66     * @return object
67     * @throws ServiceNotFoundException if unable to resolve the service.
68     * @throws ServiceNotCreatedException if an exception is raised when
69     *     creating a service.
70     * @throws ContainerException&\Throwable if any other error occurs
71     */
72    public function __invoke(
73        ContainerInterface $container,
74        $name,
75        callable $callback,
76        array $options = null
77    ) {
78        $detector = call_user_func($callback);
79        $settings = $container->get(LocaleSettings::class);
80        $detector->setDefault($settings->getDefaultLocale());
81        $detector->setSupported(array_keys($settings->getEnabledLocales()));
82        // TODO: implement mappings in the future?
83        //$detector->setMappings($settings->getMappedLocales());
84
85        foreach ($this->getStrategies($settings) as $strategy) {
86            $detector->addStrategy($strategy);
87        }
88
89        $cookies = $container->get(CookieManager::class);
90        $detector->getEventManager()->attach(
91            LocaleEvent::EVENT_FOUND,
92            function (EventInterface $event) use ($cookies) {
93                $language = $event->getParam('locale');
94                if ($language !== $cookies->get('language')) {
95                    $cookies->set('language', $language);
96                }
97            }
98        );
99
100        return $detector;
101    }
102
103    /**
104     * Generator for retrieving strategies.
105     *
106     * @param ?LocaleSettings $settings Locale settings
107     *
108     * @return \Generator
109     */
110    protected function getStrategies(LocaleSettings $settings = null): \Generator
111    {
112        yield new LocaleDetectorParamStrategy();
113
114        $queryStrategy = new QueryStrategy();
115        $queryStrategy->setOptions(['query_key' => 'lng']);
116        yield $queryStrategy;
117
118        $cookieStrategy = new LocaleDetectorCookieStrategy();
119        $cookieStrategy->setCookieName('language');
120        yield $cookieStrategy;
121
122        // By default, we want to use the HTTP Accept header, so we'll add that
123        // strategy when no settings are provided, or when the settings tell us
124        // that browser language detection should be used.
125        if (!$settings || $settings->browserLanguageDetectionEnabled()) {
126            yield new \SlmLocale\Strategy\HttpAcceptLanguageStrategy();
127        }
128    }
129}