Skip to content

Commit b8e5b14

Browse files
Jirka Fdg
Jirka F
authored andcommitted
added Cache::NAMESPACES and support for cleaning namespace in FileStorage & SqliteStorage [Closes #52]
1 parent aebaa0e commit b8e5b14

File tree

5 files changed

+223
-9
lines changed

5 files changed

+223
-9
lines changed

Diff for: src/Caching/Cache.php

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class Cache
3131
ITEMS = 'items',
3232
CONSTS = 'consts',
3333
CALLBACKS = 'callbacks',
34+
NAMESPACES = 'namespaces',
3435
ALL = 'all';
3536

3637
/** @internal */
@@ -198,6 +199,11 @@ private function completeDependencies(?array $dp): array
198199
$dp[self::TAGS] = array_values((array) $dp[self::TAGS]);
199200
}
200201

202+
// make list from NAMESPACES
203+
if (isset($dp[self::NAMESPACES])) {
204+
$dp[self::NAMESPACES] = array_values((array) $dp[self::NAMESPACES]);
205+
}
206+
201207
// convert FILES into CALLBACKS
202208
if (isset($dp[self::FILES])) {
203209
foreach (array_unique((array) $dp[self::FILES]) as $item) {

Diff for: src/Caching/Storages/FileStorage.php

+12
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ public function clean(array $conditions): void
249249
{
250250
$all = !empty($conditions[Cache::ALL]);
251251
$collector = empty($conditions);
252+
$namespaces = $conditions[Cache::NAMESPACES] ?? null;
252253

253254
// cleaning using file iterator
254255
if ($all || $collector) {
@@ -284,6 +285,17 @@ public function clean(array $conditions): void
284285
$this->journal->clean($conditions);
285286
}
286287
return;
288+
289+
} elseif ($namespaces) {
290+
foreach ($namespaces as $namespace) {
291+
$dir = $this->dir . '/_' . urlencode($namespace);
292+
if (is_dir($dir)) {
293+
foreach (Nette\Utils\Finder::findFiles('_*')->in($dir) as $entry) {
294+
$this->delete((string) $entry);
295+
}
296+
@rmdir($dir); // may already contain new files
297+
}
298+
}
287299
}
288300

289301
// cleaning using journal

Diff for: src/Caching/Storages/SQLiteStorage.php

+18-9
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public function __construct($path)
3434
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
3535
$this->pdo->exec('
3636
PRAGMA foreign_keys = ON;
37+
PRAGMA case_sensitive_like = ON;
38+
3739
CREATE TABLE IF NOT EXISTS cache (
3840
key BLOB NOT NULL PRIMARY KEY,
3941
data BLOB NOT NULL,
@@ -142,18 +144,25 @@ public function clean(array $conditions): void
142144
{
143145
if (!empty($conditions[Cache::ALL])) {
144146
$this->pdo->prepare('DELETE FROM cache')->execute();
147+
return;
148+
}
145149

146-
} else {
147-
$sql = 'DELETE FROM cache WHERE expire < ?';
148-
$args = [time()];
150+
$sql = 'DELETE FROM cache WHERE expire < ?';
151+
$args = [time()];
149152

150-
if (!empty($conditions[Cache::TAGS])) {
151-
$tags = $conditions[Cache::TAGS];
152-
$sql .= ' OR key IN (SELECT key FROM tags WHERE tag IN (?' . str_repeat(',?', count($tags) - 1) . '))';
153-
$args = array_merge($args, $tags);
154-
}
153+
if (!empty($conditions[Cache::TAGS])) {
154+
$tags = $conditions[Cache::TAGS];
155+
$sql .= ' OR key IN (SELECT key FROM tags WHERE tag IN (?' . str_repeat(',?', count($tags) - 1) . '))';
156+
$args = array_merge($args, $tags);
157+
}
155158

156-
$this->pdo->prepare($sql)->execute($args);
159+
if (!empty($conditions[Cache::NAMESPACES])) {
160+
foreach ($conditions[Cache::NAMESPACES] as $namespace) {
161+
$sql .= ' OR key LIKE ?';
162+
$args[] = $namespace . Cache::NAMESPACE_SEPARATOR . '%';
163+
}
157164
}
165+
166+
$this->pdo->prepare($sql)->execute($args);
158167
}
159168
}

Diff for: tests/Storages/FileStorage.clean-namespace.phpt

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
/**
4+
* Test: Nette\Caching\Storages\FileStorage clean with Cache::NAMESPACE
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
use Nette\Caching\Cache;
10+
use Nette\Caching\Storages\FileStorage;
11+
use Tester\Assert;
12+
13+
14+
require __DIR__ . '/../bootstrap.php';
15+
16+
$storage = new FileStorage(TEMP_DIR);
17+
18+
/*
19+
* Create filestorage cache without namespace and some with namespaces
20+
*/
21+
$cacheA = new Cache($storage);
22+
$cacheB = new Cache($storage, 'B');
23+
$cacheC = new Cache($storage, 'C');
24+
$cacheD = new Cache($storage, 'D');
25+
26+
/*
27+
* Fill with data
28+
*/
29+
$cacheA->save('test1', 'David');
30+
$cacheA->save('test2', 'Grudl');
31+
32+
$cacheB->save('test1', 'Barry');
33+
$cacheB->save('test2', 'Allen');
34+
35+
$cacheC->save('test1', 'Oliver');
36+
$cacheC->save('test2', 'Queen');
37+
38+
$cacheD->save('test1', 'Bruce');
39+
$cacheD->save('test2', 'Wayne');
40+
41+
42+
/*
43+
* Check if fill wass successfull
44+
*/
45+
Assert::same('David', $cacheA->load('test1'));
46+
Assert::same('Grudl', $cacheA->load('test2'));
47+
48+
Assert::same('Barry', $cacheB->load('test1'));
49+
Assert::same('Allen', $cacheB->load('test2'));
50+
51+
Assert::same('Oliver', $cacheC->load('test1'));
52+
Assert::same('Queen', $cacheC->load('test2'));
53+
54+
Assert::same('Bruce', $cacheD->load('test1'));
55+
Assert::same('Wayne', $cacheD->load('test2'));
56+
57+
58+
/*
59+
* Clean one namespace
60+
*/
61+
$storage->clean([Cache::NAMESPACES => ['B']]);
62+
63+
Assert::same('David', $cacheA->load('test1'));
64+
Assert::same('Grudl', $cacheA->load('test2'));
65+
66+
// Only these should be null now
67+
Assert::null($cacheB->load('test1'));
68+
Assert::null($cacheB->load('test2'));
69+
70+
Assert::same('Oliver', $cacheC->load('test1'));
71+
Assert::same('Queen', $cacheC->load('test2'));
72+
73+
Assert::same('Bruce', $cacheD->load('test1'));
74+
Assert::same('Wayne', $cacheD->load('test2'));
75+
76+
77+
/*
78+
* Test cleaning multiple namespaces
79+
*/
80+
$storage->clean([Cache::NAMESPACES => ['C', 'D']]);
81+
82+
Assert::same('David', $cacheA->load('test1'));
83+
Assert::same('Grudl', $cacheA->load('test2'));
84+
85+
// All other should be null
86+
Assert::null($cacheB->load('test1'));
87+
Assert::null($cacheB->load('test2'));
88+
89+
Assert::null($cacheC->load('test1'));
90+
Assert::null($cacheC->load('test2'));
91+
92+
Assert::null($cacheD->load('test1'));
93+
Assert::null($cacheD->load('test2'));

Diff for: tests/Storages/SQLiteStorage.clean-namespace.phpt

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
/**
4+
* Test: Nette\Caching\Storages\SQLiteStorage clean with Cache::NAMESPACE
5+
* @phpExtension pdo_sqlite
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
use Nette\Caching\Cache;
11+
use Nette\Caching\Storages\SQLiteStorage;
12+
use Tester\Assert;
13+
14+
15+
require __DIR__ . '/../bootstrap.php';
16+
17+
$storage = new SQLiteStorage(':memory:');
18+
19+
/*
20+
* Create SQLiteStorage cache without namespace and some with namespaces
21+
*/
22+
$cacheA = new Cache($storage);
23+
$cacheB = new Cache($storage, 'B');
24+
$cacheC = new Cache($storage, 'C');
25+
$cacheD = new Cache($storage, 'D');
26+
27+
/*
28+
* Fill with data
29+
*/
30+
$cacheA->save('test1', 'David');
31+
$cacheA->save('test2', 'Grudl');
32+
33+
$cacheB->save('test1', 'Barry');
34+
$cacheB->save('test2', 'Allen');
35+
36+
$cacheC->save('test1', 'Oliver');
37+
$cacheC->save('test2', 'Queen');
38+
39+
$cacheD->save('test1', 'Bruce');
40+
$cacheD->save('test2', 'Wayne');
41+
42+
43+
/*
44+
* Check if fill wass successfull
45+
*/
46+
Assert::same('David', $cacheA->load('test1'));
47+
Assert::same('Grudl', $cacheA->load('test2'));
48+
49+
Assert::same('Barry', $cacheB->load('test1'));
50+
Assert::same('Allen', $cacheB->load('test2'));
51+
52+
Assert::same('Oliver', $cacheC->load('test1'));
53+
Assert::same('Queen', $cacheC->load('test2'));
54+
55+
Assert::same('Bruce', $cacheD->load('test1'));
56+
Assert::same('Wayne', $cacheD->load('test2'));
57+
58+
59+
/*
60+
* Clean one namespace
61+
*/
62+
$storage->clean([Cache::NAMESPACES => ['B']]);
63+
64+
Assert::same('David', $cacheA->load('test1'));
65+
Assert::same('Grudl', $cacheA->load('test2'));
66+
67+
// Only these should be null now
68+
Assert::null($cacheB->load('test1'));
69+
Assert::null($cacheB->load('test2'));
70+
71+
Assert::same('Oliver', $cacheC->load('test1'));
72+
Assert::same('Queen', $cacheC->load('test2'));
73+
74+
Assert::same('Bruce', $cacheD->load('test1'));
75+
Assert::same('Wayne', $cacheD->load('test2'));
76+
77+
78+
/*
79+
* Test cleaning multiple namespaces
80+
*/
81+
$storage->clean([Cache::NAMESPACES => ['C', 'D']]);
82+
83+
Assert::same('David', $cacheA->load('test1'));
84+
Assert::same('Grudl', $cacheA->load('test2'));
85+
86+
// All other should be null
87+
Assert::null($cacheB->load('test1'));
88+
Assert::null($cacheB->load('test2'));
89+
90+
Assert::null($cacheC->load('test1'));
91+
Assert::null($cacheC->load('test2'));
92+
93+
Assert::null($cacheD->load('test1'));
94+
Assert::null($cacheD->load('test2'));

0 commit comments

Comments
 (0)