8
8
use Arris \Cache \Exceptions \RedisClientException ;
9
9
use Psr \Log \LoggerInterface ;
10
10
11
+ use Psr \Log \NullLogger ;
11
12
use function array_key_exists , array_keys , array_walk , is_array ;
12
13
use function json_decode , json_encode ;
13
14
use function class_exists , method_exists , function_exists , call_user_func_array ;
@@ -31,18 +32,25 @@ class Cache implements CacheInterface
31
32
private static $ logger ;
32
33
33
34
/**
34
- * @var PDO $pdo
35
+ * @var PDO|null $pdo
35
36
*/
36
37
private static $ pdo ;
37
38
39
+ /**
40
+ * @var array
41
+ */
42
+ /*private static $connection_options = [];*/
43
+
44
+ /*private static $connectors = [];*/
45
+
38
46
/**
39
47
* @var array
40
48
*/
41
49
public static $ repository = [];
42
50
43
- public static function init (array $ credentials = [], array $ rules = [], PDO $ PDO = null , LoggerInterface $ logger = null )
51
+ public static function init (array $ credentials = [], array $ rules = [], $ PDO = null , LoggerInterface $ logger = null )
44
52
{
45
- self ::$ logger = $ logger ;
53
+ self ::$ logger = is_null ( $ logger ) ? new NullLogger () : $ logger ;
46
54
self ::$ is_redis_connected = false ;
47
55
self ::$ pdo = $ PDO ;
48
56
@@ -55,7 +63,7 @@ public static function init(array $credentials = [], array $rules = [], PDO $PDO
55
63
'database ' => self ::REDIS_DEFAULT_DB ,
56
64
'password ' => self ::REDIS_DEFAULT_PASSWORD
57
65
];
58
- $ options = self ::overrideDefaults ($ options , $ credentials );
66
+ /*self::$connection_options = */ $ options = self ::overrideDefaults ($ options , $ credentials );
59
67
60
68
if ($ options ['enabled ' ]) {
61
69
try {
@@ -69,6 +77,7 @@ public static function init(array $credentials = [], array $rules = [], PDO $PDO
69
77
// теперь перебираем $rules
70
78
foreach ($ rules as $ rule_name => $ rule_definition ) {
71
79
$ message = self ::defineRule ($ rule_name , $ rule_definition );
80
+
72
81
if ($ logger instanceof LoggerInterface) {
73
82
$ logger ->debug ($ message );
74
83
}
@@ -81,6 +90,20 @@ public static function getConnector():RedisClient
81
90
return self ::$ redis_connector ;
82
91
}
83
92
93
+ /*public static function switchDatabase($database):RedisClient
94
+ {
95
+ $options = self::$connection_options;
96
+
97
+ if ($options['database'] !== $database) {
98
+ $connector = new RedisClient($options['host'], $options['port'], $options['timeout'], $options['persistent'], $database, $options['password']);
99
+ $connector->connect();
100
+ } else {
101
+ $connector = self::$redis_connector;
102
+ }
103
+
104
+ return $connector;
105
+ }*/
106
+
84
107
public static function addRule (string $ rule_name , $ rule_definition ):string
85
108
{
86
109
$ message = self ::defineRule ($ rule_name , $ rule_definition );
@@ -90,15 +113,45 @@ public static function addRule(string $rule_name, $rule_definition):string
90
113
return $ message ;
91
114
}
92
115
93
- public static function getAllKeys ():array
116
+ public static function getAllLocalKeys ():array
94
117
{
95
118
return array_keys (self ::$ repository );
96
119
}
97
120
121
+ public static function getAllRedisKeys ():array
122
+ {
123
+ if (!self ::$ is_redis_connected ) {
124
+ self ::$ logger ->debug ("[getAllRedisKeys] Redis not connected " );
125
+ return [];
126
+ }
127
+
128
+ $ keys = self ::$ redis_connector ->keys ('* ' );
129
+ $ keys_count = count ($ keys );
130
+
131
+ self ::$ logger ->debug ("[getAllRedisKeys] Returned {$ keys_count } key(s) " );
132
+
133
+ return $ keys ;
134
+ }
135
+
136
+ public static function getAllKeys (bool $ use_keys_from_redis ):array
137
+ {
138
+ if (!self ::$ is_redis_connected ) {
139
+ self ::$ logger ->debug ("[getAllKeys] Redis not connected " );
140
+ return [];
141
+ }
142
+
143
+ $ keys = $ use_keys_from_redis ? self ::$ redis_connector ->keys ('* ' ) : array_keys (self ::$ repository );
144
+ $ keys_count = count ($ keys );
145
+
146
+ self ::$ logger ->debug ("[getAllKeys] Returned {$ keys_count } key(s) " );
147
+
148
+ return $ keys ;
149
+ }
150
+
98
151
public static function get (string $ key , $ default = null )
99
152
{
100
153
if (self ::check ($ key )) {
101
- self ::$ logger ->debug ("Recieved ` {$ key }` from cache " );
154
+ self ::$ logger ->debug ("Received ` {$ key }` from cache " );
102
155
return self ::$ repository [ $ key ];
103
156
}
104
157
return $ default ;
@@ -110,7 +163,7 @@ public static function set(string $key, $data)
110
163
self ::$ repository [ $ key ] = $ data ;
111
164
}
112
165
113
- public static function check (string $ key )
166
+ public static function check (string $ key ): bool
114
167
{
115
168
return array_key_exists ($ key , self ::$ repository );
116
169
}
@@ -139,15 +192,16 @@ public static function flush(string $key, bool $clean_redis = true):string
139
192
return $ key ;
140
193
} else {
141
194
$ custom_mask = self ::createMask ($ key );
142
- $ custom_list = preg_grep ($ custom_mask , self ::getAllKeys ());
195
+ $ all_keys = $ clean_redis ? self ::getAllRedisKeys () : self ::getAllLocalKeys ();
196
+ $ custom_list = preg_grep ($ custom_mask , $ all_keys );
143
197
foreach ($ custom_list as $ k ) {
144
198
self ::flush ($ k , $ clean_redis );
145
199
}
146
200
return $ custom_mask ;
147
201
}
148
202
}
149
203
150
- public static function redisFetch (string $ key_name , $ use_json_decode = true )
204
+ public static function redisFetch (string $ key_name , bool $ use_json_decode = true )
151
205
{
152
206
if (self ::$ is_redis_connected === false ) {
153
207
return null ;
@@ -168,7 +222,7 @@ public static function redisPush(string $key_name, $data, int $ttl = 0):bool
168
222
return false ;
169
223
}
170
224
171
- self ::$ redis_connector ->set ($ key_name , self ::jsonize ($ data ));
225
+ self ::$ redis_connector ->set ($ key_name , CacheHelper ::jsonize ($ data ));
172
226
173
227
if ($ ttl > 0 ) {
174
228
self ::$ redis_connector ->expire ($ key_name , $ ttl );
@@ -188,20 +242,24 @@ public static function redisDel(string $key_name)
188
242
}
189
243
190
244
$ deleted = [];
191
-
192
- if (strpos ($ key_name , '* ' ) === false ) {
245
+
246
+ if ($ key_name === '* ' ) {
247
+ self ::$ redis_connector ->flushDb ();
248
+ $ deleted = [ '* ' ];
249
+ } elseif (strpos ($ key_name , '* ' ) === false ) {
193
250
self ::$ redis_connector ->del ($ key_name );
194
- return $ key_name ;
251
+ $ deleted = [ $ key_name ] ;
195
252
} else {
196
253
$ custom_mask = self ::createMask ($ key_name );
197
254
$ custom_list = preg_grep ($ custom_mask , self ::$ redis_connector ->keys ('* ' ));
198
- // $custom_list = self::$redis_connector->keys($key_name);
199
-
255
+
200
256
foreach ($ custom_list as $ k ) {
201
257
$ deleted [] = self ::redisDel ($ k );
202
258
}
203
- return $ deleted ;
259
+
204
260
}
261
+ return $ deleted ;
262
+
205
263
// return !(self::$redis_connector->exists($key_name));
206
264
}
207
265
@@ -265,7 +323,7 @@ public static function decrCounter(string $key, int $diff = 1):int
265
323
return self ::$ repository [ $ key ];
266
324
}
267
325
268
- public static function getCounter (string $ key , $ default = 0 ):int
326
+ public static function getCounter (string $ key , int $ default = 0 ):int
269
327
{
270
328
if (self ::$ is_redis_connected ) {
271
329
return self ::$ redis_connector ->get ($ key );
@@ -299,8 +357,7 @@ private static function defineRule($rule_name, $rule_definition)
299
357
300
358
if ($ rule_value !== false ) {
301
359
self ::set ($ rule_name , json_decode ($ rule_value , true , 512 , JSON_THROW_ON_ERROR ));
302
- $ message = "Loaded ` {$ rule_name }` from redis, stored to cache " ;
303
- return $ message ;
360
+ return "[INFO] Loaded ` {$ rule_name }` from redis, stored to cache " ;
304
361
}
305
362
}
306
363
@@ -315,50 +372,51 @@ private static function defineRule($rule_name, $rule_definition)
315
372
316
373
// если ACTION пуст - кладем в репозиторий NULL и продолжаем
317
374
if (empty ($ action )) {
318
- $ message = ' [ERROR] Key not found, but action is empty ' ;
375
+ $ message = " [ERROR] Key found, but action is empty " ;
319
376
self ::set ($ rule_name , null );
320
377
return $ message ;
321
378
}
322
379
323
- $ data = '' ;
380
+ switch ($ rule_definition ['source ' ]) {
381
+ case self ::RULE_SOURCE_SQL : {
382
+ // коннекта к БД нет: кладем в репозиторий null и продолжаем
383
+ if (is_null (self ::$ pdo )) {
384
+ $ message = '[ERROR] Key not found, PDO not defined ' ;
385
+ self ::set ($ rule_name , null );
386
+ return $ message ;
387
+ }
324
388
325
- // если источник данных SQL
326
- if ($ rule_definition ['source ' ] === self ::RULE_SOURCE_SQL ) {
389
+ $ sth = self ::$ pdo ->query ($ rule_definition ['action ' ]);
390
+ if (false === $ sth ) {
391
+ $ message = '[ERROR] Key not found, PDO present, PDO Answer invalid ' ;
392
+ self ::set ($ rule_name , null );
393
+ return $ message ;
394
+ }
395
+ $ data = $ sth ->fetchAll ();
396
+ $ message = "Data for ` {$ rule_name }` fetched from DB, " ;
327
397
328
- // коннекта к БД нет: кладем в репозиторий null и продолжаем
329
- if (is_null (self ::$ pdo )) {
330
- $ message = '[ERROR] Key not found, PDO not defined ' ;
331
- self ::set ($ rule_name , null );
332
- return $ message ;
398
+ break ;
333
399
}
400
+ case self ::RULE_SOURCE_RAW : {
401
+ $ data = $ rule_definition ['data ' ];
402
+ $ message = "Data for ` {$ rule_name }` fetched raw data, " ;
334
403
335
- $ sth = self ::$ pdo ->query ($ rule_definition ['action ' ]);
336
- if (false === $ sth ) {
337
- $ message = '[ERROR] Key not found, PDO present, PDO Answer invalid ' ;
338
- self ::set ($ rule_definition , null );
339
- return $ message ;
404
+ break ;
405
+ }
406
+ // case self::RULE_SOURCE_CALLBACK
407
+ default : {
408
+ [$ actor , $ params ] = self ::compileCallbackHandler ($ rule_definition ['action ' ]);
409
+ $ data = call_user_func_array ($ actor , $ params );
410
+ $ message = "Data for ` {$ rule_name }` fetched from callback, " ;
340
411
}
341
- $ data = $ sth ->fetchAll ();
342
- $ message = "Data for ` {$ rule_name }` fetched from DB, " ;
343
412
}
344
413
345
- if ($ rule_definition ['source ' ] === self ::RULE_SOURCE_CALLBACK ) {
346
- [$ actor , $ params ] = self ::compileCallbackHandler ($ rule_definition ['action ' ]);
347
- $ data = call_user_func_array ($ actor , $ params );
348
- $ message = "Data for ` {$ rule_name }` fetched from callback, " ;
349
- }
350
-
351
- if ($ rule_definition ['source ' ] === self ::RULE_SOURCE_RAW ) {
352
- $ data = $ rule_definition ['data ' ];
353
- $ message = "Data for ` {$ rule_name }` fetched raw data, " ;
354
- }
355
-
356
414
// кладем результат в репозиторий
357
415
self ::set ($ rule_name , $ data );
358
416
359
417
// и в редис, если он запущен
360
418
if (self ::$ is_redis_connected ) {
361
- self ::$ redis_connector ->set ($ rule_name , self ::jsonize ($ data ));
419
+ self ::$ redis_connector ->set ($ rule_name , CacheHelper ::jsonize ($ data ));
362
420
if ($ ttl > 0 ) {
363
421
self ::$ redis_connector ->expire ($ rule_name , $ ttl );
364
422
}
@@ -374,18 +432,6 @@ public static function isRedisConnected():bool
374
432
{
375
433
return self ::$ is_redis_connected ;
376
434
}
377
-
378
-
379
- /**
380
- *
381
- * @param $data
382
- * @return false|string
383
- * @throws JsonException
384
- */
385
- private static function jsonize ($ data )
386
- {
387
- return json_encode ($ data , JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION | JSON_INVALID_UTF8_SUBSTITUTE | JSON_THROW_ON_ERROR );
388
- }
389
435
390
436
/**
391
437
* Перезаписывает набор дефолтных значений на основе переданного списка опций
@@ -432,7 +478,6 @@ private static function compileCallbackHandler($actor)
432
478
$ handler = $ actor [0 ];
433
479
$ params = (count ($ actor ) > 1 ) ? $ actor [1 ] : [];
434
480
435
- //@todo: нужна проверка is_string() - но зачем?
436
481
if (!is_string ($ handler )) {
437
482
throw new CacheCallbackException ("First argument of callback array is NOT a string " );
438
483
}
0 commit comments