Passed
Push — 3.0 ( 5a5495...1e51f1 )
by Rubén
03:32
created

Config::isCacheExpired()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 6
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\Config;
26
27
use Psr\Container\ContainerInterface;
28
use ReflectionObject;
29
use SP\Core\Context\ContextInterface;
30
use SP\Core\Exceptions\ConfigException;
31
use SP\Services\Config\ConfigBackupService;
32
use SP\Storage\File\FileCacheInterface;
33
use SP\Storage\File\FileException;
34
use SP\Storage\File\XmlFileStorageInterface;
35
use SP\Util\PasswordUtil;
36
37
defined('APP_ROOT') || die();
38
39
/**
40
 * Esta clase es responsable de leer y escribir la configuración del archivo config.php
41
 */
42
final class Config
43
{
44
    /**
45
     * Cache file name
46
     */
47
    const CONFIG_CACHE_FILE = CACHE_PATH . DIRECTORY_SEPARATOR . 'config.cache';
48
    /**
49
     * @var int
50
     */
51
    private static $timeUpdated;
52
    /**
53
     * @var ContextInterface
54
     */
55
    private $context;
56
    /**
57
     * @var bool
58
     */
59
    private $configLoaded = false;
60
    /**
61
     * @var ConfigData
62
     */
63
    private $configData;
64
    /**
65
     * @var XmlFileStorageInterface
66
     */
67
    private $fileStorage;
68
    /**
69
     * @var FileCacheInterface
70
     */
71
    private $fileCache;
72
    /**
73
     * @var ContainerInterface
74
     */
75
    private $dic;
76
77
    /**
78
     * Config constructor.
79
     *
80
     * @param XmlFileStorageInterface $fileStorage
81
     * @param FileCacheInterface      $fileCache
82
     * @param ContainerInterface      $dic
83
     *
84
     * @throws ConfigException
85
     */
86
    public function __construct(XmlFileStorageInterface $fileStorage, FileCacheInterface $fileCache, ContainerInterface $dic)
87
    {
88
        $this->fileCache = $fileCache;
89
        $this->fileStorage = $fileStorage;
90
        $this->context = $dic->get(ContextInterface::class);
91
        $this->dic = $dic;
92
93
        $this->initialize();
94
    }
95
96
    /**
97
     * @throws ConfigException
98
     */
99
    private function initialize()
100
    {
101
        if (!$this->configLoaded) {
102
            try {
103
                if ($this->fileCache->exists()
104
                    && !$this->isCacheExpired()
105
                ) {
106
                    $this->configData = $this->fileCache->load();
107
108
                    logger('Config cache loaded');
109
                } else {
110
                    if (file_exists($this->fileStorage->getFileHandler()->getFile())) {
111
                        $this->configData = $this->loadConfigFromFile();
112
                        $this->fileCache->save($this->configData);
113
                    } else {
114
                        $this->saveConfig(new ConfigData(), false);
115
                    }
116
117
                    logger('Config loaded');
118
                }
119
120
                self::$timeUpdated = $this->configData->getConfigDate();
121
                $this->configLoaded = true;
122
            } catch (\Exception $e) {
123
                processException($e);
124
125
                throw new ConfigException($e->getMessage(),
126
                    ConfigException::CRITICAL,
127
                    null,
128
                    $e->getCode(),
129
                    $e);
130
            }
131
        }
132
    }
133
134
    /**
135
     * @return bool
136
     */
137
    private function isCacheExpired()
138
    {
139
        try {
140
            return $this->fileCache->isExpiredDate($this->fileStorage->getFileHandler()->getFileTime());
141
        } catch (FileException $e) {
142
            return true;
143
        }
144
    }
145
146
    /**
147
     * Cargar el archivo de configuración
148
     *
149
     * @return ConfigData
150
     * @throws FileException
151
     */
152
    public function loadConfigFromFile()
153
    {
154
        $configData = new ConfigData();
155
156
        // Mapear el array de elementos de configuración con las propiedades de la clase configData
157
        $items = $this->fileStorage->load('config')->getItems();
158
        $reflectionObject = new ReflectionObject($configData);
159
160
        foreach ($reflectionObject->getProperties() as $property) {
161
            $property->setAccessible(true);
162
163
            if (isset($items[$property->getName()])) {
164
                $property->setValue($configData, $items[$property->getName()]);
165
            }
166
167
            $property->setAccessible(false);
168
        }
169
170
        return $configData;
171
    }
172
173
    /**
174
     * Guardar la configuración
175
     *
176
     * @param ConfigData $configData
177
     * @param bool       $backup
178
     *
179
     * @return Config
180
     * @throws FileException
181
     */
182
    public function saveConfig(ConfigData $configData, $backup = true)
183
    {
184
        if ($backup) {
185
            $this->dic->get(ConfigBackupService::class)
186
                ->backup($configData);
187
        }
188
189
        $configData->setConfigDate(time());
190
        $configData->setConfigSaver($this->context->getUserData()->getLogin());
191
        $configData->setConfigHash();
192
193
        $this->fileStorage->save($configData, 'config');
194
        $this->fileCache->save($configData);
195
196
        $this->configData = $configData;
197
198
        return $this;
199
    }
200
201
    /**
202
     * @return int
203
     */
204
    public static function getTimeUpdated()
205
    {
206
        return self::$timeUpdated;
207
    }
208
209
    /**
210
     * Commits a config data
211
     *
212
     * @param ConfigData $configData
213
     *
214
     * @return Config
215
     */
216
    public function updateConfig(ConfigData $configData)
217
    {
218
        $configData->setConfigDate(time());
219
        $configData->setConfigSaver($this->context->getUserData()->getLogin());
220
        $configData->setConfigHash();
221
222
        $this->configData = $configData;
223
224
        self::$timeUpdated = $configData->getConfigDate();
225
226
        return $this;
227
    }
228
229
    /**
230
     * Cargar la configuración desde el contexto
231
     *
232
     * @param bool $reload
233
     *
234
     * @return ConfigData
235
     */
236
    public function loadConfig($reload = false)
237
    {
238
        try {
239
            $configData = $this->fileCache->load();
240
241
            if ($reload === true
242
                || $configData === null
243
                || $this->isCacheExpired()
244
            ) {
245
                $this->configData = $this->loadConfigFromFile();
246
                $this->fileCache->save($this->configData);
247
248
                return $this->configData;
249
            }
250
251
            return $configData;
252
        } catch (FileException $e) {
253
            processException($e);
254
        }
255
256
        return $this->configData;
257
    }
258
259
    /**
260
     * @return ConfigData
261
     */
262
    public function getConfigData()
263
    {
264
        return clone $this->configData;
265
    }
266
267
    /**
268
     * @return Config
269
     * @throws FileException
270
     * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException
271
     */
272
    public function generateUpgradeKey()
273
    {
274
        if (empty($this->configData->getUpgradeKey())) {
275
            logger('Generating upgrade key');
276
277
            return $this->saveConfig($this->configData->setUpgradeKey(PasswordUtil::generateRandomBytes(16)), false);
278
        }
279
280
        return $this;
281
    }
282
}
283