Skip to content

Commit de41cc8

Browse files
committed
Model\Server namespace deprecated
1 parent ebfe31d commit de41cc8

File tree

15 files changed

+313
-25
lines changed

15 files changed

+313
-25
lines changed

src/Controller/Webhook/AddListener.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use Psr\Http\Server\RequestHandlerInterface;
1111
use SimpleAsFuck\ApiToolkit\Factory\Server\ResponseFactory;
1212
use SimpleAsFuck\ApiToolkit\Factory\Server\Validator;
13-
use SimpleAsFuck\ApiToolkit\Model\Server\ApiException;
13+
use SimpleAsFuck\ApiToolkit\Data\Server\ApiException;
1414
use SimpleAsFuck\ApiToolkit\Service\Webhook\ParamsTransformer;
1515
use SimpleAsFuck\ApiToolkit\Service\Webhook\Repository;
1616
use SimpleAsFuck\ApiToolkit\Service\Webhook\WebhookTransformer;

src/Data/Server/ApiException.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleAsFuck\ApiToolkit\Data\Server;
6+
7+
use Kayex\HttpCodes;
8+
use SimpleAsFuck\ApiToolkit\Data\Common\ProblemDetail;
9+
10+
/** @phpstan-ignore-next-line */
11+
class ApiException extends \SimpleAsFuck\ApiToolkit\Model\Server\ApiException
12+
{
13+
/**
14+
* @param non-empty-string|null $message https://datatracker.ietf.org/doc/html/rfc9457#name-extension-members available to server and client for logging or debugging purposes MUST contain only English message
15+
* @param ProblemDetail|int<100, 505> $problemDetail ProblemDetail | HTTP status
16+
* @param object{message?: non-empty-string|null, type?: non-empty-string|null, title?: non-empty-string|null, status?: int|null, detail?: non-empty-string|null, instance?: non-empty-string|null}|null $problemDetailExtensions https://datatracker.ietf.org/doc/html/rfc9457#name-extension-members all properties MUST be json serializable
17+
* @param non-empty-string|null $internalMessage available only to server for logging or debugging purposes MUST NOT leave server environment
18+
*/
19+
public function __construct(
20+
?string $message = null,
21+
private readonly ProblemDetail|int $problemDetail = HttpCodes::HTTP_INTERNAL_SERVER_ERROR,
22+
private readonly ?object $problemDetailExtensions = null,
23+
private readonly ?string $internalMessage = null,
24+
?\Throwable $previous = null
25+
) {
26+
/** @phpstan-ignore-next-line */
27+
parent::__construct(
28+
$message,
29+
$problemDetail,
30+
$problemDetailExtensions,
31+
$internalMessage,
32+
$previous,
33+
);
34+
}
35+
36+
public function getProblemDetail(): ?ProblemDetail
37+
{
38+
if (is_int($this->problemDetail)) {
39+
return null;
40+
}
41+
42+
return $this->problemDetail;
43+
}
44+
45+
public function getProblemDetailExtensions(): ?object
46+
{
47+
return $this->problemDetailExtensions;
48+
}
49+
50+
/**
51+
* @return non-empty-string|null
52+
*/
53+
public function getInternalMessage(): ?string
54+
{
55+
return $this->internalMessage;
56+
}
57+
}

