Passed
Push — devel-3.0 ( 67d9a6...e0263f )
by Rubén
04:37
created

Theme::initialize()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * sysPass
4
 *
5
 * @author    nuxsmin
6
 * @link      https://syspass.org
7
 * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
8
 *
9
 * This file is part of sysPass.
10
 *
11
 * sysPass is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation, either version 3 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * sysPass is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 *  along with sysPass.  If not, see <http://www.gnu.org/licenses/>.
23
 */
24
25
namespace SP\Core\UI;
26
27
use SP\Bootstrap;
28
use SP\Config\Config;
29
use SP\Config\ConfigData;
30
use SP\Core\Context\ContextInterface;
31
use SP\Core\Context\SessionContext;
32
use SP\Core\Exceptions\InvalidClassException;
33
use SP\Storage\File\FileCache;
34
use SP\Storage\File\FileException;
35
36
defined('APP_ROOT') || die();
37
38
/**
39
 * Class Theme
40
 *
41
 * @package SP
42
 */
43
final class Theme implements ThemeInterface
44
{
45
    const ICONS_CACHE_FILE = CACHE_PATH . DIRECTORY_SEPARATOR . 'icons.cache';
46
    /**
47
     * Cache expire time
48
     */
49
    const CACHE_EXPIRE = 86400;
50
    /**
51
     * @var string
52
     */
53
    private $themeUri = '';
54
    /**
55
     * @var string
56
     */
57
    private $themePath = '';
58
    /**
59
     * @var string
60
     */
61
    private $themePathFull = '';
62
    /**
63
     * @var string
64
     */
65
    private $themeName = '';
66
    /**
67
     * @var string
68
     */
69
    private $viewsPath = '';
70
    /**
71
     * @var ThemeIcons
72
     */
73
    private $icons;
74
    /**
75
     * @var ConfigData
76
     */
77
    private $configData;
78
    /**
79
     * @var SessionContext
80
     */
81
    private $context;
82
    /**
83
     * @var string
84
     */
85
    private $module;
86
    /**
87
     * @var FileCache
88
     */
89
    private $fileCache;
90
91
    /**
92
     * Theme constructor.
93
     *
94
     * @param string           $module
95
     * @param Config           $config
96
     * @param ContextInterface $context
97
     * @param FileCache        $fileCache
98
     */
99
    public function __construct($module, Config $config, ContextInterface $context, FileCache $fileCache)
100
    {
101
        $this->configData = $config->getConfigData();
102
        $this->context = $context;
0 ignored issues
show
Documentation Bug introduced by
$context is of type SP\Core\Context\ContextInterface, but the property $context was declared to be of type SP\Core\Context\SessionContext. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
103
        $this->fileCache = $fileCache;
104
        $this->module = $module;
105
    }
106
107
    /**
108
     * Inicializar el tema visual a utilizar
109
     *
110
     * @param bool $force Forzar la detección del tema para los inicios de sesión
111
     *
112
     * @return void
113
     * @throws InvalidClassException
114
     */
115
    public function initTheme($force = false)
116
    {
117
        if (is_dir(VIEW_PATH)) {
118
            if (empty($this->themeName) || $force === true) {
119
                $this->themeName = $this->getUserTheme() ?: $this->getGlobalTheme();
120
            }
121
122
            $this->themeUri = Bootstrap::$WEBURI . '/app/modules/' . $this->module . 'themes' . $this->themeName;
123
            $this->themePath = str_replace(APP_ROOT, '', VIEW_PATH) . DIRECTORY_SEPARATOR . $this->themeName;
124
            $this->themePathFull = VIEW_PATH . DIRECTORY_SEPARATOR . $this->themeName;
125
            $this->viewsPath = $this->themePathFull . DIRECTORY_SEPARATOR . 'views';
126
127
            $this->initIcons();
128
        }
129
    }
130
131
    /**
132
     * Obtener el tema visual del usuario
133
     *
134
     * @return string
135
     */
136
    protected function getUserTheme()
137
    {
138
        return $this->context->isLoggedIn() ? $this->context->getUserData()->getPreferences()->getTheme() : null;
139
    }
140
141
    /**
142
     * Devolver el tema visual de sysPass desde la configuración
143
     */
144
    protected function getGlobalTheme()
145
    {
146
        return $this->configData->getSiteTheme();
147
    }
148
149
    /**
150
     * Inicializar los iconos del tema actual
151
     *
152
     * @return ThemeIcons
153
     * @throws InvalidClassException
154
     */
155
    private function initIcons()
156
    {
157
        try {
158
            if ($this->context->getAppStatus() !== SessionContext::APP_STATUS_RELOADED
159
                && !$this->fileCache->isExpired(self::ICONS_CACHE_FILE, self::CACHE_EXPIRE)
160
            ) {
161
                $this->icons = $this->fileCache->load(self::ICONS_CACHE_FILE);
162
163
                logger('Loaded icons cache', 'INFO');
164
165
                return $this->icons;
166
            }
167
        } catch (FileException $e) {
168
            processException($e);
169
        }
170
171
        $this->saveIcons();
172
173
        return $this->icons;
174
    }
175
176
    /**
177
     * @throws InvalidClassException
178
     */
179
    private function saveIcons()
180
    {
181
        $iconsClass = $this->themePathFull . DIRECTORY_SEPARATOR . 'inc' . DIRECTORY_SEPARATOR . 'Icons.php';
182
183
        if (file_exists($iconsClass)) {
184
            if (!($this->icons = require $iconsClass) instanceof ThemeIcons) {
185
                throw new InvalidClassException(__u('Clase no válida para iconos'));
186
            }
187
188
            try {
189
                $this->fileCache->save(self::ICONS_CACHE_FILE, $this->icons);
190
191
                logger('Saved icons cache', 'INFO');
192
            } catch (FileException $e) {
193
                processException($e);
194
            }
195
        }
196
    }
197
198
    /**
199
     * Obtener los temas disponibles desde el directorio de temas
200
     *
201
     * @return array Con la información del tema
202
     */
203
    public function getThemesAvailable()
204
    {
205
        $themesAvailable = [];
206
207
        $themesDirs = dir(VIEW_PATH);
208
209
        while (false !== ($themeDir = $themesDirs->read())) {
210
            if ($themeDir !== '.' && $themeDir !== '..') {
211
                $themeFile = VIEW_PATH . DIRECTORY_SEPARATOR . $themeDir . DIRECTORY_SEPARATOR . 'index.php';
212
213
                if (file_exists($themeFile)) {
214
                    $themeInfo = require $themeFile;
215
216
                    $themesAvailable[$themeDir] = $themeInfo['name'];
217
                }
218
            }
219
        }
220
221
        $themesDirs->close();
222
223
        return $themesAvailable;
224
    }
225
226
    /**
227
     * Obtener la información del tema desde el archivo de información
228
     *
229
     * @return array (
230
     *          'name' => string
231
     *          'creator' => string
232
     *          'version' => string
233
     *          'js' => array
234
     *          'css' => array
235
     *  )
236
     */
237
    public function getThemeInfo()
238
    {
239
        $themeFile = $this->themePathFull . DIRECTORY_SEPARATOR . 'index.php';
240
241
        if (file_exists($themeFile)) {
242
            return include $themeFile;
243
        }
244
245
        return [];
246
    }
247
248
    /**
249
     * @return string
250
     */
251
    public function getThemeUri()
252
    {
253
        return $this->themeUri;
254
    }
255
256
    /**
257
     * @return string
258
     */
259
    public function getThemePath()
260
    {
261
        return $this->themePath;
262
    }
263
264
    /**
265
     * @return string
266
     */
267
    public function getThemeName()
268
    {
269
        return $this->themeName;
270
    }
271
272
    /**
273
     * @return ThemeIcons
274
     */
275
    public function getIcons()
276
    {
277
        return clone $this->icons;
278
    }
279
280
    /**
281
     * @return string
282
     */
283
    public function getViewsPath()
284
    {
285
        return $this->viewsPath;
286
    }
287
}