Passed
Push — master ( 6883f1...f6e68e )
by Fran
04:09
created

Cache::readFromCache()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 3
nop 4
dl 0
loc 13
rs 9.2
c 0
b 0
f 0
ccs 10
cts 10
cp 1
crap 4
1
<?php
2
namespace PSFS\base;
3
4
use PSFS\base\config\Config;
5
use PSFS\base\exception\ConfigException;
6
use PSFS\base\types\helpers\GeneratorHelper;
7
use PSFS\base\types\helpers\FileHelper;
8
use PSFS\base\types\traits\SingletonTrait;
9
10
/**
11
 * Class Cache
12
 * @package PSFS\base
13
 * Gestión de los ficheros de cache
14
 */
15
class Cache
16
{
17
    /**
18
     * @var \Memcache
19
     */
20
    protected $memcache = null;
21
22
    const JSON = 1;
23
    const TEXT = 2;
24
    const GZIP = 3;
25
    const JSONGZ = 4;
26
    const MEMCACHE = 5;
27
28
    use SingletonTrait;
29
30
    /**
31
     * @return bool
32
     */
33 3
    public static function canUseMemcache()
34
    {
35 3
        return Config::getParam('psfs.memcache', false) && !Config::getParam('debug') && class_exists('Memcached');
36
    }
37
38
    /**
39
     * Método que guarda un text en un fichero
40
     * @param string $data
41
     * @param string $path
42
     * @throws ConfigException
43
     */
44 5 View Code Duplication
    private function saveTextToFile($data, $path)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
45
    {
46 5
        GeneratorHelper::createDir(dirname($path));
47 5
        if (false === FileHelper::writeFile($path, $data)) {
48
            throw new ConfigException(_('No se tienen los permisos suficientes para escribir en el fichero ') . $path);
49
        }
50 5
    }
51
52
    /**
53
     * Método que extrae el texto de un fichero
54
     * @param string $path
55
     * @param int $transform
56
     * @param boolean $absolute
57
     * @return mixed
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...
58
     */
59 7
    public function getDataFromFile($path, $transform = Cache::TEXT, $absolute = false)
60
    {
61 7
        $data = null;
62 7
        $absolutePath = ($absolute) ? $path : CACHE_DIR . DIRECTORY_SEPARATOR . $path;
63 7
        if (file_exists($absolutePath)) {
64 4
            $data = FileHelper::readFile($absolutePath);
65 4
        }
66 7
        return Cache::extractDataWithFormat($data, $transform);
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type false or null; however, PSFS\base\Cache::extractDataWithFormat() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
67
    }
68
69
    /**
70
     * Método que verifica si un fichero tiene la cache expirada
71
     * @param string $path
72
     * @param int $expires
73
     * @param boolean $absolute
74
     * @return bool
75
     */
76 1
    private function hasExpiredCache($path, $expires = 300, $absolute = false)
77
    {
78 1
        $absolutePath = ($absolute) ? $path : CACHE_DIR . DIRECTORY_SEPARATOR . $path;
79 1
        $lasModificationDate = filemtime($absolutePath);
80 1
        return ($lasModificationDate + $expires <= time());
81
    }
82
83
    /**
84
     * Método que transforma los datos de salida
85
     * @param string $data
86
     * @param int $transform
87
     * @return array|string|null
88
     */
89 7
    public static function extractDataWithFormat($data, $transform = Cache::TEXT)
90
    {
91
        switch ($transform) {
92 7
            case Cache::JSON:
93 7
                $data = json_decode($data, true);
94 7
                break;
95 5
            case Cache::JSONGZ:
96 5
                $data = Cache::extractDataWithFormat($data, Cache::GZIP);
97 5
                $data = Cache::extractDataWithFormat($data, Cache::JSON);
98 5
                break;
99 5
            case Cache::GZIP:
100 5
                if (function_exists('gzuncompress') && !empty($data)) {
101 2
                    $data = @gzuncompress($data ?: '');
102 2
                }
103 5
                break;
104
        }
105 7
        return $data;
106
    }
107
108
    /**
109
     * Método que transforma los datos de entrada del fichero
110
     * @param string $data
111
     * @param int $transform
112
     * @return string
113
     */
114 5
    public static function transformData($data, $transform = Cache::TEXT)
115
    {
116
        switch ($transform) {
117 5
            case Cache::JSON:
118 5
                $data = json_encode($data, JSON_PRETTY_PRINT);
119 5
                break;
120 3
            case Cache::JSONGZ:
121 2
                $data = Cache::transformData($data, Cache::JSON);
122 2
                $data = Cache::transformData($data, Cache::GZIP);
123 2
                break;
124 3
            case Cache::GZIP:
125 2
                if (function_exists('gzcompress')) {
126 2
                    $data = gzcompress($data ?: '');
127 2
                }
128 2
                break;
129
        }
130 5
        return $data;
131
    }
132
133
    /**
134
     * Método que guarda en fichero los datos pasados
135
     * @param $path
136
     * @param $data
137
     * @param int $transform
138
     * @param boolean $absolute
139
     * @param integer $expires
140
     */
141 5
    public function storeData($path, $data, $transform = Cache::TEXT, $absolute = false, $expires = 600)
0 ignored issues
show
Unused Code introduced by
The parameter $expires is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
142
    {
143 5
        $data = Cache::transformData($data, $transform);
144 5
        $absolutePath = ($absolute) ? $path : CACHE_DIR . DIRECTORY_SEPARATOR . $path;
145 5
        $this->saveTextToFile($data, $absolutePath);
146 5
    }
147
148
    /**
149
     * Método que verifica si tiene que leer o no un fichero de cache
150
     * @param string $path
151
     * @param int $expires
152
     * @param callable $function
153
     * @param int $transform
154
     * @return mixed
155
     */
156 1
    public function readFromCache($path, $expires = 300, callable $function, $transform = Cache::TEXT)
157
    {
158 1
        $data = null;
159 1
        if (file_exists(CACHE_DIR . DIRECTORY_SEPARATOR . $path)) {
160 1
            if (null !== $function && $this->hasExpiredCache($path, $expires)) {
161 1
                $data = call_user_func($function);
162 1
                $this->storeData($path, $data, $transform, false, $expires);
163 1
            } else {
164 1
                $data = $this->getDataFromFile($path, $transform);
165
            }
166 1
        }
167 1
        return $data;
168
    }
169
170
    /**
171
     * @return bool
172
     */
173 1
    private static function checkAdminSite()
174
    {
175 1
        return Security::getInstance()->canAccessRestrictedAdmin();
176
    }
177
178
    /**
179
     * Método estático que revisa si se necesita cachear la respuesta de un servicio o no
180
     * @return integer|boolean
181
     */
182 1
    public static function needCache()
183
    {
184 1
        $needCache = false;
185 1
        if (!self::checkAdminSite() && !Config::getParam('debug')) {
186 1
            $action = Security::getInstance()->getSessionKey("__CACHE__");
187 1
            if (null !== $action && array_key_exists("cache", $action) && $action["cache"] > 0) {
188 1
                $needCache = $action["cache"];
189 1
            }
190 1
        }
191 1
        return $needCache;
192
    }
193
194
    /**
195
     * Método que construye un hash para almacenar la cache
196
     * @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...
197
     */
198 1
    public function getRequestCacheHash()
199
    {
200 1
        $hashPath = null;
201 1
        $filename = null;
202 1
        $action = Security::getInstance()->getSessionKey("__CACHE__");
203 1
        if (null !== $action && $action["cache"] > 0) {
204 1
            $class = GeneratorHelper::extractClassFromNamespace($action['class']);
205 1
            $filename = sha1($action["http"] . " " . $action["slug"]);
206 1
            $subPath = substr($filename, 0, 2) . DIRECTORY_SEPARATOR . substr($filename, 2, 2);
207 1
            $hashPath = $action['module'] . DIRECTORY_SEPARATOR . $class . DIRECTORY_SEPARATOR . $action['method'] . DIRECTORY_SEPARATOR . $subPath . DIRECTORY_SEPARATOR;
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 170 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
208 1
        }
209 1
        return [$hashPath, $filename];
210
    }
211
}
212