From 1e12e5e6b943b1a9969e82e2a545da82e299ab5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bar=C3=A1=C5=A1ek?= Date: Mon, 13 Jul 2020 14:38:07 +0200 Subject: [PATCH] #12 Define basic code conventions --- src/ApiManager.php | 19 ++++- src/Endpoint/BaseEndpoint.php | 20 ++++-- src/Endpoint/Endpoint.php | 3 + src/Entity/Convention.php | 130 ++++++++++++++++++++++++++++++++++ src/Response/BaseResponse.php | 26 +++---- 5 files changed, 179 insertions(+), 19 deletions(-) create mode 100644 src/Entity/Convention.php diff --git a/src/ApiManager.php b/src/ApiManager.php index 2b0933e..8fe4a6f 100644 --- a/src/ApiManager.php +++ b/src/ApiManager.php @@ -7,6 +7,7 @@ use Baraja\RuntimeInvokeException; use Baraja\ServiceMethodInvoker; +use Baraja\StructuredApi\Entity\Convention; use Nette\Caching\Cache; use Nette\Caching\IStorage; use Nette\DI\Container; @@ -31,6 +32,9 @@ final class ApiManager /** @var Cache */ private $cache; + /** @var Convention */ + private $convention; + /** @var string[] (endpointPath => endpointType) */ private $endpoints = []; @@ -47,6 +51,7 @@ public function __construct(Container $container, Request $request, Response $re $this->request = $request; $this->response = $response; $this->cache = new Cache($storage, 'structured-api'); + $this->convention = new Convention; } @@ -84,7 +89,7 @@ public function run(string $path, ?array $params = [], ?string $method = null, b Debugger::log($e); } - $response = new JsonResponse([ + $response = new JsonResponse($this->convention, [ 'state' => 'error', 'message' => $isDebugger && Debugger::isEnabled() === true ? $e->getMessage() : null, 'code' => $code = (($code = $e->getCode()) === 0 ? 500 : $code), @@ -138,6 +143,15 @@ public function get(string $path, ?array $params = [], ?string $method = null): } + /** + * @return Convention + */ + public function getConvention(): Convention + { + return $this->convention; + } + + /** * @return string[] */ @@ -196,6 +210,7 @@ public function createEndpointInstance(string $className, array $params): Endpoi $endpoint->{$property} = $this->container->getByType($service); } + $endpoint->setConvention($this->convention); $endpoint->setData($params); return $endpoint; @@ -287,7 +302,7 @@ private function invokeActionMethod(Endpoint $endpoint, string $action, string $ } if ($method !== 'GET' && $response === null) { - $response = new JsonResponse(['state' => 'ok']); + $response = new JsonResponse($this->convention, ['state' => 'ok']); } $endpoint->saveState(); diff --git a/src/Endpoint/BaseEndpoint.php b/src/Endpoint/BaseEndpoint.php index 3a2da62..a65167a 100644 --- a/src/Endpoint/BaseEndpoint.php +++ b/src/Endpoint/BaseEndpoint.php @@ -5,6 +5,7 @@ namespace Baraja\StructuredApi; +use Baraja\StructuredApi\Entity\Convention; use Nette\Application\LinkGenerator; use Nette\Application\UI\InvalidLinkException; use Nette\Caching\Cache; @@ -30,6 +31,9 @@ abstract class BaseEndpoint implements Endpoint */ public $container; + /** @var Convention */ + protected $convention; + /** @var mixed[] */ protected $data = []; @@ -93,6 +97,12 @@ final public function setData(array $data): void } + final public function setConvention(Convention $convention): void + { + $this->convention = $convention; + } + + /** * Send raw data to output. * @@ -109,7 +119,7 @@ final public function sendJson(array $haystack, int $httpCode = 200): void $this->messages = []; // Reset for next response } - throw new ThrowResponse(new JsonResponse($haystack, $httpCode)); + throw new ThrowResponse(new JsonResponse($this->convention, $haystack, $httpCode)); } @@ -122,7 +132,7 @@ final public function sendError(string $message, ?int $code = null): void $this->sendJson([ 'state' => 'error', 'message' => $message, - 'code' => $code = $code ?? 500, + 'code' => $code = $code ?? $this->convention->getDefaultErrorCode(), ], $code); } @@ -130,14 +140,14 @@ final public function sendError(string $message, ?int $code = null): void /** * @param mixed[] $data * @param string|null $message - * @param int $code + * @param int|null $code */ - final public function sendOk(array $data = [], ?string $message = null, int $code = 200): void + final public function sendOk(array $data = [], ?string $message = null, ?int $code = null): void { $this->sendJson([ 'state' => 'ok', 'message' => $message, - 'code' => $code, + 'code' => $code = $code ?? $this->convention->getDefaultOkCode(), 'data' => $data, ], $code); } diff --git a/src/Endpoint/Endpoint.php b/src/Endpoint/Endpoint.php index a4f69d0..6d7bf4f 100644 --- a/src/Endpoint/Endpoint.php +++ b/src/Endpoint/Endpoint.php @@ -6,6 +6,7 @@ use Baraja\Service; +use Baraja\StructuredApi\Entity\Convention; interface Endpoint extends Service { @@ -14,6 +15,8 @@ interface Endpoint extends Service */ public function setData(array $data): void; + public function setConvention(Convention $convention): void; + public function startup(): void; public function startupCheck(): void; diff --git a/src/Entity/Convention.php b/src/Entity/Convention.php new file mode 100644 index 0000000..a484f16 --- /dev/null +++ b/src/Entity/Convention.php @@ -0,0 +1,130 @@ +dateTimeFormat; + } + + + /** + * @param string $dateTimeFormat + */ + public function setDateTimeFormat(string $dateTimeFormat): void + { + if ($dateTimeFormat === '') { + throw new \InvalidArgumentException('DateTime format can not be empty string.'); + } + + $this->dateTimeFormat = $dateTimeFormat; + } + + + /** + * @return int + */ + public function getDefaultErrorCode(): int + { + return $this->defaultErrorCode; + } + + + /** + * @param int $code + */ + public function setDefaultErrorCode(int $code): void + { + if ($code < 100 || $code > 999) { + throw new \InvalidArgumentException('Code must be in interval (100; 999), but ' . $code . ' given.'); + } + + $this->defaultErrorCode = $code; + } + + + /** + * @return int + */ + public function getDefaultOkCode(): int + { + return $this->defaultOkCode; + } + + + /** + * @param int $code + */ + public function setDefaultOkCode(int $code): void + { + if ($code < 100 || $code > 999) { + throw new \InvalidArgumentException('Code must be in interval (100; 999), but ' . $code . ' given.'); + } + + $this->defaultOkCode = $code; + } + + + /** + * @return bool + */ + public function isRewriteTooStringMethod(): bool + { + return $this->rewriteTooStringMethod; + } + + + /** + * @param bool $rewriteTooStringMethod + */ + public function setRewriteTooStringMethod(bool $rewriteTooStringMethod): void + { + $this->rewriteTooStringMethod = $rewriteTooStringMethod; + } + + + /** + * @return string[] + */ + public function getKeysToHide(): array + { + return $this->keysToHide; + } + + + /** + * @param string[] $keysToHide + */ + public function setKeysToHide(array $keysToHide): void + { + $this->keysToHide = $keysToHide; + } +} diff --git a/src/Response/BaseResponse.php b/src/Response/BaseResponse.php index d9a2e74..8359ea6 100644 --- a/src/Response/BaseResponse.php +++ b/src/Response/BaseResponse.php @@ -5,6 +5,7 @@ namespace Baraja\StructuredApi; +use Baraja\StructuredApi\Entity\Convention; use Baraja\StructuredApi\Entity\ItemsList; use Baraja\StructuredApi\Entity\StatusCount; use Nette\Utils\Paginator; @@ -13,25 +14,26 @@ abstract class BaseResponse { - /** @var array|string[] */ - public static $keysToHide = ['password', 'passwd', 'pass', 'pwd', 'creditcard', 'credit card', 'cc', 'pin']; - - /** @var string */ - public static $hiddenKeyLabel = '*****'; + private const HIDDEN_KEY_LABEL = '*****'; /** @var mixed[] */ protected $haystack; + /** @var Convention */ + private $convention; + /** @var int */ private $httpCode; /** + * @param Convention $convention * @param mixed[] $haystack * @param int $httpCode */ - final public function __construct(array $haystack, int $httpCode = 200) + final public function __construct(Convention $convention, array $haystack, int $httpCode = 200) { + $this->convention = $convention; $this->haystack = $haystack; $this->httpCode = $httpCode; } @@ -93,7 +95,7 @@ final protected function hideKey($key, $value): bool if ($hide === null) { $hide = []; - foreach (self::$keysToHide as $hideKey) { + foreach ($this->convention->getKeysToHide() as $hideKey) { $hide[$hideKey] = true; } } @@ -138,7 +140,7 @@ private function process($haystack, array $trackedInstanceHashes = []) throw new \InvalidArgumentException('Convention error: Paginator must be in key "paginator", but "' . $key . '" given.'); } - $return[$key] = $this->hideKey($key, $value) ? self::$hiddenKeyLabel : $this->process($value); + $return[$key] = $this->hideKey($key, $value) ? self::HIDDEN_KEY_LABEL : $this->process($value); } return $return; @@ -146,7 +148,7 @@ private function process($haystack, array $trackedInstanceHashes = []) if (\is_object($haystack) === true) { if ($haystack instanceof \DateTimeInterface) { - return $haystack->format('Y-m-d H:i:s'); + return $haystack->format($this->convention->getDateTimeFormat()); } if ($haystack instanceof Paginator) { return [ @@ -170,7 +172,7 @@ private function process($haystack, array $trackedInstanceHashes = []) if ($haystack instanceof ItemsList) { return $this->process($haystack->getData(), $trackedInstanceHashes); } - if (\method_exists($haystack, '__toString') === true) { + if ($this->convention->isRewriteTooStringMethod() && \method_exists($haystack, '__toString') === true) { return (string) $haystack; } @@ -192,11 +194,11 @@ private function process($haystack, array $trackedInstanceHashes = []) } $trackedInstanceHashes[$objectHash] = true; } - $return[$key] = $this->hideKey($key, $value) ? self::$hiddenKeyLabel : $this->process($value, $trackedInstanceHashes); + $return[$key] = $this->hideKey($key, $value) ? self::HIDDEN_KEY_LABEL : $this->process($value, $trackedInstanceHashes); } } catch (\ReflectionException $e) { foreach ($haystack as $key => $value) { - $return[$key] = $this->hideKey($key, $value) ? self::$hiddenKeyLabel : $this->process($value); + $return[$key] = $this->hideKey($key, $value) ? self::HIDDEN_KEY_LABEL : $this->process($value); } }