Skip to content

Commit d8a8db9

Browse files
committed
Adding a TimeToLive class
1 parent 0a50195 commit d8a8db9

File tree

5 files changed

+131
-107
lines changed

5 files changed

+131
-107
lines changed

src/Storage/PublicSuffixListPsr16Cache.php

Lines changed: 7 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,12 @@
55
namespace Pdp\Storage;
66

77
use DateInterval;
8-
use DateTimeImmutable;
9-
use DateTimeInterface;
10-
use DateTimeZone;
11-
use InvalidArgumentException;
128
use Pdp\PublicSuffixList;
9+
use Psr\SimpleCache\CacheException;
1310
use Psr\SimpleCache\CacheInterface;
1411
use Throwable;
15-
use TypeError;
16-
use function filter_var;
17-
use function is_string;
1812
use function md5;
1913
use function strtolower;
20-
use const FILTER_VALIDATE_INT;
2114

2215
final class PublicSuffixListPsr16Cache implements PublicSuffixListCache
2316
{
@@ -34,51 +27,7 @@ public function __construct(CacheInterface $cache, string $cachePrefix = '', $ca
3427
{
3528
$this->cache = $cache;
3629
$this->cachePrefix = $cachePrefix;
37-
$this->cacheTtl = $this->setTtl($cacheTtl);
38-
}
39-
40-
/**
41-
* Set the cache TTL.
42-
*
43-
* @param mixed $ttl the cache TTL
44-
*
45-
* @throws InvalidArgumentException if the value can not be computed
46-
* @throws TypeError if the value type is not recognized
47-
*/
48-
private function setTtl($ttl): ?DateInterval
49-
{
50-
if ($ttl instanceof DateInterval || null === $ttl) {
51-
return $ttl;
52-
}
53-
54-
if ($ttl instanceof DateTimeInterface) {
55-
/** @var DateTimeZone $timezone */
56-
$timezone = $ttl->getTimezone();
57-
58-
$now = new DateTimeImmutable('NOW', $timezone);
59-
/** @var DateInterval $ttl */
60-
$ttl = $now->diff($ttl, false);
61-
62-
return $ttl;
63-
}
64-
65-
if (false !== ($res = filter_var($ttl, FILTER_VALIDATE_INT))) {
66-
return new DateInterval('PT'.$res.'S');
67-
}
68-
69-
if (!is_string($ttl)) {
70-
throw new TypeError('The ttl must null, an integer, a string, a DateTimeInterface or a DateInterval object.');
71-
}
72-
73-
/** @var DateInterval|false $date */
74-
$date = @DateInterval::createFromDateString($ttl);
75-
if (!$date instanceof DateInterval) {
76-
throw new InvalidArgumentException(
77-
'The ttl value "'.$ttl.'" can not be parsable by `DateInterval::createFromDateString`.'
78-
);
79-
}
80-
81-
return $date;
30+
$this->cacheTtl = TimeToLive::convert($cacheTtl);
8231
}
8332

8433
public function fetch(string $uri): ?PublicSuffixList
@@ -111,7 +60,11 @@ public function remember(string $uri, PublicSuffixList $publicSuffixList): bool
11160
try {
11261
return $this->cache->set($this->cacheKey($uri), $publicSuffixList, $this->cacheTtl);
11362
} catch (Throwable $exception) {
114-
return false;
63+
if ($exception instanceof CacheException) {
64+
return false;
65+
}
66+
67+
throw $exception;
11568
}
11669
}
11770

src/Storage/PublicSuffixListPsr16CacheTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,25 @@ public function testItReturnsFalseIfItCantCacheAPublicSuffixListInstance(): void
9494
self::assertFalse($pslCache->remember('http://www.example.com', $psl));
9595
}
9696

