Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
6.67% covered (danger)
6.67%
5 / 75
0.00% covered (danger)
0.00%
0 / 15
CRAP
0.00% covered (danger)
0.00%
0 / 1
ThemeServiceAbstract
6.67% covered (danger)
6.67%
5 / 75
0.00% covered (danger)
0.00%
0 / 15
1212.03
0.00% covered (danger)
0.00%
0 / 1
 getTheme
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 setTheme
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getFirstThemeIdByLanguage
38.46% covered (danger)
38.46%
5 / 13
0.00% covered (danger)
0.00%
0 / 1
10.83
 hasTheme
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 getThemeById
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 isSolarDesignEnabled
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 isQuickWinsDesignEnabled
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getThemeIdFromThemeDetailsProviders
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
42
 getUniqueId
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 isHeadless
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 getIsHeadlessFromThemeDetailsProviders
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 getThemeDetailsProviders
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 isTaoAsToolEnabled
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFeatureFlagChecker
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getContainer
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2017-2024 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
19 */
20
21namespace oat\tao\model\theme;
22
23use common_exception_InconsistentData;
24use oat\oatbox\service\ConfigurableService;
25use oat\tao\model\DynamicConfig\DynamicConfigProviderInterface;
26use oat\tao\model\featureFlag\FeatureFlagChecker;
27use oat\tao\model\featureFlag\FeatureFlagCheckerInterface;
28use Psr\Container\ContainerInterface;
29
30abstract class ThemeServiceAbstract extends ConfigurableService implements ThemeServiceInterface
31{
32    /**
33     * @inheritdoc
34     *
35     * @throws common_exception_InconsistentData
36     */
37    public function getTheme()
38    {
39        $themeId = $this->getThemeIdFromThemeDetailsProviders();
40        if (empty($themeId)) {
41            $themeId = $this->getCurrentThemeId();
42        }
43
44        return $this->getThemeById($themeId);
45    }
46
47    /**
48     * @inheritdoc
49     */
50    public function setTheme(Theme $theme, $protectAlreadyExistingThemes = true)
51    {
52        $this->addTheme($theme, $protectAlreadyExistingThemes);
53        $this->setCurrentTheme($theme->getId());
54    }
55
56    public function getFirstThemeIdByLanguage(string $language): ?string
57    {
58        foreach (array_keys($this->getOption(self::OPTION_AVAILABLE, [])) as $themeId) {
59            try {
60                $theme = $this->getThemeById($themeId);
61
62                if ($theme instanceof LanguageAwareTheme && $theme->supportsLanguage($language)) {
63                    return $themeId;
64                }
65            } catch (common_exception_InconsistentData $exception) {
66                $this->logWarning(
67                    sprintf(
68                        'Error while searching theme for language "%s": %s',
69                        $language,
70                        $exception->getMessage()
71                    )
72                );
73            }
74        }
75
76        return null;
77    }
78
79    /**
80     * @inheritdoc
81     */
82    public function hasTheme($themeId)
83    {
84        $themes = $this->getAllThemes();
85        if (array_key_exists($themeId, $themes)) {
86            return true;
87        }
88
89        foreach ($themes as $currentTheme) {
90            if ($currentTheme->getId() === $themeId) {
91                return true;
92            }
93        }
94
95        return false;
96    }
97
98    /**
99     * @inheritdoc
100     */
101    public function getThemeById($themeId)
102    {
103        $themes = $this->getAllThemes();
104        if (array_key_exists($themeId, $themes)) {
105            return $themes[$themeId];
106        }
107
108        foreach ($themes as $currentTheme) {
109            if ($currentTheme->getId() === $themeId) {
110                return $currentTheme;
111            }
112        }
113
114        throw new common_exception_InconsistentData('The requested theme does not exist. (' . $themeId . ')');
115    }
116
117    public function isSolarDesignEnabled(): bool
118    {
119        return $this->getFeatureFlagChecker()->isEnabled(
120            FeatureFlagCheckerInterface::FEATURE_FLAG_SOLAR_DESIGN_ENABLED
121        );
122    }
123
124    public function isQuickWinsDesignEnabled(): bool
125    {
126        return $this->getFeatureFlagChecker()->isEnabled(
127            FeatureFlagCheckerInterface::FEATURE_FLAG_QUICK_WINS_ENABLED
128        );
129    }
130
131    /**
132     * Returns the theme id provided by the themeDetailsProviders.
133     *
134     * @return string
135     */
136    protected function getThemeIdFromThemeDetailsProviders()
137    {
138        $providers = $this->getThemeDetailsProviders();
139        foreach ($providers as $provider) {
140            if ($provider instanceof ThemeDetailsProviderInterface) {
141                $themeId = $provider->getThemeId();
142                if (!empty($themeId) && $themeId !== ' ') {
143                    if ($this->hasTheme($themeId)) {
144                        return $themeId;
145                    }
146
147                    \common_Logger::i(
148                        'The requested theme ' . $themeId .
149                        ' requested by the ' . get_class($provider) . ' provider does not exist!'
150                    );
151                }
152            }
153        }
154
155        return '';
156    }
157
158    /**
159     * Returns the unique identifier.
160     *
161     * @param Theme $theme
162     *
163     * @return string
164     */
165    protected function getUniqueId(Theme $theme)
166    {
167        $baseId = $theme->getId();
168
169        $idNumber = 0;
170        while ($this->hasTheme($baseId . $idNumber)) {
171            $idNumber++;
172        }
173
174        return $baseId . $idNumber;
175    }
176
177    /**
178     * Tells if the page has to be headless: without header and footer.
179     *
180     * @return bool|mixed
181     */
182    public function isHeadless()
183    {
184        if ($this->hasOption(self::OPTION_HEADLESS_PAGE)) {
185            return $this->getOption(self::OPTION_HEADLESS_PAGE);
186        }
187
188        $isHeadless = $this->getIsHeadLessFromThemeDetailsProviders();
189        if (empty($isHeadless)) {
190            $isHeadless = false;
191        }
192
193        return $isHeadless;
194    }
195
196    /**
197     * Returns the isHeadless details provided by the themeDetailsProviders.
198     *
199     * @return bool|mixed
200     */
201    protected function getIsHeadlessFromThemeDetailsProviders()
202    {
203        $providers = $this->getThemeDetailsProviders();
204        foreach ($providers as $provider) {
205            if ($provider instanceof ThemeDetailsProviderInterface) {
206                $isHeadless = $provider->isHeadless();
207                if (!empty($isHeadless)) {
208                    return $isHeadless;
209                }
210            }
211        }
212
213        return false;
214    }
215
216    /**
217     * Returns the theme details providers.
218     *
219     * @todo: think about this concept, because this could be a service.
220     *
221     * @return array
222     */
223    protected function getThemeDetailsProviders()
224    {
225        if ($this->hasOption(static::OPTION_THEME_DETAILS_PROVIDERS)) {
226            return (array)$this->getOption(static::OPTION_THEME_DETAILS_PROVIDERS);
227        }
228
229        return [];
230    }
231
232    /**
233     * @deprecated
234     */
235    protected function isTaoAsToolEnabled(): bool
236    {
237        return false;
238    }
239
240    private function getFeatureFlagChecker(): FeatureFlagCheckerInterface
241    {
242        return $this->getContainer()->get(FeatureFlagChecker::class);
243    }
244
245    private function getContainer(): ContainerInterface
246    {
247        return $this->getServiceManager()->getContainer();
248    }
249}