src/Data/Server/HeaderRule.php

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleAsFuck\ApiToolkit\Data\Server;
6+
7+
use SimpleAsFuck\Validator\Factory\Exception;
8+
use SimpleAsFuck\Validator\Model\RuleChain;
9+
use SimpleAsFuck\Validator\Model\Validated;
10+
use SimpleAsFuck\Validator\Rule\ArrayRule\Collection;
11+
use SimpleAsFuck\Validator\Rule\ArrayRule\TypedKey;
12+
use SimpleAsFuck\Validator\Rule\String\RegexMatch;
13+
use SimpleAsFuck\Validator\Rule\String\StringRule;
14+
15+
/** @phpstan-ignore-next-line */
16+
final class HeaderRule extends \SimpleAsFuck\ApiToolkit\Model\Server\HeaderRule
17+
{
18+
/**
19+
* @param Validated<array<array<string>>> $validated
20+
*/
21+
public function __construct(
22+
private readonly Exception $exceptionFactory,
23+
private readonly Validated $validated,
24+
) {
25+
/** @phpstan-ignore-next-line */
26+
parent::__construct($exceptionFactory, $validated);
27+
}
28+
29+
/**
30+
* @param non-empty-string $key
31+
*/
32+
public function key(string $key, bool $caseSensitive = false): StringRule
33+
{
34+
$values = $this->headerValues($caseSensitive);
35+
$values = $values[$caseSensitive ? $key : strtolower($key)] ?? [];
36+
$value = array_pop($values);
37+
return new StringRule($this->exceptionFactory, new RuleChain(), new Validated($value), 'Request header: '.$key);
38+
}
39+
40+
/**
41+
* @template TMapped
42+
* @param non-empty-string $key
43+
* @param callable(StringRule): TMapped $callable
44+
* @return Collection<TMapped>
45+
*/
46+
public function keyOf(string $key, callable $callable, bool $caseSensitive = false): Collection
47+
{
48+
$values = $this->headerValues($caseSensitive);
49+
$values = $values[$caseSensitive ? $key : strtolower($key)] ?? null;
50+
return new Collection(
51+
$this->exceptionFactory,
52+
/** @phpstan-ignore-next-line */
53+
new RuleChain(),
54+
new Validated($values),
55+
'Request header: '.$key,
56+
fn (TypedKey $index) => $callable($index->string())
57+
);
58+
}
59+
60+
/**
61+
* method will return rule with regex match for value of http standard authorization header
62+
*
63+
* @param non-empty-string $type
64+
*/
65+
public function authorization(string $type): RegexMatch
66+
{
67+
return $this
68+
->key('Authorization')
69+
->parseRegex('/^' . preg_quote($type, '/') . ' (?P<value>.+)$/')
70+
->match('value')
71+
;
72+
}
73+
74+
/**
75+
* @return array<array<string>>|null
76+
*/
77+
private function headerValues(bool $caseSensitive): ?array
78+
{
79+
$values = $this->validated->value;
80+
if ($caseSensitive) {
81+
return $values;
82+
}
83+
84+
return $values !== null ? array_change_key_case($values, CASE_LOWER) : $values;
85+
}
86+
}

src/Data/Server/QueryRule.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleAsFuck\ApiToolkit\Data\Server;
6+
7+
use SimpleAsFuck\ApiToolkit\Service\Server\UserQueryRule;
8+
use SimpleAsFuck\Validator\Factory\Exception;
9+
use SimpleAsFuck\Validator\Model\RuleChain;
10+
use SimpleAsFuck\Validator\Model\Validated;
11+
use SimpleAsFuck\Validator\Rule\ArrayRule\Key;
12+
use SimpleAsFuck\Validator\Rule\ArrayRule\StringTypedKey;
13+
use SimpleAsFuck\Validator\Rule\Object\ClassFromArray;
14+
15+
/** @phpstan-ignore-next-line */
16+
final readonly class QueryRule extends \SimpleAsFuck\ApiToolkit\Model\Server\QueryRule
17+
{
18+
/**
19+
* @param Validated<array<mixed>> $queryParams
20+
*/
21+
public function __construct(
22+
private Exception $exceptionFactory,
23+
private Validated $queryParams
24+
) {
25+
/** @phpstan-ignore-next-line */
26+
parent::__construct($exceptionFactory, $queryParams);
27+
}
28+
29+
/**
30+
* @param non-empty-string $key
31+
*/
32+
public function key(string $key): StringTypedKey
33+
{
34+
$ruleChain = new RuleChain();
35+
$valueName = 'Request query parameter: '.$key;
36+
return new StringTypedKey(
37+
$this->exceptionFactory,
38+
/** @phpstan-ignore-next-line */
39+
$ruleChain,
40+
$this->queryParams,
41+
$valueName,
42+
new Key(
43+
$this->exceptionFactory,
44+
/** @phpstan-ignore-next-line */
45+
$ruleChain,
46+
$this->queryParams,
47+
$valueName,
48+
$key
49+
)
50+
);
51+
}
52+
53+
/**
54+
* @template TClass of object
55+
* @param UserQueryRule<TClass> $userQueryRule
56+
* @return ClassFromArray<QueryRule, TClass>
57+
* @phpstan-ignore-next-line
58+
*/
59+
public function class(UserQueryRule $userQueryRule): ClassFromArray
60+
{
61+
/** @phpstan-ignore-next-line */
62+
return new ClassFromArray(
63+
$this->exceptionFactory,
64+
/** @phpstan-ignore-next-line */
65+
new RuleChain(),
66+
$this->queryParams,
67+
'Request query',
68+
$this,
69+
$userQueryRule
70+
);
71+
}
72+
}

