Passed
Push — devel-3.0 ( 950ad4...ce6650 )
by Rubén
04:08
created

Theme::saveIcons()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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