diff --git a/.travis.yml b/.travis.yml index f64813f711866a15db0e1bb43fd15ea2e0702ff5..835b621d0640ca510b1e545a75ff8841bf0d943c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ language: php php: - 7.2 - 7.3 + - 7.4 - nightly cache: diff --git a/composer.json b/composer.json index 2b32574174f24a77d3572e40c1dd7f2e51a54583..8979e8f06e6c4839032193da917a958266915c37 100644 --- a/composer.json +++ b/composer.json @@ -20,17 +20,17 @@ "ext-mbstring": "*", "paragonie/constant_time_encoding": "^2.0", "beberlei/assert": "^3.0", - "thecodingmachine/safe": "^0.1.14" + "thecodingmachine/safe": "^0.1.14|^1.0" }, "require-dev": { "phpunit/phpunit": "^8.0", "php-coveralls/php-coveralls": "^2.0", - "phpstan/phpstan": "^0.11", - "phpstan/phpstan-beberlei-assert": "^0.11.0", - "phpstan/phpstan-deprecation-rules": "^0.11", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-strict-rules": "^0.11", - "thecodingmachine/phpstan-safe-rule": "^0.1.0" + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-beberlei-assert": "^0.12", + "phpstan/phpstan-deprecation-rules": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12", + "thecodingmachine/phpstan-safe-rule": "^1.0" }, "suggest": { }, diff --git a/src/Factory.php b/src/Factory.php index f5be85c0f8e457b2a9346d832b42ee2bdb6ee617..70df63945588b71f02959064dae491ad3b1b2588 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -41,6 +41,9 @@ final class Factory implements FactoryInterface return $otp; } + /** + * @param array<string, mixed> $data + */ private static function populateParameters(OTPInterface &$otp, array $data): void { foreach ($data['query'] as $key => $value) { @@ -48,6 +51,9 @@ final class Factory implements FactoryInterface } } + /** + * @param array<string, mixed> $data + */ private static function populateOTP(OTPInterface &$otp, array $data): void { self::populateParameters($otp, $data); @@ -66,6 +72,9 @@ final class Factory implements FactoryInterface $otp->setIssuer($result[0]); } + /** + * @param array<string, mixed> $data + */ private static function checkData(array &$data): void { foreach (['scheme', 'host', 'path', 'query'] as $key) { @@ -76,6 +85,9 @@ final class Factory implements FactoryInterface Assertion::keyExists($data['query'], 'secret', 'Not a valid OTP provisioning URI'); } + /** + * @param array<string, mixed> $parsed_url + */ private static function createOTP(array $parsed_url): OTPInterface { switch ($parsed_url['host']) { diff --git a/src/HOTP.php b/src/HOTP.php index 6facca0a6f7311f376113894a5c8ec1eba3d9e21..a2f4a23951a1210886aa2e6460210eeb8d42f893 100644 --- a/src/HOTP.php +++ b/src/HOTP.php @@ -84,11 +84,14 @@ final class HOTP extends OTP implements HOTPInterface return false; } + /** + * @return array<string, mixed> + */ protected function getParameterMap(): array { $v = array_merge( parent::getParameterMap(), - ['counter' => function ($value) { + ['counter' => function ($value): int { Assertion::greaterOrEqualThan((int) $value, 0, 'Counter must be at least 0.'); return (int) $value; diff --git a/src/OTP.php b/src/OTP.php index d117ae6837bbe2dbc8732325b6138ecc24bb1f6d..932bcf97e0329ec8bb9d6f730d7b201df328cb01 100644 --- a/src/OTP.php +++ b/src/OTP.php @@ -58,6 +58,9 @@ abstract class OTP implements OTPInterface return $this->generateOTP($timestamp); } + /** + * @param array<string, mixed> $options + */ protected function filterOptions(array &$options): void { foreach (['algorithm' => 'sha1', 'period' => 30, 'digits' => 6] as $key => $default) { @@ -69,6 +72,9 @@ abstract class OTP implements OTPInterface ksort($options); } + /** + * @param array<string, mixed> $options + */ protected function generateURI(string $type, array $options): string { $label = $this->getLabel(); diff --git a/src/OTPInterface.php b/src/OTPInterface.php index 40dfd5bc6afff6ce4625f9032378b088f1c9e3b2..66e163d5d78a36dc3470ff0f355323998972048c 100644 --- a/src/OTPInterface.php +++ b/src/OTPInterface.php @@ -72,6 +72,9 @@ interface OTPInterface public function hasParameter(string $parameter): bool; + /** + * @return array<string, mixed> + */ public function getParameters(): array; /** diff --git a/src/ParameterTrait.php b/src/ParameterTrait.php index a65b4b9426040874361b4e57c9c5f15a69976d09..69fa774db7c3c22d25875b07841819966a79f6f7 100644 --- a/src/ParameterTrait.php +++ b/src/ParameterTrait.php @@ -21,7 +21,7 @@ use function Safe\sprintf; trait ParameterTrait { /** - * @var array + * @var array<string, mixed> */ private $parameters = []; @@ -40,6 +40,9 @@ trait ParameterTrait */ private $issuer_included_as_parameter = true; + /** + * @return array<string, mixed> + */ public function getParameters(): array { $parameters = $this->parameters; @@ -141,6 +144,9 @@ trait ParameterTrait } } + /** + * @return array<string, mixed> + */ protected function getParameterMap(): array { return [ @@ -149,7 +155,7 @@ trait ParameterTrait return $value; }, - 'secret' => function ($value) { + 'secret' => function ($value): string { if (null === $value) { $value = Base32::encodeUpper(random_bytes(64)); } @@ -157,13 +163,13 @@ trait ParameterTrait return $value; }, - 'algorithm' => function ($value) { + 'algorithm' => function ($value): string { $value = mb_strtolower($value); Assertion::inArray($value, hash_algos(), sprintf('The "%s" digest is not supported.', $value)); return $value; }, - 'digits' => function ($value) { + 'digits' => function ($value): int { Assertion::greaterThan($value, 0, 'Digits must be at least 1.'); return (int) $value; diff --git a/src/TOTP.php b/src/TOTP.php index 9c0db82645cb70fd1a3a34f1c96c9a747ead48af..588b37f17cb450a7f70d46d461519b12415a0b20 100644 --- a/src/TOTP.php +++ b/src/TOTP.php @@ -119,17 +119,20 @@ final class TOTP extends OTP implements TOTPInterface return (int) floor(($timestamp - $this->getEpoch()) / $this->getPeriod()); } + /** + * @return array<string, mixed> + */ protected function getParameterMap(): array { $v = array_merge( parent::getParameterMap(), [ - 'period' => function ($value) { + 'period' => function ($value): int { Assertion::greaterThan((int) $value, 0, 'Period must be at least 1.'); return (int) $value; }, - 'epoch' => function ($value) { + 'epoch' => function ($value): int { Assertion::greaterOrEqualThan((int) $value, 0, 'Epoch must be greater than or equal to 0.'); return (int) $value; @@ -140,6 +143,9 @@ final class TOTP extends OTP implements TOTPInterface return $v; } + /** + * @param array<string, mixed> $options + */ protected function filterOptions(array &$options): void { parent::filterOptions($options); diff --git a/tests/TOTPTest.php b/tests/TOTPTest.php index 07d4c3de078c71cbdb89adcb6595deff313d0881..ce955ebd51d2626cf2cd5331f522fc454a821ced 100644 --- a/tests/TOTPTest.php +++ b/tests/TOTPTest.php @@ -218,6 +218,8 @@ final class TOTPTest extends TestCase /** * @see https://tools.ietf.org/html/rfc6238#appendix-B * @see http://www.rfc-editor.org/errata_search.php?rfc=6238 + * + * @return array<int, mixed[]> */ public function dataVectors(): array {