Version 5.0.0 beta 1
This commit is contained in:
1 parent
25ddeb65d6
commit
15c7beabc5
6736 files changed
+627902
-497943
No files matched your search
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
use DateInterval;
|
||||
use DateTimeInterface;
|
||||
use Pdp\ResourceUri;
|
||||
use Psr\Http\Client\ClientInterface;
|
||||
use Psr\Http\Message\RequestFactoryInterface;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use Stringable;
|
||||
|
||||
final class PsrStorageFactory implements
|
||||
ResourceUri,
|
||||
PublicSuffixListStorageFactory,
|
||||
TopLevelDomainListStorageFactory
|
||||
{
|
||||
public function __construct(
|
||||
private readonly CacheInterface $cache,
|
||||
private readonly ClientInterface $client,
|
||||
private readonly RequestFactoryInterface $requestFactory
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateInterval|DateTimeInterface|Stringable|int|string|null $cacheTtl
|
||||
*/
|
||||
public function createPublicSuffixListStorage(string $cachePrefix = '', $cacheTtl = null): PublicSuffixListStorage
|
||||
{
|
||||
return new RulesStorage(
|
||||
new PublicSuffixListPsr16Cache($this->cache, $cachePrefix, $cacheTtl),
|
||||
new PublicSuffixListPsr18Client($this->client, $this->requestFactory)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateInterval|DateTimeInterface|Stringable|int|string|null $cacheTtl
|
||||
*/
|
||||
public function createTopLevelDomainListStorage(string $cachePrefix = '', $cacheTtl = null): TopLevelDomainListStorage
|
||||
{
|
||||
return new TopLevelDomainsStorage(
|
||||
new TopLevelDomainListPsr16Cache($this->cache, $cachePrefix, $cacheTtl),
|
||||
new TopLevelDomainListPsr18Client($this->client, $this->requestFactory)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
use Pdp\PublicSuffixList;
|
||||
|
||||
interface PublicSuffixListCache
|
||||
{
|
||||
/**
|
||||
* Retrieves the Public Suffix List from Cache.
|
||||
*/
|
||||
public function fetch(string $uri): ?PublicSuffixList;
|
||||
|
||||
/**
|
||||
* Caches the Public Suffix List.
|
||||
*
|
||||
* If a local cache already exists, it will be overwritten.
|
||||
*
|
||||
* Returns true if the action was successful, false otherwise
|
||||
*/
|
||||
public function remember(string $uri, PublicSuffixList $publicSuffixList): bool;
|
||||
|
||||
/**
|
||||
* Deletes the Public Suffix List entry.
|
||||
*
|
||||
* Returns true if the action was successful, false otherwise
|
||||
*/
|
||||
public function forget(string $uri): bool;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
use Pdp\PublicSuffixList;
|
||||
use Pdp\UnableToLoadPublicSuffixList;
|
||||
|
||||
interface PublicSuffixListClient
|
||||
{
|
||||
/**
|
||||
* @throws UnableToLoadPublicSuffixList
|
||||
*/
|
||||
public function get(string $uri): PublicSuffixList;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
use DateInterval;
|
||||
use DateTimeInterface;
|
||||
use Pdp\PublicSuffixList;
|
||||
use Psr\SimpleCache\CacheException;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use Stringable;
|
||||
use Throwable;
|
||||
use function md5;
|
||||
use function strtolower;
|
||||
|
||||
final class PublicSuffixListPsr16Cache implements PublicSuffixListCache
|
||||
{
|
||||
private readonly ?DateInterval $cacheTtl;
|
||||
|
||||
public function __construct(
|
||||
private readonly CacheInterface $cache,
|
||||
private readonly string $cachePrefix = '',
|
||||
DateInterval|DateTimeInterface|Stringable|int|string|null $cacheTtl = null
|
||||
) {
|
||||
$this->cacheTtl = TimeToLive::convert($cacheTtl);
|
||||
}
|
||||
|
||||
public function fetch(string $uri): ?PublicSuffixList
|
||||
{
|
||||
$cacheKey = $this->cacheKey($uri);
|
||||
$publicSuffixList = $this->cache->get($cacheKey);
|
||||
if (null === $publicSuffixList) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$publicSuffixList instanceof PublicSuffixList) {
|
||||
$this->cache->delete($cacheKey);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return $publicSuffixList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cache key according to the source URL.
|
||||
*/
|
||||
private function cacheKey(string $str): string
|
||||
{
|
||||
return $this->cachePrefix.md5(strtolower($str));
|
||||
}
|
||||
|
||||
public function remember(string $uri, PublicSuffixList $publicSuffixList): bool
|
||||
{
|
||||
try {
|
||||
return $this->cache->set($this->cacheKey($uri), $publicSuffixList, $this->cacheTtl);
|
||||
} catch (Throwable $exception) {
|
||||
if ($exception instanceof CacheException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
public function forget(string $uri): bool
|
||||
{
|
||||
return $this->cache->delete($this->cacheKey($uri));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
use Pdp\PublicSuffixList;
|
||||
use Pdp\Rules;
|
||||
use Pdp\UnableToLoadResource;
|
||||
use Psr\Http\Client\ClientExceptionInterface;
|
||||
use Psr\Http\Client\ClientInterface;
|
||||
use Psr\Http\Message\RequestFactoryInterface;
|
||||
|
||||
final class PublicSuffixListPsr18Client implements PublicSuffixListClient
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ClientInterface $client,
|
||||
private readonly RequestFactoryInterface $requestFactory
|
||||
) {
|
||||
}
|
||||
|
||||
public function get(string $uri): PublicSuffixList
|
||||
{
|
||||
$request = $this->requestFactory->createRequest('GET', $uri);
|
||||
try {
|
||||
$response = $this->client->sendRequest($request);
|
||||
} catch (ClientExceptionInterface $exception) {
|
||||
throw UnableToLoadResource::dueToUnavailableService($uri, $exception);
|
||||
}
|
||||
|
||||
if (400 <= $response->getStatusCode()) {
|
||||
throw UnableToLoadResource::dueToUnexpectedStatusCode($uri, $response->getStatusCode());
|
||||
}
|
||||
|
||||
return Rules::fromString($response->getBody());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
interface PublicSuffixListStorage extends PublicSuffixListClient
|
||||
{
|
||||
public function delete(string $uri): bool;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
use DateInterval;
|
||||
use DateTimeInterface;
|
||||
use Stringable;
|
||||
|
||||
interface PublicSuffixListStorageFactory
|
||||
{
|
||||
/**
|
||||
* @param DateInterval|DateTimeInterface|Stringable|int|string|null $cacheTtl storage TTL object should implement the __toString method
|
||||
*/
|
||||
public function createPublicSuffixListStorage(string $cachePrefix = '', $cacheTtl = null): PublicSuffixListStorage;
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
use Pdp\PublicSuffixList;
|
||||
|
||||
final class RulesStorage implements PublicSuffixListStorage
|
||||
{
|
||||
public function __construct(
|
||||
private readonly PublicSuffixListCache $cache,
|
||||
private readonly PublicSuffixListClient $client
|
||||
) {
|
||||
}
|
||||
|
||||
public function get(string $uri): PublicSuffixList
|
||||
{
|
||||
$publicSuffixList = $this->cache->fetch($uri);
|
||||
if (null !== $publicSuffixList) {
|
||||
return $publicSuffixList;
|
||||
}
|
||||
|
||||
$publicSuffixList = $this->client->get($uri);
|
||||
|
||||
$this->cache->remember($uri, $publicSuffixList);
|
||||
|
||||
return $publicSuffixList;
|
||||
}
|
||||
|
||||
public function delete(string $uri): bool
|
||||
{
|
||||
return $this->cache->forget($uri);
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
use DateInterval;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use InvalidArgumentException;
|
||||
use Stringable;
|
||||
use Throwable;
|
||||
use function filter_var;
|
||||
use const FILTER_VALIDATE_INT;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class TimeToLive
|
||||
{
|
||||
public static function fromDurationString(string $duration): DateInterval
|
||||
{
|
||||
try {
|
||||
set_error_handler(fn () => true);
|
||||
$interval = DateInterval::createFromDateString($duration);
|
||||
restore_error_handler();
|
||||
if (!$interval instanceof DateInterval) {
|
||||
throw new InvalidArgumentException(
|
||||
'The ttl value "'.$duration.'" can not be parsable by `DateInterval::createFromDateString`.'
|
||||
);
|
||||
}
|
||||
|
||||
} catch (Throwable $exception) {
|
||||
if (!$exception instanceof InvalidArgumentException) {
|
||||
throw new InvalidArgumentException(
|
||||
'The ttl value "'.$duration.'" can not be parsable by `DateInterval::createFromDateString`.',
|
||||
0,
|
||||
$exception
|
||||
);
|
||||
}
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
return $interval;
|
||||
}
|
||||
|
||||
public static function until(DateTimeInterface $date): DateInterval
|
||||
{
|
||||
return (new DateTimeImmutable('NOW', $date->getTimezone()))->diff($date, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a DateInterval relative to the current date and time.
|
||||
*
|
||||
* DEPRECATION WARNING! This method will be removed in the next major point release
|
||||
*
|
||||
* @deprecated 6.1.0 deprecated
|
||||
* @codeCoverageIgnore
|
||||
* @see TimeToLive::until
|
||||
*/
|
||||
public static function fromDateTimeInterface(DateTimeInterface $date): DateInterval
|
||||
{
|
||||
return self::until($date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a DateInterval from string parsing.
|
||||
*
|
||||
* DEPRECATION WARNING! This method will be removed in the next major point release
|
||||
*
|
||||
* @deprecated 6.1.0 deprecated
|
||||
* @see TimeToLive::fromDurationString
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @throws InvalidArgumentException if the value can not be parsable
|
||||
*
|
||||
*/
|
||||
public static function fromScalar(Stringable|int|string $duration): DateInterval
|
||||
{
|
||||
return self::fromDurationString((string) $duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the input data into a DateInterval object or null.
|
||||
*
|
||||
* @throws InvalidArgumentException if the value can not be computed
|
||||
*/
|
||||
public static function convert(DateInterval|DateTimeInterface|Stringable|int|string|null $ttl): ?DateInterval
|
||||
{
|
||||
if ($ttl instanceof Stringable) {
|
||||
$ttl = (string) $ttl;
|
||||
}
|
||||
|
||||
return match (true) {
|
||||
$ttl instanceof DateInterval || null === $ttl => $ttl,
|
||||
$ttl instanceof DateTimeInterface => self::until($ttl),
|
||||
is_int($ttl) => self::fromDurationString($ttl.' seconds'),
|
||||
false !== ($seconds = filter_var($ttl, FILTER_VALIDATE_INT)) => self::fromDurationString($seconds.' seconds'),
|
||||
default => self::fromDurationString($ttl),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
use Pdp\TopLevelDomainList;
|
||||
|
||||
interface TopLevelDomainListCache
|
||||
{
|
||||
/**
|
||||
* Retrieves the Top Level Domain List from the Cache.
|
||||
*/
|
||||
public function fetch(string $uri): ?TopLevelDomainList;
|
||||
|
||||
/**
|
||||
* Cache the Top Level Domain List.
|
||||
*
|
||||
* If a local cache already exists, it will be overwritten.
|
||||
*
|
||||
* Returns true if the action was successful, false otherwise
|
||||
*/
|
||||
public function remember(string $uri, TopLevelDomainList $topLevelDomainList): bool;
|
||||
|
||||
/**
|
||||
* Deletes the Top Level Domain List entry.
|
||||
*
|
||||
* Returns true if the action was successful, false otherwise
|
||||
*/
|
||||
public function forget(string $uri): bool;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
use Pdp\TopLevelDomainList;
|
||||
use Pdp\UnableToLoadTopLevelDomainList;
|
||||
|
||||
interface TopLevelDomainListClient
|
||||
{
|
||||
/**
|
||||
* @throws UnableToLoadTopLevelDomainList
|
||||
*/
|
||||
public function get(string $uri): TopLevelDomainList;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
use DateInterval;
|
||||
use DateTimeInterface;
|
||||
use Pdp\TopLevelDomainList;
|
||||
use Psr\SimpleCache\CacheException;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use Stringable;
|
||||
use Throwable;
|
||||
use function md5;
|
||||
use function strtolower;
|
||||
|
||||
final class TopLevelDomainListPsr16Cache implements TopLevelDomainListCache
|
||||
{
|
||||
private readonly ?DateInterval $cacheTtl;
|
||||
|
||||
public function __construct(
|
||||
private readonly CacheInterface $cache,
|
||||
private readonly string $cachePrefix = '',
|
||||
DateInterval|DateTimeInterface|Stringable|int|string|null $cacheTtl = null
|
||||
) {
|
||||
$this->cacheTtl = TimeToLive::convert($cacheTtl);
|
||||
}
|
||||
|
||||
public function fetch(string $uri): ?TopLevelDomainList
|
||||
{
|
||||
$cacheKey = $this->cacheKey($uri);
|
||||
$topLevelDomainList = $this->cache->get($cacheKey);
|
||||
if (null === $topLevelDomainList) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$topLevelDomainList instanceof TopLevelDomainList) {
|
||||
$this->cache->delete($cacheKey);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return $topLevelDomainList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cache key according to the source URL.
|
||||
*/
|
||||
private function cacheKey(string $str): string
|
||||
{
|
||||
return $this->cachePrefix.md5(strtolower($str));
|
||||
}
|
||||
|
||||
public function remember(string $uri, TopLevelDomainList $topLevelDomainList): bool
|
||||
{
|
||||
try {
|
||||
return $this->cache->set($this->cacheKey($uri), $topLevelDomainList, $this->cacheTtl);
|
||||
} catch (Throwable $exception) {
|
||||
if ($exception instanceof CacheException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
public function forget(string $uri): bool
|
||||
{
|
||||
return $this->cache->delete($this->cacheKey($uri));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
use Pdp\TopLevelDomainList;
|
||||
use Pdp\TopLevelDomains;
|
||||
use Pdp\UnableToLoadResource;
|
||||
use Psr\Http\Client\ClientExceptionInterface;
|
||||
use Psr\Http\Client\ClientInterface;
|
||||
use Psr\Http\Message\RequestFactoryInterface;
|
||||
|
||||
final class TopLevelDomainListPsr18Client implements TopLevelDomainListClient
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ClientInterface $client,
|
||||
private readonly RequestFactoryInterface $requestFactory
|
||||
) {
|
||||
}
|
||||
|
||||
public function get(string $uri): TopLevelDomainList
|
||||
{
|
||||
$request = $this->requestFactory->createRequest('GET', $uri);
|
||||
try {
|
||||
$response = $this->client->sendRequest($request);
|
||||
} catch (ClientExceptionInterface $exception) {
|
||||
throw UnableToLoadResource::dueToUnavailableService($uri, $exception);
|
||||
}
|
||||
|
||||
if (400 <= $response->getStatusCode()) {
|
||||
throw UnableToLoadResource::dueToUnexpectedStatusCode($uri, $response->getStatusCode());
|
||||
}
|
||||
|
||||
return TopLevelDomains::fromString($response->getBody());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
interface TopLevelDomainListStorage extends TopLevelDomainListClient
|
||||
{
|
||||
public function delete(string $uri): bool;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
use DateInterval;
|
||||
use DateTimeInterface;
|
||||
use Stringable;
|
||||
|
||||
interface TopLevelDomainListStorageFactory
|
||||
{
|
||||
/**
|
||||
* @param DateInterval|DateTimeInterface|Stringable|int|string|null $cacheTtl storage TTL object should implement the __toString method
|
||||
*/
|
||||
public function createTopLevelDomainListStorage(string $cachePrefix = '', $cacheTtl = null): TopLevelDomainListStorage;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pdp\Storage;
|
||||
|
||||
use Pdp\TopLevelDomainList;
|
||||
|
||||
final class TopLevelDomainsStorage implements TopLevelDomainListStorage
|
||||
{
|
||||
public function __construct(
|
||||
private readonly TopLevelDomainListCache $cache,
|
||||
private readonly TopLevelDomainListClient $client
|
||||
) {
|
||||
}
|
||||
|
||||
public function get(string $uri): TopLevelDomainList
|
||||
{
|
||||
$topLevelDomains = $this->cache->fetch($uri);
|
||||
if (null !== $topLevelDomains) {
|
||||
return $topLevelDomains;
|
||||
}
|
||||
|
||||
$topLevelDomains = $this->client->get($uri);
|
||||
|
||||
$this->cache->remember($uri, $topLevelDomains);
|
||||
|
||||
return $topLevelDomains;
|
||||
}
|
||||
|
||||
public function delete(string $uri): bool
|
||||
{
|
||||
return $this->cache->forget($uri);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user