Cache   B
last analyzed

Complexity

Total Complexity 50

Size/Duplication

Total Lines 231
Duplicated Lines 0 %

Test Coverage

Coverage 96.7%

Importance

Changes 3
Bugs 1 Features 0
Metric Value
eloc 96
dl 0
loc 231
ccs 88
cts 91
cp 0.967
rs 8.4
c 3
b 1
f 0
wmc 50

14 Methods

Rating   Name   Duplication   Size   Complexity  
A getRequestCacheHash() 0 15 3
B needCache() 0 12 7
A transformData() 0 18 6
A getDataFromFile() 0 9 3
A canUseMemcache() 0 3 3
A canUseRedis() 0 3 3
A flushCache() 0 11 4
A hasExpiredCache() 0 6 2
A readFromCache() 0 13 5
B extractDataWithFormat() 0 18 8
A storeData() 0 6 2
A saveTextToFile() 0 5 2
A checkAdminSite() 0 3 1
A __construct() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Cache often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Cache, and based on these observations, apply Extract Interface, too.

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