diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 841ae43..da5f168 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,7 @@ jobs: run: vendor/bin/phpunit - name: Run phpstan - run: vendor/bin/phpstan analyze --no-progress --autoload-file=tests/phpstan/bootstrap.php --level=5 src/ + run: vendor/bin/phpstan analyze --no-progress --autoload-file=tests/phpstan/bootstrap.php src/ - name: Validate coding standards run: vendor/bin/phpcs diff --git a/docker-compose.yml b/docker-compose.yml index d056e83..52d9628 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,7 +8,7 @@ services: analysis: build: ./ working_dir: /project - command: bash -c "composer install && ./vendor/bin/phpstan analyze --level=4 ./src" + command: bash -c "composer install && ./vendor/bin/phpstan analyze ./src" volumes: - ./:/project standards: diff --git a/phpstan.dist.neon b/phpstan.dist.neon new file mode 100644 index 0000000..4bf57db --- /dev/null +++ b/phpstan.dist.neon @@ -0,0 +1,12 @@ +parameters: + level: 6 + paths: + - src + exceptions: + check: + missingCheckedExceptionInThrows: true + uncheckedExceptionClasses: + - ImagickException + - ImagickDrawException + - ImagickPixelException + - Error diff --git a/src/Laravel/ValidationServiceProvider.php b/src/Laravel/ValidationServiceProvider.php index 8ca89da..01ca9f5 100644 --- a/src/Laravel/ValidationServiceProvider.php +++ b/src/Laravel/ValidationServiceProvider.php @@ -40,7 +40,7 @@ function ($attribute, $value, $parameters, $validator) use ($rulename) { * Return rule object for given shortname * * @param string $rulename - * @param array $parameters + * @param array $parameters * @return Rule * @throws NotExistingRuleException */ @@ -58,7 +58,7 @@ private function getInterventionRule(string $rulename, array $parameters): Rule /** * List all shortnames of new rule objects * - * @return array + * @return array */ private function getRuleShortnames(): array { @@ -81,7 +81,7 @@ protected function getErrorMessage(string $rulename): string /** * Get the services provided by the provider. * - * @return array + * @return array */ public function provides() { diff --git a/src/Rules/AustrianInsuranceNumber.php b/src/Rules/AustrianInsuranceNumber.php index d5a131d..ee3e866 100644 --- a/src/Rules/AustrianInsuranceNumber.php +++ b/src/Rules/AustrianInsuranceNumber.php @@ -19,7 +19,7 @@ class AustrianInsuranceNumber extends AbstractRule * Multiplier series to calculate checksum * https://www.sozialversicherung.at/cdscontent/?contentid=10007.820902&viewmode=content * - * @var array + * @var array */ private array $multiplierSeries = [ 3, 7, 9, 5, 8, 4, 2, 1, 6 @@ -33,7 +33,7 @@ class AustrianInsuranceNumber extends AbstractRule */ public function isValid(mixed $value): bool { - $value = str_replace(' ', '', $value); + $value = str_replace(' ', '', strval($value)); return is_numeric($value) && $this->startsNotWithZero($value) @@ -41,17 +41,17 @@ public function isValid(mixed $value): bool && $this->checkChecksum($value); } - private function hasValidLength($svnumber): bool + private function hasValidLength(string $svnumber): bool { return $this->length === strlen($svnumber); } - private function startsNotWithZero($svnumber): bool + private function startsNotWithZero(string $svnumber): bool { return (int) $svnumber[0] !== 0; } - private function checkChecksum($svnumber): bool + private function checkChecksum(string $svnumber): bool { if (strlen($svnumber) !== $this->length) { return false; @@ -62,7 +62,7 @@ private function checkChecksum($svnumber): bool $sum = 0; for ($c = 0, $cMax = strlen($svnumberWithoutChecksum); $c < $cMax; $c++) { - $result = $svnumberWithoutChecksum[$c] * $this->multiplierSeries[$c]; + $result = intval($svnumberWithoutChecksum[$c]) * $this->multiplierSeries[$c]; $sum += $result; } $checksum = $sum % 11; diff --git a/src/Rules/Creditcard.php b/src/Rules/Creditcard.php index 511652a..8776aca 100644 --- a/src/Rules/Creditcard.php +++ b/src/Rules/Creditcard.php @@ -20,10 +20,11 @@ public function isValid(mixed $value): bool /** * Check if the given value has the proper length for creditcards * + * @param mixed $value * @return bool */ - private function hasValidLength($value): bool + private function hasValidLength(mixed $value): bool { - return (strlen($value) >= 13 && strlen($value) <= 19); + return (strlen(strval($value)) >= 13 && strlen(strval($value)) <= 19); } } diff --git a/src/Rules/DataUri.php b/src/Rules/DataUri.php index 5d9ba47..9a17bb3 100644 --- a/src/Rules/DataUri.php +++ b/src/Rules/DataUri.php @@ -11,7 +11,7 @@ class DataUri extends AbstractRule /** * Create new instance with allowed media types or null for all valid media types * - * @param null|array $media_types + * @param null|array $media_types * @return void */ public function __construct(protected ?array $media_types = null) @@ -27,6 +27,7 @@ public function __construct(protected ?array $media_types = null) public function isValid(mixed $value): bool { $info = $this->dataUriInfo($value); + if (!$info->isValid()) { return false; } @@ -104,20 +105,37 @@ protected function isValidBase64EncodedValue(mixed $value): bool /** * Parse data url info from current value * + * @param mixed $value * @return object */ - protected function dataUriInfo($value): object + protected function dataUriInfo(mixed $value): object { $pattern = "/^data:(?P\w+\/[-+.\w]+)?(?P" . "(;[-\w]+=[-\w]+)*)(?P;base64)?,(?P.*)/"; - $result = preg_match($pattern, $value, $matches); + $result = preg_match($pattern, strval($value), $matches); return new class ($matches, $result) { - private $matches; - private $result; - - public function __construct($matches, $result) + /** + * Matches of regex operation + * + * @var array $matches + */ + private array $matches; + + /** + * Result of regex operation + * + * @var int|false $result + */ + private int|false $result; + + /** + * @param array $matches + * @param int|false $result + * @return void + */ + public function __construct(array $matches, int|false $result) { $this->matches = $matches; $this->result = $result; @@ -142,6 +160,7 @@ public function hasMediaType(): bool return !empty($this->mediaType()); } + /** @return array */ public function parameters(): array { if (isset($this->matches['parameters']) && !empty($this->matches['parameters'])) { diff --git a/src/Rules/Domainname.php b/src/Rules/Domainname.php index 168640a..2659bf3 100644 --- a/src/Rules/Domainname.php +++ b/src/Rules/Domainname.php @@ -42,7 +42,7 @@ public function isValid(mixed $value): bool /** * Get all labels of domainname * - * @return array + * @return array */ private function getLabels(mixed $value): array { diff --git a/src/Rules/Ean.php b/src/Rules/Ean.php index e076278..c2a675c 100644 --- a/src/Rules/Ean.php +++ b/src/Rules/Ean.php @@ -11,7 +11,7 @@ class Ean extends AbstractRule /** * Create a new rule instance. * - * @param array $lengths + * @param array $lengths * @return void */ public function __construct(protected array $lengths = [8, 13]) @@ -32,20 +32,22 @@ public function isValid(mixed $value): bool /** * Determine if the current value has the lengths of EAN-8 or EAN-13 * + * @param mixed $value * @return bool */ - public function hasAllowedLength($value): bool + public function hasAllowedLength(mixed $value): bool { - return in_array(strlen((string) $value), $this->lengths); + return in_array(strlen(strval($value)), $this->lengths); } /** * Try to calculate the EAN checksum of the * current value and check the matching. * + * @param mixed $value * @return bool */ - protected function checksumMatches($value): bool + protected function checksumMatches(mixed $value): bool { return $this->calculateChecksum($value) === $this->cutChecksum($value); } @@ -53,11 +55,12 @@ protected function checksumMatches($value): bool /** * Cut out the checksum of the current value and return * + * @param mixed $value * @return int */ - protected function cutChecksum($value): int + protected function cutChecksum(mixed $value): int { - return intval(substr((string) $value, -1)); + return intval(substr(strval($value), -1)); } /** @@ -66,12 +69,12 @@ protected function cutChecksum($value): int * @param mixed $value * @return int */ - protected function calculateChecksum($value): int + protected function calculateChecksum(mixed $value): int { $checksum = 0; // chars without check digit in reverse - $chars = array_reverse(str_split(substr((string) $value, 0, -1))); + $chars = array_reverse(str_split(substr(strval($value), 0, -1))); foreach ($chars as $key => $char) { $multiplier = $key % 2 ? 1 : 3; diff --git a/src/Rules/Gtin.php b/src/Rules/Gtin.php index 2cc00f7..5e3e1c4 100644 --- a/src/Rules/Gtin.php +++ b/src/Rules/Gtin.php @@ -6,6 +6,10 @@ class Gtin extends Ean { + /** + * @param array $lengths + * @return void + */ public function __construct(protected array $lengths = [8, 12, 13, 14]) { } diff --git a/src/Rules/Hexadecimalcolor.php b/src/Rules/Hexadecimalcolor.php index 5f93fdf..5b65c6e 100644 --- a/src/Rules/Hexadecimalcolor.php +++ b/src/Rules/Hexadecimalcolor.php @@ -11,7 +11,7 @@ class Hexadecimalcolor extends AbstractRegexRule /** * Create a new rule instance. * - * @param array $lengths + * @param array $lengths * @return void */ public function __construct(protected array $lengths = [3, 4, 6, 8]) @@ -41,10 +41,11 @@ public function isValid(mixed $value): bool /** * Determine if the current value has correct length * + * @param mixed $value * @return bool */ - public function hasAllowedLength($value): bool + public function hasAllowedLength(mixed $value): bool { - return in_array(strlen(trim($value, '#')), $this->lengths); + return in_array(strlen(trim(strval($value), '#')), $this->lengths); } } diff --git a/src/Rules/Iban.php b/src/Rules/Iban.php index 01b7c34..8880b20 100644 --- a/src/Rules/Iban.php +++ b/src/Rules/Iban.php @@ -11,7 +11,7 @@ class Iban extends AbstractRule /** * IBAN lengths for countries * - * @var array + * @var array */ private $lengths = [ 'AL' => 28, @@ -130,7 +130,7 @@ class Iban extends AbstractRule public function isValid(mixed $value): bool { // normalize value - $value = str_replace(' ', '', strtoupper($value)); + $value = str_replace(' ', '', strtoupper(strval($value))); // check iban length and checksum return $this->hasValidLength($value) && $this->getChecksum($value) === 1; @@ -142,7 +142,7 @@ public function isValid(mixed $value): bool * @param string $iban * @return int */ - private function getChecksum($iban) + private function getChecksum(string $iban) { $iban = substr($iban, 4) . substr($iban, 0, 4); $iban = str_replace( @@ -168,7 +168,7 @@ private function getChecksum($iban) * @param string $iban * @return int */ - private function getDesignatedIbanLength($iban) + private function getDesignatedIbanLength(string $iban) { $countrycode = substr($iban, 0, 2); @@ -181,17 +181,27 @@ private function getDesignatedIbanLength($iban) * @param string $iban * @return bool */ - private function hasValidLength($iban) + private function hasValidLength(string $iban): bool { return $this->getDesignatedIbanLength($iban) == strlen($iban); } - private function getReplacementsChars() + /** + * Get chars to be replaced in checksum calculation + * + * @return array + */ + private function getReplacementsChars(): array { return range('A', 'Z'); } - private function getReplacementsValues() + /** + * Get values to replace chars in checksum calculation + * + * @return array + */ + private function getReplacementsValues(): array { $values = []; foreach (range(10, 35) as $value) { diff --git a/src/Rules/Imei.php b/src/Rules/Imei.php index 5bea432..336de59 100644 --- a/src/Rules/Imei.php +++ b/src/Rules/Imei.php @@ -20,9 +20,10 @@ public function isValid(mixed $value): bool /** * Determine if current value has valid IMEI length * + * @param string $value * @return bool */ - private function hasValidLength($value): bool + private function hasValidLength(string $value): bool { return strlen($value) === 15; } diff --git a/src/Rules/Isbn.php b/src/Rules/Isbn.php index aaaaf8b..a4028af 100644 --- a/src/Rules/Isbn.php +++ b/src/Rules/Isbn.php @@ -6,6 +6,10 @@ class Isbn extends Ean { + /** + * @param array $lengths + * @return void + */ public function __construct(protected array $lengths = [10, 13]) { } @@ -39,9 +43,10 @@ public function isValid(mixed $value): bool /** * Determine if checksum for ISBN-10 numbers is valid * + * @param string $value * @return bool */ - private function shortChecksumMatches($value) + private function shortChecksumMatches(string $value) { return $this->getShortChecksum($value) % 11 === 0; } @@ -49,9 +54,10 @@ private function shortChecksumMatches($value) /** * Calculate checksum of short ISBN numbers * + * @param string $value * @return int */ - private function getShortChecksum($value) + private function getShortChecksum(string $value) { $checksum = 0; $multiplier = 10; diff --git a/src/Rules/Isin.php b/src/Rules/Isin.php index 1910ae6..b778596 100644 --- a/src/Rules/Isin.php +++ b/src/Rules/Isin.php @@ -9,9 +9,9 @@ class Isin extends Luhn /** * Chars to calculate checksum * - * @var array + * @var array */ - private $chars = [ + private array $chars = [ 10 => 'A', 11 => 'B', 12 => 'C', @@ -54,9 +54,10 @@ public function isValid(mixed $value): bool /** * Get value to check against * + * @param string $value * @return string */ - public function normalize($value) + public function normalize(string $value) { return $this->replaceChars($this->getValueWithoutLastDigit($value)) . $this->getLastDigit($value); } @@ -67,7 +68,7 @@ public function normalize($value) * @param string $value * @return string */ - private function replaceChars($value) + private function replaceChars(string $value) { return str_replace($this->chars, array_keys($this->chars), $value); } @@ -75,9 +76,10 @@ private function replaceChars($value) /** * Return value without last digit * + * @param string $value * @return string */ - private function getValueWithoutLastDigit($value) + private function getValueWithoutLastDigit(string $value) { return substr($value, 0, -1); } @@ -85,9 +87,10 @@ private function getValueWithoutLastDigit($value) /** * Return last digit of current value * + * @param string $value * @return string */ - private function getLastDigit($value) + private function getLastDigit(string $value) { return substr($value, -1); } diff --git a/src/Rules/Issn.php b/src/Rules/Issn.php index b06f2ab..375a9c4 100644 --- a/src/Rules/Issn.php +++ b/src/Rules/Issn.php @@ -21,9 +21,10 @@ public function isValid(mixed $value): bool /** * Determine if checksum matches * + * @param string $value * @return bool */ - private function checkSumMatches($value): bool + private function checkSumMatches(string $value): bool { return $this->calculateChecksum($value) === $this->parseChecksum($value); } @@ -31,9 +32,10 @@ private function checkSumMatches($value): bool /** * Calculate checksum from the current value * + * @param string $value * @return int */ - private function calculateChecksum($value): int + private function calculateChecksum(string $value): int { $checksum = 0; $issn_numbers = str_replace('-', '', $value); @@ -50,9 +52,10 @@ private function calculateChecksum($value): int /** * Parse attached checksum of current value (last digit) * + * @param string $value * @return int */ - private function parseChecksum($value): int + private function parseChecksum(string $value): int { $last = substr($value, -1); diff --git a/src/Rules/Lowercase.php b/src/Rules/Lowercase.php index ddafce8..c020c09 100644 --- a/src/Rules/Lowercase.php +++ b/src/Rules/Lowercase.php @@ -22,10 +22,11 @@ public function isValid(mixed $value): bool /** * Return value as lowercase * + * @param mixed $value * @return string */ - private function getLowerCaseValue($value): string + private function getLowerCaseValue(mixed $value): string { - return mb_strtolower($value, mb_detect_encoding($value)); + return mb_strtolower(strval($value), mb_detect_encoding($value)); } } diff --git a/src/Rules/Luhn.php b/src/Rules/Luhn.php index f9692f8..7d56060 100644 --- a/src/Rules/Luhn.php +++ b/src/Rules/Luhn.php @@ -49,6 +49,6 @@ protected function getChecksum($value): int } } - return $checksum; + return (int) $checksum; } } diff --git a/src/Rules/Postalcode.php b/src/Rules/Postalcode.php index 0084122..5a37eec 100644 --- a/src/Rules/Postalcode.php +++ b/src/Rules/Postalcode.php @@ -19,14 +19,14 @@ class Postalcode extends AbstractRule implements DataAwareRule /** * Data set used for validation * - * @var array + * @var array */ protected $data = []; /** * Create a new rule instance with allowed countrycodes * - * @param array $countrycodes + * @param array $countrycodes */ public function __construct(protected array $countrycodes = []) { @@ -35,7 +35,7 @@ public function __construct(protected array $countrycodes = []) /** * Set data * - * @param array $data + * @param array $data * @return static */ public function setData(array $data): static @@ -63,7 +63,7 @@ public static function reference(string $reference): self /** * Static constructor method * - * @param array $countrycodes + * @param array $countrycodes * @return Postalcode */ public static function countrycode(array $countrycodes): self @@ -91,7 +91,7 @@ public function isValid(mixed $value): bool /** * Return regex patterns for allowed country codes * - * @return array + * @return array */ protected function getPatterns(): array { @@ -104,6 +104,11 @@ protected function getPatterns(): array }); } + /** + * Get array of allowed country codes + * + * @return array + */ protected function getCountryCodes(): array { if (count($this->countrycodes) == 0) { diff --git a/src/Rules/Titlecase.php b/src/Rules/Titlecase.php index d7efb57..28d22da 100644 --- a/src/Rules/Titlecase.php +++ b/src/Rules/Titlecase.php @@ -28,9 +28,10 @@ public function isValid(mixed $value): bool /** * Get array of words from current value * - * @return array + * @param mixed $value + * @return array */ - private function getWords($value): array + private function getWords(mixed $value): array { return explode(" ", $value); } diff --git a/src/Rules/Ulid.php b/src/Rules/Ulid.php index e0627bc..6f4b87f 100644 --- a/src/Rules/Ulid.php +++ b/src/Rules/Ulid.php @@ -34,10 +34,11 @@ public function isValid(mixed $value): bool /** * Determine if current ulid has exceeded maximum size - * + + * @param string $value * @return bool */ - protected function ulidTooLarge($value): bool + protected function ulidTooLarge(string $value): bool { return intval($value[0]) > 7; } diff --git a/src/Rules/Uppercase.php b/src/Rules/Uppercase.php index 47fcc48..efe93c3 100644 --- a/src/Rules/Uppercase.php +++ b/src/Rules/Uppercase.php @@ -24,8 +24,8 @@ public function isValid(mixed $value): bool * * @return string */ - private function getUpperCaseValue($value): string + private function getUpperCaseValue(mixed $value): string { - return mb_strtoupper($value, mb_detect_encoding($value)); + return mb_strtoupper(strval($value), mb_detect_encoding($value)); } } diff --git a/tests/Rules/IsbnTest.php b/tests/Rules/IsbnTest.php index e7a5473..5b8a212 100644 --- a/tests/Rules/IsbnTest.php +++ b/tests/Rules/IsbnTest.php @@ -34,6 +34,7 @@ public function testValidationLong($result, $value): void public static function dataProvider(): array { return [ + [true, '3498016709'], [true, '3498016709'], [true, '978-3499255496'], [true, '85-359-0277-5'],