diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 1c17eba8..9db45faf 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,131 +1,11 @@ parameters: ignoreErrors: - - - message: '#^Call to function is_int\(\) with string will always evaluate to false\.$#' - identifier: function.impossibleType - count: 1 - path: src/Altair/Cache/SimpleCache.php - - - - message: '#^Result of && is always false\.$#' - identifier: booleanAnd.alwaysFalse - count: 1 - path: src/Altair/Cache/Storage/FilesystemCacheItemStorage.php - - - - message: '#^Strict comparison using \=\=\= between ''\\\\'' and ''/'' will always evaluate to false\.$#' - identifier: identical.alwaysFalse - count: 1 - path: src/Altair/Cache/Storage/FilesystemCacheItemStorage.php - - - - message: '#^Class Predis\\Connection\\Aggregate\\PredisCluster not found\.$#' - identifier: class.notFound - count: 1 - path: src/Altair/Cache/Storage/PredisCacheItemStorage.php - - - - message: '#^Class Predis\\Connection\\Aggregate\\RedisCluster not found\.$#' - identifier: class.notFound - count: 1 - path: src/Altair/Cache/Storage/PredisCacheItemStorage.php - - - - message: '#^Comparison operation "\>\=" between 0 and int\<1, max\> is always false\.$#' - identifier: greaterOrEqual.alwaysFalse - count: 1 - path: src/Altair/Cache/Storage/PredisCacheItemStorage.php - - - - message: '#^Iterating over an object of an unknown class Predis\\Connection\\Aggregate\\PredisCluster\.$#' - identifier: class.notFound - count: 1 - path: src/Altair/Cache/Storage/PredisCacheItemStorage.php - - - - message: '#^Variable \$pipe in PHPDoc tag @var does not match any variable in the foreach loop\: \$serialized, \$id, \$value$#' - identifier: varTag.differentVariable - count: 1 - path: src/Altair/Cache/Storage/PredisCacheItemStorage.php - - - - message: '#^Comparison operation "\>\=" between 0 and int\<1, max\> is always false\.$#' - identifier: greaterOrEqual.alwaysFalse - count: 1 - path: src/Altair/Cache/Storage/RedisCacheItemStorage.php - - message: '#^Trait Altair\\Cache\\Traits\\TagsAwareTrait is used zero times and is not analysed\.$#' identifier: trait.unused count: 1 path: src/Altair/Cache/Traits/TagsAwareTrait.php - - - message: '#^Call to function is_array\(\) with array will always evaluate to true\.$#' - identifier: function.alreadyNarrowedType - count: 1 - path: src/Altair/Common/Support/Arr.php - - - - message: '#^Method Altair\\Common\\Support\\Arr\:\:getValue\(\) has parameter \$array with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/Altair/Common/Support/Arr.php - - - - message: '#^PHPDoc tag @param for parameter \$array with type array\|object is not subtype of native type array\.$#' - identifier: parameter.phpDocType - count: 1 - path: src/Altair/Common/Support/Arr.php - - - - message: '#^Call to function is_string\(\) with non\-falsy\-string will always evaluate to true\.$#' - identifier: function.alreadyNarrowedType - count: 2 - path: src/Altair/Container/Collection/AliasesCollection.php - - - - message: '#^Method Altair\\Container\\Collection\\AliasesCollection\:\:define\(\) should return Altair\\Container\\Collection\\AliasesCollection but returns Altair\\Structure\\Contracts\\MapInterface\\.$#' - identifier: return.type - count: 1 - path: src/Altair/Container/Collection/AliasesCollection.php - - - - message: '#^PHPDoc tag @var with type Altair\\Container\\Collection\\AliasesCollection\|string is not subtype of native type string\.$#' - identifier: varTag.nativeType - count: 1 - path: src/Altair/Container/Collection/AliasesCollection.php - - - - message: '#^Method Altair\\Container\\Collection\\SharesCollection\:\:shareClass\(\) should return Altair\\Structure\\Contracts\\MapInterface\ but returns Altair\\Structure\\Contracts\\MapInterface\\.$#' - identifier: return.type - count: 1 - path: src/Altair/Container/Collection/SharesCollection.php - - - - message: '#^Method Altair\\Container\\Collection\\SharesCollection\:\:shareInstance\(\) should return Altair\\Structure\\Contracts\\MapInterface\ but returns Altair\\Structure\\Contracts\\MapInterface\\.$#' - identifier: return.type - count: 1 - path: src/Altair/Container/Collection/SharesCollection.php - - - - message: '#^Call to an undefined method ReflectionFunctionAbstract\:\:invokeArgs\(\)\.$#' - identifier: method.notFound - count: 1 - path: src/Altair/Container/Executable.php - - - - message: '#^PHPDoc tag @param for parameter \$reflection with type ReflectionFunctionAbstract is not subtype of native type ReflectionFunction\.$#' - identifier: parameter.phpDocType - count: 1 - path: src/Altair/Container/Executable.php - - - - message: '#^Parameter \#1 \$reflection of method Altair\\Container\\Executable\:\:invokeClosure\(\) expects ReflectionFunction, ReflectionFunctionAbstract given\.$#' - identifier: argument.type - count: 1 - path: src/Altair/Container/Executable.php - - message: '#^Class Altair\\Cookie\\Collection\\CookieCollection extends generic class Altair\\Structure\\Map but does not specify its types\: TKey, TValue$#' identifier: missingType.generics @@ -138,36 +18,6 @@ parameters: count: 1 path: src/Altair/Cookie/Collection/SetCookieCollection.php - - - message: '#^Method Altair\\Courier\\Contracts\\CommandMiddlewareInterface\:\:handle\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: src/Altair/Courier/Contracts/CommandMiddlewareInterface.php - - - - message: '#^Property Altair\\Courier\\Middleware\\CommandLockerMiddleware\:\:\$queue type has no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/Altair/Courier/Middleware/CommandLockerMiddleware.php - - - - message: '#^Method Altair\\Courier\\Strategy\\CommandRunnerMiddlewareStrategy\:\:__construct\(\) has parameter \$middlewares with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/Altair/Courier/Strategy/CommandRunnerMiddlewareStrategy.php - - - - message: '#^Method Altair\\Courier\\Strategy\\CommandRunnerMiddlewareStrategy\:\:withMiddlewares\(\) has parameter \$middlewares with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/Altair/Courier/Strategy/CommandRunnerMiddlewareStrategy.php - - - - message: '#^Property Altair\\Courier\\Strategy\\CommandRunnerMiddlewareStrategy\:\:\$middlewares type has no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/Altair/Courier/Strategy/CommandRunnerMiddlewareStrategy.php - - message: '#^Trait Altair\\Courier\\Traits\\LogMessageTrait is used zero times and is not analysed\.$#' identifier: trait.unused @@ -204,230 +54,14 @@ parameters: count: 1 path: src/Altair/Data/Traits/SerializeAwareTrait.php - - - message: '#^Parameter \#1 \$array \(list\\) of array_values is already a list, call has no effect\.$#' - identifier: arrayValues.list - count: 1 - path: src/Altair/Doctor/Configuration/DoctorConfiguration.php - - - - message: '#^Using nullsafe property access "\?\-\>id" on left side of \?\? is unnecessary\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: src/Altair/Events/Cli/CheckpointCreateCommand.php - - - - message: '#^PHPDoc tag @return has invalid value \(EventDispatcherInterface;\)\: Unexpected token ";", expected TOKEN_HORIZONTAL_WS at offset 203 on line 8$#' - identifier: phpDoc.parseError - count: 1 - path: src/Altair/Happen/Contracts/EventDispatcherInterface.php - - message: '#^Trait Altair\\Happen\\Traits\\EventStackAwareTrait is used zero times and is not analysed\.$#' identifier: trait.unused count: 1 path: src/Altair/Happen/Traits/EventStackAwareTrait.php - - - message: '#^PHPDoc tag @var for property Altair\\Http\\Base\\Payload\:\:\$settingsCollection with type Altair\\Structure\\Map\|null is not subtype of native type Altair\\Http\\Collection\\SettingsCollection\.$#' - identifier: property.phpDocType - count: 1 - path: src/Altair/Http/Base/Payload.php - - - - message: '#^Instanceof between array\ and Traversable will always evaluate to false\.$#' - identifier: instanceof.alwaysFalse - count: 1 - path: src/Altair/Http/Collection/HttpStatusCollection.php - - - - message: '#^Method Altair\\Http\\Collection\\HttpStatusCollection\:\:getResponseClass\(\) should return string but returns int\.$#' - identifier: return.type - count: 1 - path: src/Altair/Http/Collection/HttpStatusCollection.php - - - - message: '#^Parameter \#1 \$string of function substr expects string, int given\.$#' - identifier: argument.type - count: 1 - path: src/Altair/Http/Collection/HttpStatusCollection.php - - - - message: '#^Result of \|\| is always true\.$#' - identifier: booleanOr.alwaysTrue - count: 1 - path: src/Altair/Http/Collection/HttpStatusCollection.php - - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: src/Altair/Http/Collection/HttpStatusCollection.php - - - - message: '#^Dead catch \- Exception is never thrown in the try block\.$#' - identifier: catch.neverThrown - count: 1 - path: src/Altair/Http/Formatter/PhpViewFormatter.php - - - - message: '#^Offset ''domain'' on array\{lifetime\: int\<0, max\>, path\: non\-falsy\-string, domain\: string, secure\: bool, httponly\: bool, samesite\: ''Lax''\|''lax''\|''None''\|''none''\|''Strict''\|''strict''\} on left side of \?\? always exists and is not nullable\.$#' - identifier: nullCoalesce.offset - count: 1 - path: src/Altair/Http/Middleware/SessionHeadersMiddleware.php - - - - message: '#^Offset ''lifetime'' on array\{lifetime\: int\<0, max\>, path\: non\-falsy\-string, domain\: string, secure\: bool, httponly\: bool, samesite\: ''Lax''\|''lax''\|''None''\|''none''\|''Strict''\|''strict''\} on left side of \?\? always exists and is not nullable\.$#' - identifier: nullCoalesce.offset - count: 1 - path: src/Altair/Http/Middleware/SessionHeadersMiddleware.php - - - - message: '#^Offset ''path'' on array\{lifetime\: int\<0, max\>, path\: non\-falsy\-string, domain\: string, secure\: bool, httponly\: bool, samesite\: ''Lax''\|''lax''\|''None''\|''none''\|''Strict''\|''strict''\} on left side of \?\? always exists and is not nullable\.$#' - identifier: nullCoalesce.offset - count: 1 - path: src/Altair/Http/Middleware/SessionHeadersMiddleware.php - - - - message: '#^Using nullsafe method call on non\-nullable type Altair\\Cookie\\Cookie\. Use \-\> instead\.$#' - identifier: nullsafe.neverNull - count: 1 - path: src/Altair/Http/Middleware/SessionHeadersMiddleware.php - - - - message: '#^Parameter \#1 \$array \(list\\) of array_values is already a list, call has no effect\.$#' - identifier: arrayValues.list - count: 1 - path: src/Altair/Http/Middleware/SpamBlockerMiddleware.php - - - - message: '#^PHPDoc tag @var with type callable is not subtype of native type object\.$#' - identifier: varTag.nativeType - count: 1 - path: src/Altair/Http/Responder/CompoundResponder.php - - - - message: '#^Parameter \#1 \$reason of method Altair\\Http\\Collection\\HttpStatusCollection\:\:getStatusCode\(\) expects string, int\|null given\.$#' - identifier: argument.type - count: 1 - path: src/Altair/Http/Responder/StatusResponder.php - - - - message: '#^PHPDoc tag @return with type resource is incompatible with native type GdImage\|false\.$#' - identifier: return.phpDocType - count: 1 - path: src/Altair/Http/Support/DefaultErrorHandler.php - - - - message: '#^Call to function is_array\(\) with array\ will always evaluate to true\.$#' - identifier: function.alreadyNarrowedType - count: 2 - path: src/Altair/Introspection/Inspector/ConfigInspector.php - - message: '#^Unable to resolve the template type TEntity in call to method Cycle\\ORM\\ORMInterface\:\:getRepository\(\)$#' identifier: argument.templateType count: 1 path: src/Altair/Persistence/Cycle/CycleRepository.php - - - - message: '#^PHPDoc tag @return with type mixed is not subtype of native type int\|null\.$#' - identifier: return.phpDocType - count: 1 - path: src/Altair/Sanitation/Filter/IntegerFilter.php - - - - message: '#^PHPDoc tag @param for parameter \$resolver with type callable is not subtype of native type Altair\\Sanitation\\Contracts\\ResolverInterface\|null\.$#' - identifier: parameter.phpDocType - count: 1 - path: src/Altair/Sanitation/FiltersRunner.php - - - - message: '#^Property Altair\\Sanitation\\Sanitizer\:\:\$payload \(Altair\\Middleware\\Payload\) does not accept Altair\\Middleware\\Contracts\\PayloadInterface\.$#' - identifier: assign.propertyType - count: 2 - path: src/Altair/Sanitation/Sanitizer.php - - - - message: '#^Parameter \#1 \$array \(list\\) of array_values is already a list, call has no effect\.$#' - identifier: arrayValues.list - count: 1 - path: src/Altair/Scaffold/Sdk/Model/OpenApiParser.php - - - - message: '#^Strict comparison using \=\=\= between non\-falsy\-string and false will always evaluate to false\.$#' - identifier: identical.alwaysFalse - count: 1 - path: src/Altair/Security/Support/Pbkdf2Key.php - - - - message: '#^Return type \(void\) of method Altair\\Session\\Handler\\FileSessionHandler\:\:gc\(\) should be compatible with return type \(int\|false\) of method SessionHandlerInterface\:\:gc\(\)$#' - identifier: method.childReturnType - count: 1 - path: src/Altair/Session/Handler/FileSessionHandler.php - - - - message: '#^Method Altair\\Session\\Handler\\MongoSessionHandler\:\:gc\(\) should return int\|false but returns true\.$#' - identifier: return.type - count: 1 - path: src/Altair/Session/Handler/MongoSessionHandler.php - - - - message: '#^Method Altair\\Session\\Handler\\PdoSessionHandler\:\:gc\(\) should return int\|false but returns true\.$#' - identifier: return.type - count: 1 - path: src/Altair/Session/Handler/PdoSessionHandler.php - - - - message: '#^Call to function method_exists\(\) with \$this\(Altair\\Structure\\Deque\\) and ''adjustCapacity'' will always evaluate to true\.$#' - identifier: function.alreadyNarrowedType - count: 3 - path: src/Altair/Structure/Deque.php - - - - message: '#^Property Altair\\Structure\\PriorityNode\\:\:\$priority \(int\) does not accept null\.$#' - identifier: assign.propertyType - count: 1 - path: src/Altair/Structure/PriorityNode.php - - - - message: '#^Property Altair\\Structure\\PriorityNode\\:\:\$stamp \(int\) does not accept null\.$#' - identifier: assign.propertyType - count: 1 - path: src/Altair/Structure/PriorityNode.php - - - - message: '#^Call to function method_exists\(\) with \$this\(Altair\\Structure\\Vector\\) and ''adjustCapacity'' will always evaluate to true\.$#' - identifier: function.alreadyNarrowedType - count: 3 - path: src/Altair/Structure/Vector.php - - - - message: '#^Binary operation "\*\=" between non\-empty\-string and 2 results in an error\.$#' - identifier: assignOp.invalid - count: 1 - path: src/Altair/Validation/Rule/CreditCardRule.php - - - - message: '#^Binary operation "\-" between 32 and string results in an error\.$#' - identifier: binaryOp.invalid - count: 1 - path: src/Altair/Validation/Rule/IpRule.php - - - - message: '#^Strict comparison using \=\=\= between 1 and 0 will always evaluate to false\.$#' - identifier: identical.alwaysFalse - count: 1 - path: src/Altair/Validation/Rule/IsbnRule.php - - - - message: '#^PHPDoc tag @param for parameter \$resolver with type callable is not subtype of native type Altair\\Validation\\Contracts\\ResolverInterface\|null\.$#' - identifier: parameter.phpDocType - count: 1 - path: src/Altair/Validation/RulesRunner.php - - - - message: '#^Property Altair\\Validation\\Validator\:\:\$payload \(Altair\\Middleware\\Payload\) does not accept Altair\\Middleware\\Contracts\\PayloadInterface\.$#' - identifier: assign.propertyType - count: 2 - path: src/Altair/Validation/Validator.php diff --git a/src/Altair/Cache/SimpleCache.php b/src/Altair/Cache/SimpleCache.php index e462b51c..18106a79 100644 --- a/src/Altair/Cache/SimpleCache.php +++ b/src/Altair/Cache/SimpleCache.php @@ -113,7 +113,6 @@ public function setMultiple(iterable $values, null|int|DateInterval $ttl = null) $items = $this->pool->getItems($keys); } else { foreach ($values as $key => $value) { - $key = \is_int($key) ? (string) $key : $key; $items[$key] = $this->pool->getItem($key)->set($value); } } diff --git a/src/Altair/Cache/Storage/FilesystemCacheItemStorage.php b/src/Altair/Cache/Storage/FilesystemCacheItemStorage.php index c5eef4a2..6ca007ee 100644 --- a/src/Altair/Cache/Storage/FilesystemCacheItemStorage.php +++ b/src/Altair/Cache/Storage/FilesystemCacheItemStorage.php @@ -214,7 +214,7 @@ private function setCacheDirectory(Filesystem $filesystem, ?string $directory): } $path .= '/'; - if ('\\' === '/' && \strlen($path) > 234) { // windows allows max of 258 + if (DIRECTORY_SEPARATOR === '\\' && \strlen($path) > 234) { // windows allows max of 258 throw new InvalidArgumentException(\sprintf('Cache directory path is too long "%s"', $path)); } diff --git a/src/Altair/Cache/Storage/PredisCacheItemStorage.php b/src/Altair/Cache/Storage/PredisCacheItemStorage.php index 14186a29..5b90260c 100644 --- a/src/Altair/Cache/Storage/PredisCacheItemStorage.php +++ b/src/Altair/Cache/Storage/PredisCacheItemStorage.php @@ -20,8 +20,8 @@ use Override; use Predis\Client; use Predis\Collection\Iterator\Keyspace; -use Predis\Connection\Aggregate\PredisCluster; -use Predis\Connection\Aggregate\RedisCluster; +use Predis\Connection\Cluster\PredisCluster; +use Predis\Connection\Cluster\RedisCluster; class PredisCacheItemStorage implements CacheItemStorageInterface { @@ -163,14 +163,10 @@ public function save(array $values, int $lifespan) } $this->client->pipeline( + /** @param Client $pipe */ static function ($pipe) use ($serialized, $lifespan): void { - /** @var Client $pipe */ foreach ($serialized as $id => $value) { - if (0 >= $lifespan) { - $pipe->set($id, $value); - } else { - $pipe->setex($id, $lifespan, $value); - } + $pipe->setex($id, $lifespan, $value); } } ); diff --git a/src/Altair/Cache/Storage/RedisCacheItemStorage.php b/src/Altair/Cache/Storage/RedisCacheItemStorage.php index 6a5fb8ba..dc2fb7e5 100644 --- a/src/Altair/Cache/Storage/RedisCacheItemStorage.php +++ b/src/Altair/Cache/Storage/RedisCacheItemStorage.php @@ -155,12 +155,7 @@ public function save(array $values, int $lifespan) $this->client->multi(Redis::PIPELINE); $ids = []; foreach ($serialized as $id => $value) { - if (0 >= $lifespan) { - $this->client->set($id, $value); - } else { - $this->client->setex($id, $lifespan, $value); - } - + $this->client->setex($id, $lifespan, $value); $ids[] = $id; } diff --git a/src/Altair/Common/Support/Arr.php b/src/Altair/Common/Support/Arr.php index 4bb384fd..dbef8052 100644 --- a/src/Altair/Common/Support/Arr.php +++ b/src/Altair/Common/Support/Arr.php @@ -85,7 +85,7 @@ public static function merge(array $a, array $b): array * $value = Arr::getValue($versions, ['1.0', 'date']); * ``` * - * @param array|object $array array or object to extract value from + * @param mixed $array array or object to extract the value from; any other type yields the default * @param string|Closure|array $key key name of the array element, an array of keys or property name of the object, * or an anonymous function returning the value. The anonymous function signature should be: * `function($array, $defaultValue)`. @@ -94,7 +94,7 @@ public static function merge(array $a, array $b): array * * @return mixed the value of the element if found, default value otherwise */ - public static function getValue(array $array, $key, mixed $default = null) + public static function getValue(mixed $array, $key, mixed $default = null) { if ($key instanceof Closure) { return $key($array, $default); @@ -636,10 +636,6 @@ public static function isAssociative(array $array, bool $allStrings = true): boo */ public static function isIndexed(array $array, bool $consecutive = false): bool { - if (!\is_array($array)) { - return false; - } - if ($array === []) { return true; } diff --git a/src/Altair/Container/Collection/AliasesCollection.php b/src/Altair/Container/Collection/AliasesCollection.php index e7050a72..bc92ce70 100644 --- a/src/Altair/Container/Collection/AliasesCollection.php +++ b/src/Altair/Container/Collection/AliasesCollection.php @@ -34,11 +34,10 @@ class AliasesCollection extends Map */ public function define(string $original, string $alias, SharesCollection $sharesCollection): self { - if (($original === '' || $original === '0' || !\is_string($original)) || ($alias === '' || $alias === '0' || !\is_string($alias))) { + if ($original === '' || $original === '0' || $alias === '' || $alias === '0') { throw new InvalidArgumentException('"$original" and/or "$alias" cannot be empty.'); } - /** @var AliasesCollection|string $original */ $original = $this->normalizeName($original); if (isset($sharesCollection[$original])) { @@ -56,7 +55,9 @@ public function define(string $original, string $alias, SharesCollection $shares $sharesCollection->put($alias, null)->remove($original); } - return $this->put($original, $alias); + $this->put($original, $alias); + + return $this; } /** diff --git a/src/Altair/Container/Collection/SharesCollection.php b/src/Altair/Container/Collection/SharesCollection.php index 4bf246ad..1b98f420 100644 --- a/src/Altair/Container/Collection/SharesCollection.php +++ b/src/Altair/Container/Collection/SharesCollection.php @@ -30,7 +30,9 @@ public function shareClass(string $name, AliasesCollection $aliasesCollection): { [, $normalizedName] = $aliasesCollection->resolve($name); - return $this->put($normalizedName, $this[$normalizedName] ?? null); + $this->put($normalizedName, $this[$normalizedName] ?? null); + + return $this; } /** @@ -49,6 +51,8 @@ public function shareInstance(object $instance, AliasesCollection $aliasesCollec ); } - return $this->put($normalizedName, $instance); + $this->put($normalizedName, $instance); + + return $this; } } diff --git a/src/Altair/Container/Executable.php b/src/Altair/Container/Executable.php index 06bad445..66fbb345 100644 --- a/src/Altair/Container/Executable.php +++ b/src/Altair/Container/Executable.php @@ -19,10 +19,7 @@ class Executable { - /** - * @var ReflectionFunctionAbstract|ReflectionFunction - */ - protected $callableReflection; + protected ReflectionFunction|ReflectionMethod $callableReflection; /** * @var mixed|null The object to invoke the method on if $reflectionFunction is a ReflectionMethod. In @@ -41,8 +38,10 @@ public function __construct(ReflectionFunctionAbstract $reflectionFunction, $obj { if ($reflectionFunction instanceof ReflectionMethod) { $this->setMethodCallable($reflectionFunction, $object); - } else { + } elseif ($reflectionFunction instanceof ReflectionFunction) { $this->callableReflection = $reflectionFunction; + } else { + throw new InvalidArgumentException(\sprintf('Unsupported reflection type "%s".', $reflectionFunction::class)); } } @@ -87,7 +86,6 @@ protected function setMethodCallable(ReflectionMethod $reflection, mixed $object } /** - * @param ReflectionFunction|ReflectionFunctionAbstract $reflection * @param array $args */ protected function invokeClosure(ReflectionFunction $reflection, array $args): mixed diff --git a/src/Altair/Courier/Contracts/CommandMiddlewareInterface.php b/src/Altair/Courier/Contracts/CommandMiddlewareInterface.php index eca5d369..70ed6300 100644 --- a/src/Altair/Courier/Contracts/CommandMiddlewareInterface.php +++ b/src/Altair/Courier/Contracts/CommandMiddlewareInterface.php @@ -13,5 +13,5 @@ interface CommandMiddlewareInterface { - public function handle(CommandMessageInterface $message, callable $next); + public function handle(CommandMessageInterface $message, callable $next): void; } diff --git a/src/Altair/Courier/Middleware/CommandLockerMiddleware.php b/src/Altair/Courier/Middleware/CommandLockerMiddleware.php index 8dd91931..44781600 100644 --- a/src/Altair/Courier/Middleware/CommandLockerMiddleware.php +++ b/src/Altair/Courier/Middleware/CommandLockerMiddleware.php @@ -19,14 +19,11 @@ class CommandLockerMiddleware implements CommandMiddlewareInterface { /** - * @var array + * @var array */ protected $queue = []; - /** - * @var bool - */ - protected $running = false; + protected bool $running = false; /** * @inheritDoc diff --git a/src/Altair/Courier/Strategy/CommandRunnerMiddlewareStrategy.php b/src/Altair/Courier/Strategy/CommandRunnerMiddlewareStrategy.php index 2c555c28..a9ee6a46 100644 --- a/src/Altair/Courier/Strategy/CommandRunnerMiddlewareStrategy.php +++ b/src/Altair/Courier/Strategy/CommandRunnerMiddlewareStrategy.php @@ -24,10 +24,15 @@ */ class CommandRunnerMiddlewareStrategy implements CommandRunnerStrategyInterface { + /** + * @var array> + */ protected array $middlewares; /** * CommandRunnerMiddlewareStrategy constructor. + * + * @param array>|null $middlewares */ public function __construct(?array $middlewares = null, protected ?MiddlewareResolverInterface $resolver = null) { @@ -37,6 +42,7 @@ public function __construct(?array $middlewares = null, protected ?MiddlewareRes /** * Returns a new instance with * + * @param array> $middlewares * * @throws InvalidCommandMiddlewareException */ diff --git a/src/Altair/Doctor/Configuration/DoctorConfiguration.php b/src/Altair/Doctor/Configuration/DoctorConfiguration.php index 8d60b5a7..cf7e5598 100644 --- a/src/Altair/Doctor/Configuration/DoctorConfiguration.php +++ b/src/Altair/Doctor/Configuration/DoctorConfiguration.php @@ -147,7 +147,7 @@ private function readRequirements(string $projectRoot): array sort($extensions, SORT_STRING); - return [$floor, array_values($extensions)]; + return [$floor, $extensions]; } private function normalizeVersion(string $constraint, string $fallback): string diff --git a/src/Altair/Events/Cli/CheckpointCreateCommand.php b/src/Altair/Events/Cli/CheckpointCreateCommand.php index a9be57fe..16eec58b 100644 --- a/src/Altair/Events/Cli/CheckpointCreateCommand.php +++ b/src/Altair/Events/Cli/CheckpointCreateCommand.php @@ -41,7 +41,7 @@ public function __invoke( $head = $event; } - $eventId = $head?->id ?? ''; + $eventId = $head->id ?? ''; $this->storage->create($name, $eventId); diff --git a/src/Altair/Happen/Contracts/EventDispatcherInterface.php b/src/Altair/Happen/Contracts/EventDispatcherInterface.php index 0336fc6d..6538598c 100644 --- a/src/Altair/Happen/Contracts/EventDispatcherInterface.php +++ b/src/Altair/Happen/Contracts/EventDispatcherInterface.php @@ -87,8 +87,6 @@ public function hasListeners(string $event): bool; * The first parameter should be the event name. All event listeners will * be removed. * - * - * @return EventDispatcherInterface; */ public function removeAllListeners(string $event): EventDispatcherInterface; diff --git a/src/Altair/Http/Base/Payload.php b/src/Altair/Http/Base/Payload.php index 1a932168..ce65cc5c 100644 --- a/src/Altair/Http/Base/Payload.php +++ b/src/Altair/Http/Base/Payload.php @@ -14,7 +14,6 @@ use Altair\Http\Collection\InputCollection; use Altair\Http\Collection\SettingsCollection; use Altair\Http\Contracts\PayloadInterface; -use Altair\Structure\Map; use Override; class Payload implements PayloadInterface @@ -36,9 +35,6 @@ class Payload implements PayloadInterface */ protected $messages = []; - /** - * @var Map|null - */ protected SettingsCollection $settingsCollection; /** diff --git a/src/Altair/Http/Collection/HttpStatusCollection.php b/src/Altair/Http/Collection/HttpStatusCollection.php index aa835324..08c69450 100644 --- a/src/Altair/Http/Collection/HttpStatusCollection.php +++ b/src/Altair/Http/Collection/HttpStatusCollection.php @@ -20,7 +20,6 @@ use IteratorAggregate; use Override; use ReflectionClass; -use Traversable; /** * @implements IteratorAggregate @@ -36,9 +35,9 @@ class HttpStatusCollection implements Countable, IteratorAggregate /** * @inheritDoc - * @param array|Traversable $values + * @param iterable $values */ - public function __construct($values = []) + public function __construct(iterable $values = []) { $this->values = $this->buildCommonValues(); @@ -107,7 +106,7 @@ public function getReasonPhrase(int $code): string * @throws InvalidArgumentException If the requested $statusCode is not valid * */ - public function getResponseClass(int $code): string + public function getResponseClass(int $code): int { $responseClass = [ 1 => HttpStatusCodeInterface::RESPONSE_CLASS_INFORMATIONAL, @@ -117,7 +116,7 @@ public function getResponseClass(int $code): string 5 => HttpStatusCodeInterface::RESPONSE_CLASS_SERVER_ERROR, ]; $code = $this->filterCode($code); - return $responseClass[(int) substr($code, 0, 1)]; + return $responseClass[intdiv($code, 100)]; } /** @@ -172,14 +171,10 @@ public function merge(int $code, string $reason): void /** * Merges an array of status codes and its reason phrase into the default values. * - * @param array|Traversable $values + * @param iterable $values */ - public function mergeAll($values): void + public function mergeAll(iterable $values): void { - if (!\is_array($values) || !$values instanceof Traversable) { - throw new InvalidArgumentException("Values must be a Traversable object or an array"); - } - foreach ($values as $code => $reason) { $this->merge($code, $reason); } diff --git a/src/Altair/Http/Formatter/PhpViewFormatter.php b/src/Altair/Http/Formatter/PhpViewFormatter.php index c5468368..988ea2d2 100644 --- a/src/Altair/Http/Formatter/PhpViewFormatter.php +++ b/src/Altair/Http/Formatter/PhpViewFormatter.php @@ -14,7 +14,6 @@ use Altair\Http\Contracts\PayloadInterface; use Altair\Http\Exception\InvalidArgumentException; use Altair\Http\Exception\RuntimeException; -use Exception; use Override; use Throwable; @@ -94,7 +93,6 @@ protected function renderLayout(PayloadInterface $payload, $content): string * * @param array $params * - * @throws Exception * @throws Throwable */ protected function renderPhpFile(string $file, array $params = []): string @@ -108,14 +106,14 @@ protected function renderPhpFile(string $file, array $params = []): string require($file); return ob_get_clean(); - } catch (Exception|Throwable $e) { + } catch (Throwable $throwable) { while (ob_get_level() > $level) { if (!@ob_end_clean()) { ob_clean(); } } - throw $e; + throw $throwable; } } diff --git a/src/Altair/Http/Middleware/SessionHeadersMiddleware.php b/src/Altair/Http/Middleware/SessionHeadersMiddleware.php index ed5be155..0bb780da 100644 --- a/src/Altair/Http/Middleware/SessionHeadersMiddleware.php +++ b/src/Altair/Http/Middleware/SessionHeadersMiddleware.php @@ -32,7 +32,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface { $prevName = session_name(); $prevCookie = $this->cookieManager->getFromRequest($request, $prevName); - $prevId = $prevCookie?->getValue(); + $prevId = $prevCookie->getValue(); if ($prevId !== null) { session_id($prevId); } @@ -57,9 +57,9 @@ private function createNewSessionCookie(string $sessionId): SetCookie $params = session_get_cookie_params(); return (new SetCookie((string) session_name(), $sessionId)) - ->withDomain($params['domain'] ?? null) - ->withPath($params['path'] ?? null) - ->withExpires($params['lifetime'] ?? null) + ->withDomain($params['domain']) + ->withPath($params['path']) + ->withExpires($params['lifetime']) ->withSecure(!empty($params['secure'])) ->withHttpOnly(!empty($params['httponly'])); } diff --git a/src/Altair/Http/Middleware/SpamBlockerMiddleware.php b/src/Altair/Http/Middleware/SpamBlockerMiddleware.php index dffcaadd..4bdb287c 100644 --- a/src/Altair/Http/Middleware/SpamBlockerMiddleware.php +++ b/src/Altair/Http/Middleware/SpamBlockerMiddleware.php @@ -39,7 +39,7 @@ public function __construct( } $entries = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); - $this->list = $entries === false ? [] : array_values($entries); + $this->list = $entries === false ? [] : $entries; } #[Override] diff --git a/src/Altair/Http/Responder/CompoundResponder.php b/src/Altair/Http/Responder/CompoundResponder.php index 32d23c05..eb285ca0 100644 --- a/src/Altair/Http/Responder/CompoundResponder.php +++ b/src/Altair/Http/Responder/CompoundResponder.php @@ -53,7 +53,7 @@ public function __invoke( PayloadInterface $payload ): ResponseInterface { foreach ($this->responders as $responder) { - /** @var callable $responder */ + /** @var ResponderInterface $responder */ $responder = $this->resolve($responder); $response = $responder($request, $response, $payload); } diff --git a/src/Altair/Http/Responder/StatusResponder.php b/src/Altair/Http/Responder/StatusResponder.php index 8a1203e4..fae8cbc6 100644 --- a/src/Altair/Http/Responder/StatusResponder.php +++ b/src/Altair/Http/Responder/StatusResponder.php @@ -63,11 +63,13 @@ private function hasStatus(PayloadInterface $payload): bool */ private function status(ResponseInterface $response, PayloadInterface $payload): ResponseInterface { - $status = $payload->getStatus(); - $code = $this->httpStatusCollection->getStatusCode($status); + $code = (int) $payload->getStatus(); + $reason = $this->httpStatusCollection->hasCode($code) + ? $this->httpStatusCollection->getReasonPhrase($code) + : ''; try { - return $response->withStatus($code); + return $response->withStatus($code, $reason); } catch (\InvalidArgumentException $invalidArgumentException) { throw new InvalidArgumentException($invalidArgumentException->getMessage(), $invalidArgumentException->getCode(), $invalidArgumentException->getPrevious()); } diff --git a/src/Altair/Http/Support/DefaultErrorHandler.php b/src/Altair/Http/Support/DefaultErrorHandler.php index d206e76a..cb78d486 100644 --- a/src/Altair/Http/Support/DefaultErrorHandler.php +++ b/src/Altair/Http/Support/DefaultErrorHandler.php @@ -193,7 +193,7 @@ protected function png($statusCode, $message): void * @param int $statusCode * @param string $message * - * @return resource + * @return GdImage|false */ protected function createImage($statusCode, $message): GdImage|false { diff --git a/src/Altair/Introspection/Inspector/ConfigInspector.php b/src/Altair/Introspection/Inspector/ConfigInspector.php index d0cf3af6..9ae54463 100644 --- a/src/Altair/Introspection/Inspector/ConfigInspector.php +++ b/src/Altair/Introspection/Inspector/ConfigInspector.php @@ -82,8 +82,8 @@ private function collectEnv(): iterable // De-duplicate across the three sources; $_ENV wins over $_SERVER wins over getenv(). $merged = array_merge( $this->envFromGetenv(), - \is_array($_SERVER) ? $_SERVER : [], - \is_array($_ENV) ? $_ENV : [], + $_SERVER, + $_ENV, ); ksort($merged); diff --git a/src/Altair/Sanitation/Filter/IntegerFilter.php b/src/Altair/Sanitation/Filter/IntegerFilter.php index 9e17e506..140029de 100644 --- a/src/Altair/Sanitation/Filter/IntegerFilter.php +++ b/src/Altair/Sanitation/Filter/IntegerFilter.php @@ -15,13 +15,8 @@ class IntegerFilter extends AbstractFilter { - /** - * @param mixed $value - * - * @return int|mixed|null - */ #[Override] - public function parse($value): ?int + public function parse(mixed $value): ?int { if (!\is_scalar($value)) { return null; diff --git a/src/Altair/Sanitation/FiltersRunner.php b/src/Altair/Sanitation/FiltersRunner.php index 93774f99..7349320c 100644 --- a/src/Altair/Sanitation/FiltersRunner.php +++ b/src/Altair/Sanitation/FiltersRunner.php @@ -33,8 +33,7 @@ class FiltersRunner implements FiltersRunnerInterface * * Constructor. * - * @param callable|ResolverInterface $resolver Converts queue entries to callables. - * @param Queue $queue The middleware queue. + * @param Queue|null $queue The middleware queue. */ public function __construct(?ResolverInterface $resolver = null, protected ?Queue $queue = null) { diff --git a/src/Altair/Sanitation/Sanitizer.php b/src/Altair/Sanitation/Sanitizer.php index 6f55a9d1..513c4407 100644 --- a/src/Altair/Sanitation/Sanitizer.php +++ b/src/Altair/Sanitation/Sanitizer.php @@ -21,10 +21,7 @@ class Sanitizer implements SanitizerInterface { - /** - * @var Payload - */ - protected $payload; + protected MiddlewarePayloadInterface $payload; /** * Validator constructor. diff --git a/src/Altair/Scaffold/Sdk/Model/OpenApiParser.php b/src/Altair/Scaffold/Sdk/Model/OpenApiParser.php index 8710732a..f6d63d96 100644 --- a/src/Altair/Scaffold/Sdk/Model/OpenApiParser.php +++ b/src/Altair/Scaffold/Sdk/Model/OpenApiParser.php @@ -272,7 +272,7 @@ private function extractPathParameters(string $path): array { preg_match_all('/\{([A-Za-z_]\w*)\}/', $path, $matches); - return array_values($matches[1]); + return $matches[1]; } /** diff --git a/src/Altair/Security/Support/Pbkdf2Key.php b/src/Altair/Security/Support/Pbkdf2Key.php index 0452d8ca..58bd0e66 100644 --- a/src/Altair/Security/Support/Pbkdf2Key.php +++ b/src/Altair/Security/Support/Pbkdf2Key.php @@ -11,7 +11,6 @@ namespace Altair\Security\Support; -use Altair\Security\Exception\InvalidConfigException; use Override; class Pbkdf2Key extends AbstractKey @@ -30,18 +29,10 @@ public function __construct( /** * @inheritDoc - * - * @throws InvalidConfigException */ #[Override] public function derive(): string { - $outputKey = hash_pbkdf2($this->algorithm, $this->key, (string) $this->salt, $this->iterations, $this->length, true); - - if ($outputKey === false) { - throw new InvalidConfigException('Invalid parameters to hash_pbkdf2().'); - } - - return $outputKey; + return hash_pbkdf2($this->algorithm, $this->key, (string) $this->salt, $this->iterations, $this->length, true); } } diff --git a/src/Altair/Session/Handler/FileSessionHandler.php b/src/Altair/Session/Handler/FileSessionHandler.php index f1eb9f42..4fa984d8 100644 --- a/src/Altair/Session/Handler/FileSessionHandler.php +++ b/src/Altair/Session/Handler/FileSessionHandler.php @@ -59,15 +59,18 @@ public function destroy($session_id) */ #[ReturnTypeWillChange] #[Override] - public function gc($maxlifetime): void + public function gc($maxlifetime): int|false { $files = $this->filesystem->listAllFiles($this->path); $now = time(); + $deleted = 0; foreach ($files as $file) { - if (filemtime($file->getPathname()) + $maxlifetime <= $now) { - $this->filesystem->delete($file->getPathname()); + if (filemtime($file->getPathname()) + $maxlifetime <= $now && $this->filesystem->delete($file->getPathname())) { + ++$deleted; } } + + return $deleted; } /** diff --git a/src/Altair/Session/Handler/MongoSessionHandler.php b/src/Altair/Session/Handler/MongoSessionHandler.php index 3709100e..570fb273 100644 --- a/src/Altair/Session/Handler/MongoSessionHandler.php +++ b/src/Altair/Session/Handler/MongoSessionHandler.php @@ -120,10 +120,10 @@ public function destroy($sessionId) */ #[ReturnTypeWillChange] #[Override] - public function gc($maxlifetime) + public function gc($maxlifetime): int|false { try { - $this->collection->deleteMany( + $result = $this->collection->deleteMany( [ 'session_lifetime' => ['$lt' => $this->createUTCDateTime()], ] @@ -132,7 +132,7 @@ public function gc($maxlifetime) return false; } - return true; + return $result->getDeletedCount(); } /** diff --git a/src/Altair/Session/Handler/PdoSessionHandler.php b/src/Altair/Session/Handler/PdoSessionHandler.php index 2d3a5405..3a9018f1 100644 --- a/src/Altair/Session/Handler/PdoSessionHandler.php +++ b/src/Altair/Session/Handler/PdoSessionHandler.php @@ -103,11 +103,14 @@ public function destroy($sessionId) */ #[ReturnTypeWillChange] #[Override] - public function gc($maxlifetime) + public function gc($maxlifetime): int|false { // We delay gc() to close() so that it is executed outside the transactional and blocking read-write process. // This way, pruning expired sessions does not block them from being started while the current session is used. - return $this->gcCalled = true; + // The actual pruning (and its count) happens in close(); at this point nothing has been deleted yet. + $this->gcCalled = true; + + return 0; } /** diff --git a/src/Altair/Structure/PriorityNode.php b/src/Altair/Structure/PriorityNode.php index 7a68e9f7..9a2b098f 100644 --- a/src/Altair/Structure/PriorityNode.php +++ b/src/Altair/Structure/PriorityNode.php @@ -25,38 +25,23 @@ */ class PriorityNode implements PriorityNodeInterface { - /** - * @var int - */ - public $priority; - - /** - * @var int - */ - public $stamp; - /** * PriorityNode constructor. * * @param TValue $value */ - public function __construct(public mixed $value, int $priority, int $stamp) - { - $this->priority = $priority; - $this->stamp = $stamp; - } + public function __construct(public mixed $value, public int $priority, public int $stamp) {} /** - * This allows unset($pair->key) to not completely remove the property, - * but be set to null instead. - * + * Allows unset($node->value) to soft-null the payload rather than remove it. * - * @return mixed|null + * priority and stamp are required ordering keys (always int) and are not + * accessible through this magic getter. */ - public function __get(mixed $name): mixed + public function __get(string $name): mixed { - if (\in_array($name, ['value', 'priority', 'stamp'], true)) { - $this->$name = null; + if ($name === 'value') { + $this->value = null; return null; } diff --git a/src/Altair/Structure/Traits/SequenceTrait.php b/src/Altair/Structure/Traits/SequenceTrait.php index 07823d16..f2ac0eed 100644 --- a/src/Altair/Structure/Traits/SequenceTrait.php +++ b/src/Altair/Structure/Traits/SequenceTrait.php @@ -195,9 +195,7 @@ public function pop() } $value = array_pop($this->internal); - if (method_exists($this, 'adjustCapacity')) { - $this->adjustCapacity(); - } + $this->adjustCapacity(); return $value; } @@ -234,9 +232,7 @@ public function remove(int $index) $this->checkRange($index); $value = array_splice($this->internal, $index, 1, null)[0]; - if (method_exists($this, 'adjustCapacity')) { - $this->adjustCapacity(); - } + $this->adjustCapacity(); return $value; } @@ -299,9 +295,7 @@ public function shift() } $value = array_shift($this->internal); - if (method_exists($this, 'adjustCapacity')) { - $this->adjustCapacity(); - } + $this->adjustCapacity(); return $value; } @@ -429,6 +423,14 @@ public function offsetExists($offset) return $this->get($offset) !== null; } + /** + * Rebalances the backing storage capacity after a mutation. + * + * Provided by the capacity trait the consuming collection composes + * (CapacityTrait / SquaredCapacityTrait). + */ + abstract protected function adjustCapacity(): void; + protected function checkRange(int $index): void { if ($index < 0 || $index >= \count($this->internal)) { diff --git a/src/Altair/Validation/Rule/CreditCardRule.php b/src/Altair/Validation/Rule/CreditCardRule.php index d5abbbdb..be201d30 100644 --- a/src/Altair/Validation/Rule/CreditCardRule.php +++ b/src/Altair/Validation/Rule/CreditCardRule.php @@ -167,7 +167,7 @@ protected function assertLuhn($value): bool $checksum = 0; $length = \strlen($cardNumber); for ($i = 0; $i < $length; $i++) { - $currentNum = $cardNumber[$i]; + $currentNum = (int) $cardNumber[$i]; if ($i % 2 === 1) { $currentNum *= 2; } diff --git a/src/Altair/Validation/Rule/IpRule.php b/src/Altair/Validation/Rule/IpRule.php index 964c06ef..57ea55bb 100644 --- a/src/Altair/Validation/Rule/IpRule.php +++ b/src/Altair/Validation/Rule/IpRule.php @@ -108,11 +108,12 @@ protected function parseRangeUsingCidr(string $value, array $range): array return $range; } - if ($isMask || $max < 8 || $max > 30) { + $prefix = (int) $max; + if ($isMask || $prefix < 8 || $prefix > 30) { throw new InvalidArgumentException('Invalid network mask.'); } - $range['mask'] = \sprintf('%032b', ip2long(long2ip(~((2 ** (32 - $max)) - 1)))); + $range['mask'] = \sprintf('%032b', ip2long(long2ip(~((2 ** (32 - $prefix)) - 1)))); return $range; } diff --git a/src/Altair/Validation/Rule/IsbnRule.php b/src/Altair/Validation/Rule/IsbnRule.php index 68f44e22..36a7bfd3 100644 --- a/src/Altair/Validation/Rule/IsbnRule.php +++ b/src/Altair/Validation/Rule/IsbnRule.php @@ -88,13 +88,8 @@ protected function assertIsbn13(string $value): bool $checksum = 0; for ($i = 0; $i < $length; $i += 2) { - if ($length % 2 === 0) { - $checksum += 3 * (int) substr($value, $i, 1); - $checksum += (int) substr($value, $i + 1, 1); - } else { - $checksum += (int) substr($value, $i, 1); - $checksum += 3 * (int) substr($value, $i + 1, 1); - } + $checksum += (int) substr($value, $i, 1); + $checksum += 3 * (int) substr($value, $i + 1, 1); } return $checksum % 10 === 0; diff --git a/src/Altair/Validation/RulesRunner.php b/src/Altair/Validation/RulesRunner.php index 4bbfa0a2..95459786 100644 --- a/src/Altair/Validation/RulesRunner.php +++ b/src/Altair/Validation/RulesRunner.php @@ -21,19 +21,13 @@ class RulesRunner implements RulesRunnerInterface { /** - * - * A callable to convert queue entries to callables. - * - * @var callable|ResolverInterface - * + * A resolver to convert queue entries to callables. */ - protected $resolver; + protected ?ResolverInterface $resolver; /** - * * Constructor. * - * @param callable|ResolverInterface $resolver Converts queue entries to callables. * @param Queue $queue The middleware queue. */ public function __construct(?ResolverInterface $resolver = null, protected ?Queue $queue = null) @@ -79,7 +73,7 @@ protected function resolve($entry) return fn(PayloadInterface $payload, callable $next): PayloadInterface => $payload; } - if (!$this->resolver) { + if (!$this->resolver instanceof ResolverInterface) { return $entry; } diff --git a/src/Altair/Validation/Validator.php b/src/Altair/Validation/Validator.php index ce15bcde..efa4a538 100644 --- a/src/Altair/Validation/Validator.php +++ b/src/Altair/Validation/Validator.php @@ -21,10 +21,7 @@ class Validator implements ValidatorInterface { - /** - * @var Payload - */ - protected $payload; + protected MiddlewarePayloadInterface $payload; /** * Validator constructor.