Test Failed
Push — master ( acaa8d...dcec5f )
by Fran
02:31
created

Cache::checkAdminSite()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
1
<?php
2
namespace PSFS\base;
3
4
use PSFS\base\config\Config;
5
use PSFS\base\exception\ConfigException;
6
use PSFS\base\exception\GeneratorException;
7
use PSFS\base\types\Api;
8
use PSFS\base\types\helpers\FileHelper;
9
use PSFS\base\types\helpers\GeneratorHelper;
10
use PSFS\base\types\helpers\Inspector;
11
use PSFS\base\types\traits\SingletonTrait;
12
13
/**
14
 * Class Cache
15
 * @package PSFS\base
16
 * Gestión de los ficheros de cache
17
 */
18
class Cache
19
{
20
    /**
21
     * @var \Memcache
22
     */
23
    protected $memcache = null;
24
25
    const JSON = 1;
26
    const TEXT = 2;
27
    const GZIP = 3;
28
    const JSONGZ = 4;
29
    const MEMCACHE = 5;
30
31
    const CACHE_SESSION_VAR = '__CACHE__';
32
33
    use SingletonTrait;
34
35
    public function __construct()
36
    {
37
        $this->setLoaded(true);
38
    }
39
40
    /**
41
     * @return bool
42
     */
43
    public static function canUseMemcache()
44
    {
45
        return Config::getParam('psfs.memcache', false) && !Config::getParam('debug') && class_exists('Memcached');
46
    }
47
48
    /**
49
     * @param string $data
50
     * @param string $path
51
     * @throws GeneratorException
52
     * @throws ConfigException
53
     */
54
    private function saveTextToFile($data, $path)
55
    {
56
        GeneratorHelper::createDir(dirname($path));
57
        if (false === FileHelper::writeFile($path, $data)) {
0 ignored issues
show
introduced by
The condition false === PSFS\base\type...writeFile($path, $data) is always false.
Loading history...
58
            throw new ConfigException(t('No se tienen los permisos suficientes para escribir en el fichero ') . $path);
59
        }
60
    }
61
62
    /**
63
     * @param string $path
64
     * @param int $transform
65
     * @param boolean $absolute
66
     * @return mixed
67
     */
68
    public function getDataFromFile($path, $transform = Cache::TEXT, $absolute = false)
69
    {
70
        Inspector::stats('[Cache] Gathering data from cache', Inspector::SCOPE_DEBUG);
71
        $data = null;
72
        $absolutePath = $absolute ? $path : CACHE_DIR . DIRECTORY_SEPARATOR . $path;
73
        if (file_exists($absolutePath)) {
74
            $data = FileHelper::readFile($absolutePath);
75
        }
76
        return self::extractDataWithFormat($data, $transform);
77
    }
78
79
    /**
80
     * @param string $path
81
     * @param int $expires
82
     * @param boolean $absolute
83
     * @return bool
84
     */
85
    private function hasExpiredCache($path, $expires = 300, $absolute = false)
86
    {
87
        Inspector::stats('[Cache] Checking expiration', Inspector::SCOPE_DEBUG);
88
        $absolutePath = ($absolute) ? $path : CACHE_DIR . DIRECTORY_SEPARATOR . $path;
89
        $lasModificationDate = filemtime($absolutePath);
90
        return ($lasModificationDate + $expires <= time());
91
    }
92
93
    /**
94
     * @param mixed $data
95
     * @param int $transform
96
     * @return mixed
97
     */
98
    public static function extractDataWithFormat($data = null, $transform = Cache::TEXT)
99
    {
100
        Inspector::stats('[Cache] Extracting data from cache', Inspector::SCOPE_DEBUG);
101
        switch ($transform) {
102
            case self::JSON:
103
                $data = json_decode($data ?: '', true);
104
                break;
105
            case self::JSONGZ:
106
                $data = self::extractDataWithFormat($data, self::GZIP);
107
                $data = self::extractDataWithFormat($data, self::JSON);
108
                break;
109
            case self::GZIP:
110
                if (null !== $data && function_exists('gzuncompress')) {
111
                    $data = @gzuncompress($data ?: '');
112
                }
113
                break;
114
        }
115
        return $data;
116
    }
117
118
    /**
119
     * @param string $data
120
     * @param int $transform
121
     * @return string
122
     */
123
    public static function transformData($data, $transform = Cache::TEXT)
124
    {
125
        Logger::log('Transform data in cache', LOG_DEBUG);
126
        switch ($transform) {
127
            case self::JSON:
128
                $data = json_encode($data, JSON_PRETTY_PRINT);
129
                break;
130
            case self::JSONGZ:
131
                $data = self::transformData($data, self::JSON);
132
                $data = self::transformData($data, self::GZIP);
133
                break;
134
            case self::GZIP:
135
                if (function_exists('gzcompress')) {
136
                    $data = gzcompress($data ?: '');
137
                }
138
                break;
139
        }
140
        return $data;
141
    }
142
143
    /**
144
     * @param string $path
145
     * @param mixed $data
146
     * @param int $transform
147
     * @param bool $absolute
148
     * @throws GeneratorException
149
     * @throws ConfigException
150
     */
151
    public function storeData($path, $data, $transform = Cache::TEXT, $absolute = false)
152
    {
153
        Inspector::stats('[Cache] Store data in cache', Inspector::SCOPE_DEBUG);
154
        $data = self::transformData($data, $transform);
155
        $absolutePath = $absolute ? $path : CACHE_DIR . DIRECTORY_SEPARATOR . $path;
156
        $this->saveTextToFile($data, $absolutePath);
157
    }
158
159
    /**
160
     * @param string $path
161
     * @param int $expires
162
     * @param callable $function
163
     * @param int $transform
164
     * @return mixed|null
165
     * @throws GeneratorException
166
     * @throws ConfigException
167
     */
168
    public function readFromCache($path, $expires = 300, $function = null, $transform = Cache::TEXT)
169
    {
170
        $data = null;
171
        Inspector::stats('[Cache] Reading data from cache: ' . json_encode(['path' => $path]), Inspector::SCOPE_DEBUG);
172
        if (file_exists(CACHE_DIR . DIRECTORY_SEPARATOR . $path)) {
173
            if (is_callable($function) && $this->hasExpiredCache($path, $expires)) {
174
                $data = $function();
175
                $this->storeData($path, $data, $transform);
176
            } else {
177
                $data = $this->getDataFromFile($path, $transform);
178
            }
179
        }
180
        return $data;
181
    }
182
183
    /**
184
     * @return bool
185
     */
186
    private static function checkAdminSite()
187
    {
188
        return Security::getInstance()->canAccessRestrictedAdmin();
189
    }
190
191
    /**
192
     * @return integer|boolean
193
     */
194
    public static function needCache()
195
    {
196
        $needCache = false;
197
        Logger::log('Checking cache requirements');
198
        if (!self::checkAdminSite() && !Config::getParam('debug') && Config::getParam('cache.data.enable', false)) {
199
            $action = Security::getInstance()->getSessionKey(self::CACHE_SESSION_VAR);
200
            Logger::log('Gathering cache params from Session', LOG_DEBUG, $action);
201
            if (null !== $action && array_key_exists('cache', $action) && $action['cache'] > 0) {
202
                $needCache = $action['cache'];
203
            }
204
        }
205
        return $needCache;
206
    }
207
208
    /**
209
     * @return array
210
     */
211
    public function getRequestCacheHash()
212
    {
213
        $hashPath = null;
214
        $filename = null;
215
        $action = Security::getInstance()->getSessionKey(self::CACHE_SESSION_VAR);
216
        Inspector::stats('[Cache] Gathering cache hash for request', Inspector::SCOPE_DEBUG);
217
        if (null !== $action && $action['cache'] > 0) {
218
            $query = $action['params'];
219
            $query[Api::HEADER_API_LANG] = Request::header(Api::HEADER_API_LANG, 'es');
220
            $filename = FileHelper::generateHashFilename($action['http'], $action['slug'], $query);
221
            $hashPath = FileHelper::generateCachePath($action, $query);
222
            Inspector::stats('[Cache] Cache file calculated: ' . json_encode(['file' => $filename, 'hash' => $hashPath]), Inspector::SCOPE_DEBUG);
223
            Logger::log('Cache file calculated', LOG_DEBUG, ['file' => $filename, 'hash' => $hashPath]);
224
        }
225
        return [$hashPath, $filename];
226
    }
227
228
    public function flushCache() {
229
        if(Config::getParam('cache.data.enable', false)) {
230
            Inspector::stats('[Cache] Flushing cache', Inspector::SCOPE_DEBUG);
231
            $action = Security::getInstance()->getSessionKey(self::CACHE_SESSION_VAR);
232
            if(is_array($action)) {
233
                $hashPath = FileHelper::generateCachePath($action, $action['params']) . '..' . DIRECTORY_SEPARATOR . ' .. ' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR;
234
                if(!file_exists($hashPath)) {
235
                    $hashPath = CACHE_DIR . DIRECTORY_SEPARATOR . $hashPath;
236
                }
237
                FileHelper::deleteDir($hashPath);
238
            }
239
        }
240
    }
241
}
242