src/Data/Server/RequestRules.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleAsFuck\ApiToolkit\Data\Server;
6+
7+
use Psr\Http\Message\ServerRequestInterface;
8+
use SimpleAsFuck\ApiToolkit\Data\Webhook\WebhookRules;
9+
use SimpleAsFuck\ApiToolkit\Service\Common\JsonService;
10+
use SimpleAsFuck\ApiToolkit\Service\Webhook\WebhookTransformer;
11+
use SimpleAsFuck\Validator\Factory\Exception;
12+
use SimpleAsFuck\Validator\Model\Validated;
13+
use SimpleAsFuck\Validator\Rule\General\Rules;
14+
15+
/** @phpstan-ignore-next-line */
16+
final readonly class RequestRules extends \SimpleAsFuck\ApiToolkit\Model\Server\RequestRules
17+
{
18+
public function __construct(
19+
private Exception $exceptionFactory,
20+
private ServerRequestInterface $request
21+
) {
22+
/** @phpstan-ignore-next-line */
23+
parent::__construct($exceptionFactory, $request);
24+
}
25+
26+
public function header(): HeaderRule
27+
{
28+
return new HeaderRule($this->exceptionFactory, new Validated($this->request->getHeaders()));
29+
}
30+
31+
public function query(): QueryRule
32+
{
33+
/** @var Validated<array<mixed>> $validate */
34+
$validate = new Validated($this->request->getQueryParams());
35+
return new QueryRule($this->exceptionFactory, $validate);
36+
}
37+
38+
/**
39+
* @param int $jsonDecodeFlags bitmask https://www.php.net/manual/en/function.json-decode.php
40+
*/
41+
public function json(bool $allowInvalidJson = false, int $jsonDecodeFlags = 0): Rules
42+
{
43+
return JsonService::jsonDecode($this->request->getBody()->getContents(), 'Request body', $this->exceptionFactory, $allowInvalidJson, $jsonDecodeFlags);
44+
}
45+
46+
/**
47+
* this is experimental url query parser,
48+
* url after question mark is decoded and parsed as json,
49+
* parsing json directly from query string may not be supported by all http libraries or tools
50+
*/
51+
public function queryJson(bool $allowInvalidJson = false): Rules
52+
{
53+
$query = $this->request->getUri()->getQuery();
54+
$query = \urldecode($query);
55+
56+
$query = \json_decode($query);
57+
if (\json_last_error() !== JSON_ERROR_NONE) {
58+
if ($allowInvalidJson) {
59+
$query = null;
60+
} else {
61+
throw $this->exceptionFactory->create('Request query must be valid json which is url encoded before concatenation after question mark');
62+
}
63+
}
64+
65+
return new Rules($this->exceptionFactory, 'Request query: json', new Validated($query));
66+
}
67+
68+
public function webhook(): WebhookRules
69+
{
70+
return new WebhookRules(
71+
$this->exceptionFactory,
72+
$this->json()->object()->class(new WebhookTransformer())->notNull(),
73+
);
74+
}
75+
}

