Test Failed
Push — master ( ed25dd...eced50 )
by Fran
04:57 queued 01:39
created

Cache::canUseMemcache()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
crap 3
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\traits\SingletonTrait;
11
12
/**
13
 * Class Cache
14
 * @package PSFS\base
15
 * Gestión de los ficheros de cache
16
 */
17
class Cache
18
{
19
    /**
20
     * @var \Memcache
21
     */
22
    protected $memcache = null;
23
24
    const JSON = 1;
25
    const TEXT = 2;
26
    const GZIP = 3;
27
    const JSONGZ = 4;
28
    const MEMCACHE = 5;
29
30
    const CACHE_SESSION_VAR = '__CACHE__';
31
32
    use SingletonTrait;
33
34 3
    public function __construct()
35
    {
36 3
        $this->setLoaded(true);
37 3
    }
38
39
    /**
40
     * @return bool
41
     */
42 3
    public static function canUseMemcache()
43
    {
44 3
        return Config::getParam('psfs.memcache', false) && !Config::getParam('debug') && class_exists('Memcached');
45
    }
46
47
    /**
48
     * @param string $data
49
     * @param string $path
50
     * @throws GeneratorException
51
     * @throws ConfigException
52
     */
53 7 View Code Duplication
    private function saveTextToFile($data, $path)
54
    {
55 7
        GeneratorHelper::createDir(dirname($path));
56 7
        if (false === FileHelper::writeFile($path, $data)) {
57 1
            throw new ConfigException(_('No se tienen los permisos suficientes para escribir en el fichero ') . $path);
58
        }
59 6
    }
60
61
    /**
62
     * @param string $path
63
     * @param int $transform
64
     * @param boolean $absolute
65
     * @return mixed
66
     */
67 8
    public function getDataFromFile($path, $transform = Cache::TEXT, $absolute = false)
68
    {
69 8
        Logger::log('Gathering data from cache', LOG_DEBUG, ['path' => $path]);
70 8
        $data = null;
71 8
        $absolutePath = $absolute ? $path : CACHE_DIR . DIRECTORY_SEPARATOR . $path;
72 8
        if (file_exists($absolutePath)) {
73 5
            $data = FileHelper::readFile($absolutePath);
74
        }
75 8
        return self::extractDataWithFormat($data, $transform);
76
    }
77
78
    /**
79
     * @param string $path
80
     * @param int $expires
81
     * @param boolean $absolute
82
     * @return bool
83
     */
84 1
    private function hasExpiredCache($path, $expires = 300, $absolute = false)
85
    {
86 1
        Logger::log('Checking expiration', LOG_DEBUG, ['path' => $path]);
87 1
        $absolutePath = ($absolute) ? $path : CACHE_DIR . DIRECTORY_SEPARATOR . $path;
88 1
        $lasModificationDate = filemtime($absolutePath);
89 1
        return ($lasModificationDate + $expires <= time());
90
    }
91
92
    /**
93
     * @param string $data
0 ignored issues
show
Documentation introduced by
Should the type for parameter $data not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
94
     * @param int $transform
95
     * @return mixed
96
     */
97 8 View Code Duplication
    public static function extractDataWithFormat($data = null, $transform = Cache::TEXT)
98
    {
99 8
        Logger::log('Extracting data from cache');
100
        switch ($transform) {
101 8
            case self::JSON:
102 8
                $data = json_decode($data, true);
103 8
                break;
104 5
            case self::JSONGZ:
105 5
                $data = self::extractDataWithFormat($data, self::GZIP);
106 5
                $data = self::extractDataWithFormat($data, self::JSON);
107 5
                break;
108 5
            case self::GZIP:
109 5
                if (null !== $data && function_exists('gzuncompress')) {
110 2
                    $data = @gzuncompress($data ?: '');
111
                }
112 5
                break;
113
        }
114 8
        return $data;
115
    }
116
117
    /**
118
     * @param string $data
119
     * @param int $transform
120
     * @return string
121
     */
122 7 View Code Duplication
    public static function transformData($data, $transform = Cache::TEXT)
123
    {
124 7
        Logger::log('Transform data in cache', LOG_DEBUG);
125
        switch ($transform) {
126 7
            case self::JSON:
127 6
                $data = json_encode($data, JSON_PRETTY_PRINT);
128 6
                break;
129 4
            case self::JSONGZ:
130 2
                $data = self::transformData($data, self::JSON);
131 2
                $data = self::transformData($data, self::GZIP);
132 2
                break;
133 4
            case self::GZIP:
134 2
                if (function_exists('gzcompress')) {
135 2
                    $data = gzcompress($data ?: '');
136
                }
137 2
                break;
138
        }
139 7
        return $data;
140
    }
141
142
    /**
143
     * @param string $path
144
     * @param mixed $data
145
     * @param int $transform
146
     * @param bool $absolute
147
     * @throws GeneratorException
148
     * @throws ConfigException
149
     */
150 7
    public function storeData($path, $data, $transform = Cache::TEXT, $absolute = false)
151
    {
152 7
        Logger::log('Store data in cache', LOG_DEBUG, ['path' => $path]);
153 7
        $data = self::transformData($data, $transform);
154 7
        $absolutePath = $absolute ? $path : CACHE_DIR . DIRECTORY_SEPARATOR . $path;
155 7
        $this->saveTextToFile($data, $absolutePath);
156 6
    }
157
158
    /**
159
     * @param string $path
160
     * @param int $expires
161
     * @param null $function
162
     * @param int $transform
163
     * @return mixed|null
164
     * @throws GeneratorException
165
     * @throws ConfigException
166
     */
167 1
    public function readFromCache($path, $expires = 300, $function = null, $transform = Cache::TEXT)
168
    {
169 1
        $data = null;
170 1
        Logger::log('Reading data from cache', LOG_DEBUG, ['path' => $path]);
171 1
        if (file_exists(CACHE_DIR . DIRECTORY_SEPARATOR . $path)) {
172 1
            if (is_callable($function) && $this->hasExpiredCache($path, $expires)) {
173 1
                $data = $function();
174 1
                $this->storeData($path, $data, $transform, false, $expires);
0 ignored issues
show
Unused Code introduced by
The call to Cache::storeData() has too many arguments starting with $expires.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
175
            } else {
176 1
                $data = $this->getDataFromFile($path, $transform);
177
            }
178
        }
179 1
        return $data;
180
    }
181
182
    /**
183
     * @return bool
184
     */
185 1
    private static function checkAdminSite()
186
    {
187 1
        return Security::getInstance()->canAccessRestrictedAdmin();
188
    }
189
190
    /**
191
     * @return integer|boolean
192
     */
193 1
    public static function needCache()
194
    {
195 1
        $needCache = false;
196 1
        Logger::log('Checking cache requirements');
197 1
        if (!self::checkAdminSite() && !Config::getParam('debug') && Config::getParam('cache.data.enable', false)) {
198 1
            $action = Security::getInstance()->getSessionKey(self::CACHE_SESSION_VAR);
199 1
            Logger::log('Gathering cache params from Session', LOG_DEBUG, $action);
200 1
            if (null !== $action && array_key_exists('cache', $action) && $action['cache'] > 0) {
201 1
                $needCache = $action['cache'];
202
            }
203
        }
204 1
        return $needCache;
205
    }
206
207
    /**
208
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string|null>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
209
     */
210 2
    public function getRequestCacheHash()
211
    {
212 2
        $hashPath = null;
213 2
        $filename = null;
214 2
        $action = Security::getInstance()->getSessionKey(self::CACHE_SESSION_VAR);
215 2
        Logger::log('Gathering cache hash for request', LOG_DEBUG, $action);
216 2
        if (null !== $action && $action['cache'] > 0) {
217 2
            $query = $action['params'];
218 2
            $query[Api::HEADER_API_LANG] = Request::header(Api::HEADER_API_LANG, 'es');
219 2
            $filename = FileHelper::generateHashFilename($action['http'], $action['slug'], $query);
220 2
            $hashPath = FileHelper::generateCachePath($action, $query);
221 2
            Logger::log('Cache file calculated', LOG_DEBUG, ['file' => $filename, 'hash' => $hashPath]);
222
        }
223 2
        return [$hashPath, $filename];
224
    }
225
226 1
    public function flushCache() {
227 1
        if(Config::getParam('cache.data.enable', false)) {
228 1
            Logger::log('Flushing cache', LOG_DEBUG);
229 1
            $action = Security::getInstance()->getSessionKey(self::CACHE_SESSION_VAR);
230 1
            if(is_array($action)) {
231 1
                $hashPath = FileHelper::generateCachePath($action, $action['params']) . '..' . DIRECTORY_SEPARATOR . ' .. ' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR;
232 1
                if(!file_exists($hashPath)) {
233 1
                    $hashPath = CACHE_DIR . DIRECTORY_SEPARATOR . $hashPath;
234
                }
235 1
                FileHelper::deleteDir($hashPath);
236
            }
237
        }
238 1
    }
239
}
240