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\SingletonTrait; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* Class Cache |
11
|
|
|
* @package PSFS\base |
12
|
|
|
* Gestión de los ficheros de cache |
13
|
|
|
*/ |
14
|
|
|
class Cache |
15
|
|
|
{ |
16
|
|
|
/** |
17
|
|
|
* @var \Memcache |
18
|
|
|
*/ |
19
|
|
|
protected $memcache = null; |
20
|
|
|
|
21
|
|
|
const JSON = 1; |
22
|
|
|
const TEXT = 2; |
23
|
|
|
const GZIP = 3; |
24
|
|
|
const JSONGZ = 4; |
25
|
|
|
const MEMCACHE = 5; |
26
|
|
|
|
27
|
|
|
use SingletonTrait; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @return bool |
31
|
|
|
*/ |
32
|
3 |
|
public static function canUseMemcache() |
33
|
|
|
{ |
34
|
3 |
|
return Config::getParam('psfs.memcache', false) && !Config::getParam('debug') && class_exists('Memcached'); |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Método que guarda un text en un fichero |
39
|
|
|
* @param string $data |
40
|
|
|
* @param string $path |
41
|
|
|
* @throws ConfigException |
42
|
|
|
*/ |
43
|
5 |
View Code Duplication |
private function saveTextToFile($data, $path) |
|
|
|
|
44
|
|
|
{ |
45
|
5 |
|
GeneratorHelper::createDir(dirname($path)); |
46
|
5 |
|
if (false === file_put_contents($path, $data)) { |
47
|
|
|
throw new ConfigException(_('No se tienen los permisos suficientes para escribir en el fichero ') . $path); |
48
|
|
|
} |
49
|
5 |
|
} |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Método que extrae el texto de un fichero |
53
|
|
|
* @param string $path |
54
|
|
|
* @param int $transform |
55
|
|
|
* @param boolean $absolute |
56
|
|
|
* @return mixed |
|
|
|
|
57
|
|
|
*/ |
58
|
6 |
|
public function getDataFromFile($path, $transform = Cache::TEXT, $absolute = false) |
59
|
|
|
{ |
60
|
6 |
|
$data = null; |
61
|
6 |
|
$absolutePath = ($absolute) ? $path : CACHE_DIR . DIRECTORY_SEPARATOR . $path; |
62
|
6 |
|
if (file_exists($absolutePath)) { |
63
|
4 |
|
$data = file_get_contents($absolutePath); |
64
|
4 |
|
} |
65
|
6 |
|
return Cache::extractDataWithFormat($data, $transform); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* Método que verifica si un fichero tiene la cache expirada |
70
|
|
|
* @param string $path |
71
|
|
|
* @param int $expires |
72
|
|
|
* @param boolean $absolute |
73
|
|
|
* @return bool |
74
|
|
|
*/ |
75
|
1 |
|
private function hasExpiredCache($path, $expires = 300, $absolute = false) |
76
|
|
|
{ |
77
|
1 |
|
$absolutePath = ($absolute) ? $path : CACHE_DIR . DIRECTORY_SEPARATOR . $path; |
78
|
1 |
|
$lasModificationDate = filemtime($absolutePath); |
79
|
1 |
|
return ($lasModificationDate + $expires <= time()); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Método que transforma los datos de salida |
84
|
|
|
* @param string $data |
85
|
|
|
* @param int $transform |
86
|
|
|
* @return array|string|null |
87
|
|
|
*/ |
88
|
6 |
|
public static function extractDataWithFormat($data, $transform = Cache::TEXT) |
89
|
|
|
{ |
90
|
|
|
switch ($transform) { |
91
|
6 |
|
case Cache::JSON: |
92
|
6 |
|
$data = json_decode($data, true); |
93
|
6 |
|
break; |
94
|
4 |
|
case Cache::JSONGZ: |
95
|
4 |
|
$data = Cache::extractDataWithFormat($data, Cache::GZIP); |
96
|
4 |
|
$data = Cache::extractDataWithFormat($data, Cache::JSON); |
97
|
4 |
|
break; |
98
|
4 |
|
case Cache::GZIP: |
99
|
4 |
|
if (function_exists('gzuncompress') && !empty($data)) { |
100
|
2 |
|
$data = @gzuncompress($data ?: ''); |
101
|
2 |
|
} |
102
|
4 |
|
break; |
103
|
|
|
} |
104
|
6 |
|
return $data; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Método que transforma los datos de entrada del fichero |
109
|
|
|
* @param string $data |
110
|
|
|
* @param int $transform |
111
|
|
|
* @return string |
112
|
|
|
*/ |
113
|
5 |
|
public static function transformData($data, $transform = Cache::TEXT) |
114
|
|
|
{ |
115
|
|
|
switch ($transform) { |
116
|
5 |
|
case Cache::JSON: |
117
|
5 |
|
$data = json_encode($data, JSON_PRETTY_PRINT); |
118
|
5 |
|
break; |
119
|
3 |
|
case Cache::JSONGZ: |
120
|
2 |
|
$data = Cache::transformData($data, Cache::JSON); |
121
|
2 |
|
$data = Cache::transformData($data, Cache::GZIP); |
122
|
2 |
|
break; |
123
|
3 |
|
case Cache::GZIP: |
124
|
2 |
|
if (function_exists('gzcompress')) { |
125
|
2 |
|
$data = gzcompress($data ?: ''); |
126
|
2 |
|
} |
127
|
2 |
|
break; |
128
|
|
|
} |
129
|
5 |
|
return $data; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Método que guarda en fichero los datos pasados |
134
|
|
|
* @param $path |
135
|
|
|
* @param $data |
136
|
|
|
* @param int $transform |
137
|
|
|
* @param boolean $absolute |
138
|
|
|
* @param integer $expires |
139
|
|
|
*/ |
140
|
5 |
|
public function storeData($path, $data, $transform = Cache::TEXT, $absolute = false, $expires = 600) |
|
|
|
|
141
|
|
|
{ |
142
|
5 |
|
$data = Cache::transformData($data, $transform); |
143
|
5 |
|
$absolutePath = ($absolute) ? $path : CACHE_DIR . DIRECTORY_SEPARATOR . $path; |
144
|
5 |
|
$this->saveTextToFile($data, $absolutePath); |
145
|
5 |
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Método que verifica si tiene que leer o no un fichero de cache |
149
|
|
|
* @param string $path |
150
|
|
|
* @param int $expires |
151
|
|
|
* @param callable $function |
152
|
|
|
* @param int $transform |
153
|
|
|
* @return mixed |
154
|
|
|
*/ |
155
|
1 |
|
public function readFromCache($path, $expires = 300, callable $function, $transform = Cache::TEXT) |
156
|
|
|
{ |
157
|
1 |
|
$data = null; |
158
|
1 |
|
if (file_exists(CACHE_DIR . DIRECTORY_SEPARATOR . $path)) { |
159
|
1 |
|
if (null !== $function && $this->hasExpiredCache($path, $expires)) { |
160
|
1 |
|
$data = call_user_func($function); |
161
|
1 |
|
$this->storeData($path, $data, $transform, false, $expires); |
162
|
1 |
|
} else { |
163
|
1 |
|
$data = $this->getDataFromFile($path, $transform); |
164
|
|
|
} |
165
|
1 |
|
} |
166
|
1 |
|
return $data; |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* @return bool |
171
|
|
|
*/ |
172
|
1 |
|
private static function checkAdminSite() |
173
|
|
|
{ |
174
|
1 |
|
$isAdminRequest = false; |
175
|
1 |
|
$lastRequest = Security::getInstance()->getSessionKey("lastRequest"); |
176
|
1 |
|
if (null !== $lastRequest) { |
177
|
|
|
$url = str_replace(Request::getInstance()->getRootUrl(true), '', $lastRequest['url']); |
178
|
|
|
$isAdminRequest = preg_match('/^\/admin\//i', $url); |
179
|
|
|
} |
180
|
1 |
|
return (bool)$isAdminRequest; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Método estático que revisa si se necesita cachear la respuesta de un servicio o no |
185
|
|
|
* @return integer|boolean |
186
|
|
|
*/ |
187
|
1 |
|
public static function needCache() |
188
|
|
|
{ |
189
|
1 |
|
$needCache = false; |
190
|
1 |
|
if (!self::checkAdminSite()) { |
191
|
1 |
|
$action = Security::getInstance()->getSessionKey("__CACHE__"); |
192
|
1 |
|
if (null !== $action && array_key_exists("cache", $action) && $action["cache"] > 0) { |
193
|
1 |
|
$needCache = $action["cache"]; |
194
|
1 |
|
} |
195
|
1 |
|
} |
196
|
1 |
|
return $needCache; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* Método que construye un hash para almacenar la cache |
201
|
|
|
* @return string |
202
|
|
|
*/ |
203
|
1 |
|
public function getRequestCacheHash() |
204
|
|
|
{ |
205
|
1 |
|
$hash = ""; |
206
|
1 |
|
$action = Security::getInstance()->getSessionKey("__CACHE__"); |
207
|
1 |
|
if (null !== $action && $action["cache"] > 0) { |
208
|
1 |
|
$hash = $action["http"] . " " . $action["slug"]; |
209
|
1 |
|
} |
210
|
1 |
|
return sha1($hash); |
211
|
|
|
} |
212
|
|
|
} |
213
|
|
|
|
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.