97+
public function testItWillThrowIfItCantCacheAPublicSuffixListInstance(): void
98+
{
99+
$exception = new class('Something went wrong.', 0) extends RuntimeException {
100+
};
101+
$cache = $this->createStub(CacheInterface::class);
102+
$cache->method('set')->will(self::throwException($exception));
103+
104+
$psl = Rules::fromPath(dirname(__DIR__, 2).'/test_data/public_suffix_list.dat');
105+
$pslCache = new PublicSuffixListPsr16Cache($cache, 'pdp_', new class() {
106+
public function __toString(): string
107+
{
108+
return '1 DAY';
109+
}
110+
});
111+
$this->expectException(RuntimeException::class);
112+
113+
$pslCache->remember('http://www.example.com', $psl);
114+
}
115+
97116
public function testItCanDeleteTheCachedDatabase(): void
98117
{
99118
$uri = 'http://www.example.com';

src/Storage/TimeToLive.php

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Pdp\Storage;
6+
7+
use DateInterval;
8+
use DateTimeImmutable;
9+
use DateTimeInterface;
10+
use DateTimeZone;
11+
use InvalidArgumentException;
12+
use TypeError;
13+
use function filter_var;
14+
use function is_object;
15+
use function is_string;
16+
use function method_exists;
17+
use const FILTER_VALIDATE_INT;
18+
19+
final class TimeToLive
20+
{
21+
public static function fromDateTimeInterface(DateTimeInterface $ttl): DateInterval
22+
{
23+
/** @var DateTimeZone $timezone */
24+
$timezone = $ttl->getTimezone();
25+
26+
$now = new DateTimeImmutable('NOW', $timezone);
27+
28+
/** @var DateInterval $diff */
29+
$diff = $now->diff($ttl, false);
30+
31+
return $diff;
32+
}
33+
34+
/**
35+
* @param object|string|int $ttl the cache TTL the object must implement the __toString method
36+
*/
37+
public static function fromScalar($ttl): DateInterval
38+
{
39+
if (is_object($ttl) && method_exists($ttl, '__toString')) {
40+
$ttl = (string) $ttl;
41+
}
42+
43+
if (false !== ($res = filter_var($ttl, FILTER_VALIDATE_INT))) {
44+
return new DateInterval('PT'.$res.'S');
45+
}
46+
47+
if (!is_string($ttl)) {
48+
throw new TypeError('The ttl must null, an integer, a string, a DateTimeInterface or a DateInterval object.');
49+
}
50+
51+
/** @var DateInterval|false $date */
52+
$date = @DateInterval::createFromDateString($ttl);
53+
if (!$date instanceof DateInterval) {
54+
throw new InvalidArgumentException(
55+
'The ttl value "'.$ttl.'" can not be parsable by `DateInterval::createFromDateString`.'
56+
);
57+
}
58+
59+
return $date;
60+
}
61+
62+
/**
63+
* Set the cache TTL.
64+
*
65+
* @param mixed $ttl the cache TTL
66+
*
67+
* @throws InvalidArgumentException if the value can not be computed
68+
* @throws TypeError if the value type is not recognized
69+
*/
70+
public static function convert($ttl): ?DateInterval
71+
{
72+
if ($ttl instanceof DateInterval || null === $ttl) {
73+
return $ttl;
74+
}
75+
76+
if ($ttl instanceof DateTimeInterface) {
77+
return self::fromDateTimeInterface($ttl);
78+
}
79+
80+
return self::fromScalar($ttl);
81+
}
82+
}

src/Storage/TopLevelDomainListPsr16Cache.php

Lines changed: 7 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,12 @@
55
namespace Pdp\Storage;
66

77
use DateInterval;
8-
use DateTimeImmutable;
9-
use DateTimeInterface;
10-
use DateTimeZone;
11-
use InvalidArgumentException;
128
use Pdp\TopLevelDomainList;
9+
use Psr\SimpleCache\CacheException;
1310
use Psr\SimpleCache\CacheInterface;
1411
use Throwable;
15-
use TypeError;
16-
use function filter_var;
17-
use function is_string;
1812
use function md5;
1913
use function strtolower;
20-
use const FILTER_VALIDATE_INT;
2114

2215
final class TopLevelDomainListPsr16Cache implements TopLevelDomainListCache
2316
{
@@ -34,49 +27,7 @@ public function __construct(CacheInterface $cache, string $cachePrefix = '', $ca
3427
{
3528
$this->cache = $cache;
3629
$this->cachePrefix = $cachePrefix;
37-
$this->cacheTtl = $this->setTtl($cacheTtl);
38-
}
39-
40-
/**
41-
* Set the cache TTL.
42-
*
43-
* @param mixed $ttl the cache TTL
44-
*
45-
* @throws InvalidArgumentException if the value can not be computed
46-
* @throws TypeError if the value type is not recognized
47-
*/
48-
private function setTtl($ttl): ?DateInterval
49-
{
50-
if ($ttl instanceof DateInterval || null === $ttl) {
51-
return $ttl;
52-
}
53-
54-
if ($ttl instanceof DateTimeInterface) {
55-
/** @var DateTimeZone $timezone */
56-
$timezone = $ttl->getTimezone();
57-
58-
$now = new DateTimeImmutable('NOW', $timezone);
59-
/** @var DateInterval $ttl */
60-
$ttl = $now->diff($ttl, false);
61-
62-
return $ttl;
63-
}
64-
65-
if (false !== ($res = filter_var($ttl, FILTER_VALIDATE_INT))) {
66-
return new DateInterval('PT'.$res.'S');
67-
}
68-
69-
if (!is_string($ttl)) {
70-
throw new TypeError('The ttl must null, an integer, a string, a DateTimeInterface or a DateInterval object.');
71-
}
72-
73-
/** @var DateInterval|false $date */
74-
$date = @DateInterval::createFromDateString($ttl);
75-
if (!$date instanceof DateInterval) {
76-
throw new InvalidArgumentException('The ttl value "'.$ttl.'" can not be parsable by `DateInterval::createFromDateString`.');
77-
}
78-
79-
return $date;
30+
$this->cacheTtl = TimeToLive::convert($cacheTtl);
8031
}
8132

8233
public function fetch(string $uri): ?TopLevelDomainList
@@ -109,7 +60,11 @@ public function remember(string $uri, TopLevelDomainList $topLevelDomainList): b
10960
try {
11061
return $this->cache->set($this->cacheKey($uri), $topLevelDomainList, $this->cacheTtl);
11162
} catch (Throwable $exception) {
112-
return false;
63+
if ($exception instanceof CacheException) {
64+
return false;
65+
}
66+
67+
throw $exception;
11368
}
11469
}
11570

src/Storage/TopLevelDomainListPsr16CacheTest.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public function testItReturnsFalseIfItCantStoreAPublicSuffixListInstance(): void
8484
self::assertFalse($instance->remember('http://www.example.com', $rzd));
8585
}
8686

87-
public function testItReturnsFalseIfItCantCacheAPublicSuffixListInstance(): void
87+
public function testItReturnsFalseIfItCantCacheATopLevelDomainListInstance(): void
8888
{
8989
$exception = new class('Something went wrong.', 0) extends RuntimeException implements CacheException {
9090
};
@@ -97,6 +97,21 @@ public function testItReturnsFalseIfItCantCacheAPublicSuffixListInstance(): void
9797
self::assertFalse($instance->remember('http://www.example.com', $rzd));
9898
}
9999

100+
public function testItThrowsIfItCantCacheATopLevelDomainListInstance(): void
101+
{
102+
$exception = new class('Something went wrong.', 0) extends RuntimeException {
103+
};
104+
$cache = $this->createStub(CacheInterface::class);
105+
$cache->method('set')->will(self::throwException($exception));
106+
107+
$rzd = TopLevelDomains::fromPath(dirname(__DIR__, 2).'/test_data/tlds-alpha-by-domain.txt');
108+
$instance = new TopLevelDomainListPsr16Cache($cache, 'pdp_', new DateInterval('P1D'));
109+
110+
$this->expectException(RuntimeException::class);
111+
112+
$instance->remember('http://www.example.com', $rzd);
113+
}
114+
100115
public function testItCanDeleteTheCachedDatabase(): void
101116
{
102117
$uri = 'http://www.example.com';

0 commit comments

Comments
 (0)