aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/spomky-labs/otphp/src/ParameterTrait.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/spomky-labs/otphp/src/ParameterTrait.php')
-rw-r--r--vendor/spomky-labs/otphp/src/ParameterTrait.php188
1 files changed, 188 insertions, 0 deletions
diff --git a/vendor/spomky-labs/otphp/src/ParameterTrait.php b/vendor/spomky-labs/otphp/src/ParameterTrait.php
new file mode 100644
index 000000000..b05092351
--- /dev/null
+++ b/vendor/spomky-labs/otphp/src/ParameterTrait.php
@@ -0,0 +1,188 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OTPHP;
+
+use function array_key_exists;
+use function in_array;
+use InvalidArgumentException;
+use function is_int;
+use function is_string;
+
+trait ParameterTrait
+{
+ /**
+ * @var array<string, mixed>
+ */
+ private array $parameters = [];
+
+ private null|string $issuer = null;
+
+ private null|string $label = null;
+
+ private bool $issuer_included_as_parameter = true;
+
+ /**
+ * @return array<string, mixed>
+ */
+ public function getParameters(): array
+ {
+ $parameters = $this->parameters;
+
+ if ($this->getIssuer() !== null && $this->isIssuerIncludedAsParameter() === true) {
+ $parameters['issuer'] = $this->getIssuer();
+ }
+
+ return $parameters;
+ }
+
+ public function getSecret(): string
+ {
+ $value = $this->getParameter('secret');
+ is_string($value) || throw new InvalidArgumentException('Invalid "secret" parameter.');
+
+ return $value;
+ }
+
+ public function getLabel(): null|string
+ {
+ return $this->label;
+ }
+
+ public function setLabel(string $label): void
+ {
+ $this->setParameter('label', $label);
+ }
+
+ public function getIssuer(): null|string
+ {
+ return $this->issuer;
+ }
+
+ public function setIssuer(string $issuer): void
+ {
+ $this->setParameter('issuer', $issuer);
+ }
+
+ public function isIssuerIncludedAsParameter(): bool
+ {
+ return $this->issuer_included_as_parameter;
+ }
+
+ public function setIssuerIncludedAsParameter(bool $issuer_included_as_parameter): void
+ {
+ $this->issuer_included_as_parameter = $issuer_included_as_parameter;
+ }
+
+ public function getDigits(): int
+ {
+ $value = $this->getParameter('digits');
+ is_int($value) || throw new InvalidArgumentException('Invalid "digits" parameter.');
+
+ return $value;
+ }
+
+ public function getDigest(): string
+ {
+ $value = $this->getParameter('algorithm');
+ is_string($value) || throw new InvalidArgumentException('Invalid "algorithm" parameter.');
+
+ return $value;
+ }
+
+ public function hasParameter(string $parameter): bool
+ {
+ return array_key_exists($parameter, $this->parameters);
+ }
+
+ public function getParameter(string $parameter): mixed
+ {
+ if ($this->hasParameter($parameter)) {
+ return $this->getParameters()[$parameter];
+ }
+
+ throw new InvalidArgumentException(sprintf('Parameter "%s" does not exist', $parameter));
+ }
+
+ public function setParameter(string $parameter, mixed $value): void
+ {
+ $map = $this->getParameterMap();
+
+ if (array_key_exists($parameter, $map) === true) {
+ $callback = $map[$parameter];
+ $value = $callback($value);
+ }
+
+ if (property_exists($this, $parameter)) {
+ $this->{$parameter} = $value;
+ } else {
+ $this->parameters[$parameter] = $value;
+ }
+ }
+
+ public function setSecret(string $secret): void
+ {
+ $this->setParameter('secret', $secret);
+ }
+
+ public function setDigits(int $digits): void
+ {
+ $this->setParameter('digits', $digits);
+ }
+
+ public function setDigest(string $digest): void
+ {
+ $this->setParameter('algorithm', $digest);
+ }
+
+ /**
+ * @return array<string, callable>
+ */
+ protected function getParameterMap(): array
+ {
+ return [
+ 'label' => function ($value) {
+ $this->hasColon($value) === false || throw new InvalidArgumentException(
+ 'Label must not contain a colon.'
+ );
+
+ return $value;
+ },
+ 'secret' => static fn ($value): string => mb_strtoupper(trim((string) $value, '=')),
+ 'algorithm' => static function ($value): string {
+ $value = mb_strtolower($value);
+ in_array($value, hash_algos(), true) || throw new InvalidArgumentException(sprintf(
+ 'The "%s" digest is not supported.',
+ $value
+ ));
+
+ return $value;
+ },
+ 'digits' => static function ($value): int {
+ $value > 0 || throw new InvalidArgumentException('Digits must be at least 1.');
+
+ return (int) $value;
+ },
+ 'issuer' => function ($value) {
+ $this->hasColon($value) === false || throw new InvalidArgumentException(
+ 'Issuer must not contain a colon.'
+ );
+
+ return $value;
+ },
+ ];
+ }
+
+ private function hasColon(string $value): bool
+ {
+ $colons = [':', '%3A', '%3a'];
+ foreach ($colons as $colon) {
+ if (str_contains($value, $colon)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}