src/Factory/Server/ApiValidationException.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
namespace SimpleAsFuck\ApiToolkit\Factory\Server;
66

77
use Kayex\HttpCodes;
8-
use SimpleAsFuck\ApiToolkit\Model\Server\ApiException;
8+
use SimpleAsFuck\ApiToolkit\Data\Server\ApiException;
99
use SimpleAsFuck\Validator\Factory\Exception;
1010

1111
final class ApiValidationException extends Exception

src/Factory/Server/Validator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
namespace SimpleAsFuck\ApiToolkit\Factory\Server;
66

77
use Psr\Http\Message\ServerRequestInterface;
8-
use SimpleAsFuck\ApiToolkit\Model\Server\RequestRules;
8+
use SimpleAsFuck\ApiToolkit\Data\Server\RequestRules;
99
use SimpleAsFuck\Validator\Factory\Exception;
1010
use SimpleAsFuck\Validator\Model\RuleChain;
1111
use SimpleAsFuck\Validator\Model\Validated;

src/Factory/Symfony/Validator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
namespace SimpleAsFuck\ApiToolkit\Factory\Symfony;
66

77
use GuzzleHttp\Psr7\HttpFactory;
8-
use SimpleAsFuck\ApiToolkit\Model\Server\RequestRules;
8+
use SimpleAsFuck\ApiToolkit\Data\Server\RequestRules;
99
use SimpleAsFuck\Validator\Factory\Exception;
1010
use SimpleAsFuck\Validator\Model\RuleChain;
1111
use SimpleAsFuck\Validator\Model\Validated;

src/Model/Server/ApiException.php

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Kayex\HttpCodes;
88
use SimpleAsFuck\ApiToolkit\Data\Common\ProblemDetail;
99

10+
/** @deprecated use SimpleAsFuck\ApiToolkit\Data\Server\ApiException */
1011
class ApiException extends \RuntimeException
1112
{
1213
private readonly ProblemDetail|int $problemDetail;
@@ -19,31 +20,24 @@ class ApiException extends \RuntimeException
1920
*/
2021
public function __construct(
2122
?string $message = null,
22-
/** @phpstan-ignore-next-line */
2323
ProblemDetail|\SimpleAsFuck\ApiToolkit\DataObject\Common\ProblemDetail|int $problemDetail = HttpCodes::HTTP_INTERNAL_SERVER_ERROR,
2424
private readonly ?object $problemDetailExtensions = null,
2525
private readonly ?string $internalMessage = null,
2626
?\Throwable $previous = null
2727
) {
2828
if ($problemDetail instanceof \SimpleAsFuck\ApiToolkit\DataObject\Common\ProblemDetail) {
2929
$problemDetail = new ProblemDetail(
30-
/** @phpstan-ignore-next-line */
3130
$problemDetail->type,
32-
/** @phpstan-ignore-next-line */
3331
$problemDetail->status,
34-
/** @phpstan-ignore-next-line */
3532
$problemDetail->title,
36-
/** @phpstan-ignore-next-line */
3733
$problemDetail->detail,
38-
/** @phpstan-ignore-next-line */
3934
$problemDetail->instance,
4035
);
4136
}
4237

4338
if (is_int($problemDetail)) {
4439
$code = $problemDetail;
4540
} else {
46-
/** @phpstan-ignore-next-line */
4741
$code = $problemDetail->status ?? HttpCodes::HTTP_INTERNAL_SERVER_ERROR;
4842
}
4943
$this->problemDetail = $problemDetail;

src/Model/Server/HeaderRule.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
use SimpleAsFuck\Validator\Rule\String\RegexMatch;
1313
use SimpleAsFuck\Validator\Rule\String\StringRule;
1414

15-
final class HeaderRule
15+
/** @deprecated use SimpleAsFuck\ApiToolkit\Data\Server\HeaderRule */
16+
class HeaderRule
1617
{
1718
/**
1819
* @param Validated<array<array<string>>> $validated

0 commit comments

Comments
 (0)