Skip to content

Commit

Permalink
Improve codebase
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed Nov 12, 2024
1 parent 568f515 commit 8d5d177
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 81 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ $statusCode = $response->getStatusCode(); //304

$cacheStatus = Field::fromHttpValue($headerLine, $statusCode);
//you can also use the $_SERVER array
$cacheStatus = Field::fromSapi($_SERVER);
$cacheStatus = Field::fromSapi($_SERVER, Field::SAPI_NAME);

count($cacheStatus); // returns 2 (the number of HandledRequestCache instances parsed)

Expand Down
10 changes: 3 additions & 7 deletions src/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function __construct(HandledRequestCache|Stringable|string ...$caches)
{
$this->caches = array_map(fn (HandledRequestCache|Stringable|string $value) => match (true) {
$value instanceof HandledRequestCache => $value,
default => HandledRequestCache::fromHttpValue((string) $value),
default => HandledRequestCache::fromHttpValue($value),
}, $caches);
}

Expand Down Expand Up @@ -67,7 +67,7 @@ private static function fromStructuredField(OuterList $list, ?int $statusCode =
return new self(...$list->map(
fn (Item|InnerList $item, int $offset): HandledRequestCache => match (true) {
$item instanceof Item => HandledRequestCache::fromStructuredField($item, $statusCode),
default => throw new Exception('The list must only contain Items.'),
default => throw new Exception('The list must only contain item structure representing handled request cache.'),
}
));
}
Expand Down Expand Up @@ -188,11 +188,7 @@ public function has(int ...$indexes): bool
*/
public function contains(Token|string $serverIdentifier): bool
{
$validate = fn (Token|string $token): bool => match (true) {
$token instanceof Token => $serverIdentifier instanceof Token && $serverIdentifier->equals($token),
default => $token === $serverIdentifier,
};

$validate = fn (Token|string $token): bool => $token instanceof Token ? $token->equals($serverIdentifier) : $token === $serverIdentifier;
foreach ($this->caches as $member) {
if ($validate($member->servedBy)) {
return true;
Expand Down
12 changes: 12 additions & 0 deletions src/Forward.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,16 @@ public function toStructuredField(): Parameters
->append(Properties::Collapsed->value, $this->collapsed)
->filter(fn (array $pair): bool => false !== $pair[1]->value());
}

public function equals(mixed $other): bool
{
return match (true) {
!$other instanceof self,
!$other->reason->equals($this->reason),
$other->statusCode !== $this->statusCode,
$other->stored !== $this->stored,
$other->collapsed !== $this->collapsed => false,
default => true,
};
}
}
27 changes: 13 additions & 14 deletions src/ForwardedReason.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,15 @@ public static function fromToken(Token|Stringable|string $token): self

public static function tryFromToken(Token|Stringable|string|null $token): ?self
{
if (null === $token) {
return null;
}

if ($token instanceof Token) {
return self::tryFrom($token->toString());
}

$token = Token::tryFromString($token);
if (!$token instanceof Token) {
return null;
}
$token = match (true) {
$token instanceof Token => $token->toString(),
default => (string) $token,
};

return self::tryFrom($token->toString());
return match (true) {
in_array($token, self::list(), true) => self::from($token),
default => null,
};
}

public function description(): string
Expand Down Expand Up @@ -86,6 +81,10 @@ public function isOneOf(mixed ...$other): bool
*/
public static function list(): array
{
return array_map(fn (self $case) => $case->value, self::cases());
static $list;

$list ??= array_map(fn (self $case) => $case->value, self::cases());

return $list;
}
}
107 changes: 51 additions & 56 deletions src/HandledRequestCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use Bakame\Http\StructuredFields\Item;
use Bakame\Http\StructuredFields\Parameters;
use Bakame\Http\StructuredFields\StructuredFieldError;
use Bakame\Http\StructuredFields\StructuredFieldProvider;
use Bakame\Http\StructuredFields\Token;
use Bakame\Http\StructuredFields\Type;
Expand All @@ -23,11 +22,11 @@ final class HandledRequestCache implements StructuredFieldProvider, Stringable
{
private function __construct(
public readonly Token|string $servedBy,
public readonly bool $hit = true,
public readonly ?Forward $forward = null,
public readonly ?int $ttl = null,
public readonly ?string $key = null,
public readonly Token|string|null $detail = null,
public readonly bool $hit,
public readonly ?Forward $forward,
public readonly ?int $ttl,
public readonly ?string $key,
public readonly Token|string|null $detail,
) {
match (true) {
!Type::Token->supports($this->servedBy) && !Type::String->supports($this->servedBy) => throw new Exception('The handled request cache identifier must be a Token or a string.'),
Expand All @@ -43,25 +42,11 @@ private function __construct(
/**
* Returns an instance from a Header Line and the optional response status code.
*/
public static function fromHttpValue(string $value, ?int $statusCode = null): self
public static function fromHttpValue(Stringable|string $value, ?int $statusCode = null): self
{
return self::fromStructuredField(Item::fromHttpValue($value), $statusCode);
}

private static function validator(): ItemValidator
{
static $validator;

$validator ??= ItemValidator::new()
->value(fn (mixed $value): bool|string => match (true) {
Type::fromVariable($value)->isOneOf(Type::String, Type::Token) => true,
default => 'The cache name must be a HTTP structured field token or string.',
})
->parameters(Properties::validator());

return $validator;
}

/**
* Returns an instance from a Structured Field Item and the optional response status code.
*/
Expand Down Expand Up @@ -94,36 +79,53 @@ public static function fromStructuredField(Item $item, ?int $statusCode = null):
*/
$parameters = $parsedItem->parameters;

$forward = null === $parameters[Properties::Forward->value] ? null : Forward::fromReason($parameters[Properties::Forward->value])
->statusCode($parameters[Properties::ForwardStatusCode->value] ?? $statusCode)
->collapsed($parameters[Properties::Collapsed->value])
->stored($parameters[Properties::Stored->value]);

return new self(
$servedBy,
$parameters[Properties::Hit->value],
null !== $parameters[Properties::Forward->value] ? Forward::fromReason($parameters[Properties::Forward->value])
->statusCode($parameters[Properties::ForwardStatusCode->value] ?? $statusCode)
->collapsed($parameters[Properties::Collapsed->value])
->stored($parameters[Properties::Stored->value]) : null,
$parameters[Properties::TimeToLive->value],
$parameters[Properties::Key->value],
$parameters[Properties::Detail->value],
servedBy: $servedBy,
hit: $parameters[Properties::Hit->value],
forward: $forward,
ttl: $parameters[Properties::TimeToLive->value],
key: $parameters[Properties::Key->value],
detail: $parameters[Properties::Detail->value],
);
}

private static function validator(): ItemValidator
{
static $validator;

$validator ??= ItemValidator::new()
->value(fn (mixed $value): bool|string => match (true) {
Type::fromVariable($value)->isOneOf(Type::String, Type::Token) => true,
default => 'The cache name must be a HTTP structured field token or string.',
})
->parameters(Properties::validator());

return $validator;
}

/**
* Returns a new instance with a server identifier as a string which is already hit.
*/
public static function serverIdentifierAsString(string $serverIdentifier): self
public static function serverIdentifierAsString(string $identifier): self
{
return new self($serverIdentifier);
return new self($identifier, hit: true, forward: null, ttl: null, key: null, detail: null);
}

/**
* Returns a new instance with a server identifier as a Token which is already hit.
*/
public static function serverIdentifierAsToken(Token|string $identifier): self
{
return new self(match (true) {
$identifier instanceof Token => $identifier,
default => Token::fromString($identifier)
});
if (!$identifier instanceof Token) {
$identifier = Token::tryFromString($identifier) ?? throw new Exception('The handled request cache identifier must be a valid Token.');
}

return new self($identifier, hit: true, forward: null, ttl:null, key:null, detail: null);
}

/**
Expand All @@ -137,9 +139,6 @@ public function servedBy(): string
};
}

/**
* @throws StructuredFieldError
*/
public function __toString(): string
{
return $this->toStructuredField()->toHttpValue();
Expand Down Expand Up @@ -185,19 +184,17 @@ public function wasHit(): self
*/
public function wasForwarded(Forward|ForwardedReason|Token|string $forward): self
{
if (is_string($forward)) {
$forward = Token::fromString($forward);
}

if ($forward instanceof Token) {
$forward = ForwardedReason::fromToken($forward);
}

if ($forward instanceof ForwardedReason) {
$forward = Forward::fromReason($forward);
}
$forward = match (true) {
is_string($forward) => Forward::fromReason(ForwardedReason::tryFrom($forward) ?? throw new Exception('The submitted string is not a valid server identifier.')),
$forward instanceof Token => Forward::fromReason(ForwardedReason::fromToken($forward)),
$forward instanceof ForwardedReason => Forward::fromReason($forward),
default => $forward,
};

return new self($this->servedBy, false, $forward, $this->ttl, $this->key, $this->detail);
return match (true) {
$forward->equals($this->forward) => $this,
default => new self($this->servedBy, false, $forward, $this->ttl, $this->key, $this->detail),
};
}

/**
Expand Down Expand Up @@ -240,11 +237,9 @@ public function withDetailAsString(?string $detail): self
*/
public function withDetailAsToken(Token|string|null $detail): self
{
$detail = match (true) {
$detail instanceof Token,
null === $detail => $detail,
default => Token::fromString($detail),
};
if (is_string($detail)) {
$detail = Token::tryFromString($detail) ?? throw new Exception('The handled request cache detail must be a valid Token.');
}

return match (true) {
$this->detail === $detail,
Expand Down
6 changes: 3 additions & 3 deletions src/HandledRequestCacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ public function it_can_create_a_cache_status_with_ttl(): void
#[Test]
public function it_can_create_a_cache_status_progressively(): void
{
$forward = new Forward(reason:ForwardedReason::Miss, statusCode: 304, collapsed: true);
$cacheForwarded = HandledRequestCache::serverIdentifierAsString(serverIdentifier: '10.0.0.7')
$forward = new Forward(reason: ForwardedReason::Miss, statusCode: 304, collapsed: true);
$cacheForwarded = HandledRequestCache::serverIdentifierAsString('10.0.0.7')
->withDetailAsString('This is a detail')
->withTtl(376)
->wasForwarded($forward)
Expand Down Expand Up @@ -114,7 +114,7 @@ public function parsing_a_response_header(): void
#[Test]
public function it_can_update_the_forward_parameters(): void
{
$cacheForwarded = HandledRequestCache::serverIdentifierAsString(serverIdentifier: '10.0.0.7')
$cacheForwarded = HandledRequestCache::serverIdentifierAsString('10.0.0.7')
->wasForwarded('miss');

self::assertInstanceOf(Forward::class, $cacheForwarded->forward);
Expand Down

0 comments on commit 8d5d177

Please sign in to comment.