From 5092bc4cfda0974dfde323619c4b3ca7d99e495f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Sun, 1 Aug 2021 04:49:26 +0200 Subject: [PATCH] Params are now objects too --- src/DisallowedCall.php | 38 ++++++----------- src/DisallowedCallFactory.php | 23 +++++++++-- src/DisallowedHelper.php | 24 ++++------- src/Params/DisallowedCallParam.php | 13 ++++++ ...lowedCallParamWithCaseInsensitiveValue.php | 41 +++++++++++++++++++ src/Params/DisallowedCallParamWithValue.php | 38 +++++++++++++++++ 6 files changed, 132 insertions(+), 45 deletions(-) create mode 100644 src/Params/DisallowedCallParam.php create mode 100644 src/Params/DisallowedCallParamWithCaseInsensitiveValue.php create mode 100644 src/Params/DisallowedCallParamWithValue.php diff --git a/src/DisallowedCall.php b/src/DisallowedCall.php index 119d788..8ba3204 100644 --- a/src/DisallowedCall.php +++ b/src/DisallowedCall.php @@ -3,6 +3,8 @@ namespace Spaze\PHPStan\Rules\Disallowed; +use Spaze\PHPStan\Rules\Disallowed\Params\DisallowedCallParam; + class DisallowedCall { @@ -15,18 +17,15 @@ class DisallowedCall /** @var string[] */ private $allowIn; - /** @var array */ + /** @var array */ private $allowParamsInAllowed; - /** @var array */ + /** @var array */ private $allowParamsAnywhere; - /** @var array */ + /** @var array */ private $allowExceptParams; - /** @var array */ - private $allowExceptCaseInsensitiveParams; - /** * DisallowedCall constructor. @@ -34,12 +33,11 @@ class DisallowedCall * @param string $call * @param string|null $message * @param string[] $allowIn - * @param array $allowParamsInAllowed - * @param array $allowParamsAnywhere - * @param array $allowExceptParams - * @param array $allowExceptCaseInsensitiveParams + * @param array $allowParamsInAllowed + * @param array $allowParamsAnywhere + * @param array $allowExceptParams */ - public function __construct(string $call, ?string $message, array $allowIn, array $allowParamsInAllowed, array $allowParamsAnywhere, array $allowExceptParams, array $allowExceptCaseInsensitiveParams) + public function __construct(string $call, ?string $message, array $allowIn, array $allowParamsInAllowed, array $allowParamsAnywhere, array $allowExceptParams) { $call = substr($call, -2) === '()' ? substr($call, 0, -2) : $call; $this->call = ltrim($call, '\\'); @@ -48,7 +46,6 @@ public function __construct(string $call, ?string $message, array $allowIn, arra $this->allowParamsInAllowed = $allowParamsInAllowed; $this->allowParamsAnywhere = $allowParamsAnywhere; $this->allowExceptParams = $allowExceptParams; - $this->allowExceptCaseInsensitiveParams = $allowExceptCaseInsensitiveParams; } @@ -74,7 +71,7 @@ public function getAllowIn(): array /** - * @return array + * @return array */ public function getAllowParamsInAllowed(): array { @@ -83,7 +80,7 @@ public function getAllowParamsInAllowed(): array /** - * @return array + * @return array */ public function getAllowParamsAnywhere(): array { @@ -92,7 +89,7 @@ public function getAllowParamsAnywhere(): array /** - * @return array + * @return array */ public function getAllowExceptParams(): array { @@ -100,20 +97,11 @@ public function getAllowExceptParams(): array } - /** - * @return array - */ - public function getAllowExceptCaseInsensitiveParams(): array - { - return $this->allowExceptCaseInsensitiveParams; - } - - public function getKey(): string { // The key consists of "initial" config values that would be overwritten with more specific details in a custom config. // `allowIn` & `allowParams*` aren't included because these are set by the user in their config, not in the bundled files. - return serialize([$this->getCall(), $this->getAllowExceptParams(), $this->getAllowExceptCaseInsensitiveParams()]); + return serialize([$this->getCall(), $this->getAllowExceptParams()]); } } diff --git a/src/DisallowedCallFactory.php b/src/DisallowedCallFactory.php index d94e6b1..16bee8d 100644 --- a/src/DisallowedCallFactory.php +++ b/src/DisallowedCallFactory.php @@ -4,6 +4,8 @@ namespace Spaze\PHPStan\Rules\Disallowed; use PHPStan\ShouldNotHappenException; +use Spaze\PHPStan\Rules\Disallowed\Params\DisallowedCallParamWithCaseInsensitiveValue; +use Spaze\PHPStan\Rules\Disallowed\Params\DisallowedCallParamWithValue; class DisallowedCallFactory { @@ -23,14 +25,27 @@ public function createFromConfig(array $config): array if (!$call) { throw new ShouldNotHappenException("Either 'method' or 'function' must be set in configuration items"); } + + $allowParamsInAllowed = $allowParamsAnywhere = $allowExceptParams = []; + foreach ($disallowedCall['allowParamsInAllowed'] ?? [] as $param => $value) { + $allowParamsInAllowed[$param] = new DisallowedCallParamWithValue($value); + } + foreach ($disallowedCall['allowParamsAnywhere'] ?? [] as $param => $value) { + $allowParamsAnywhere[$param] = new DisallowedCallParamWithValue($value); + } + foreach ($disallowedCall['allowExceptParams'] ?? [] as $param => $value) { + $allowExceptParams[$param] = new DisallowedCallParamWithValue($value); + } + foreach ($disallowedCall['allowExceptCaseInsensitiveParams'] ?? [] as $param => $value) { + $allowExceptParams[$param] = new DisallowedCallParamWithCaseInsensitiveValue($value); + } $disallowedCall = new DisallowedCall( $call, $disallowedCall['message'] ?? null, $disallowedCall['allowIn'] ?? [], - $disallowedCall['allowParamsInAllowed'] ?? [], - $disallowedCall['allowParamsAnywhere'] ?? [], - $disallowedCall['allowExceptParams'] ?? [], - $disallowedCall['allowExceptCaseInsensitiveParams'] ?? [] + $allowParamsInAllowed, + $allowParamsAnywhere, + $allowExceptParams ); $calls[$disallowedCall->getKey()] = $disallowedCall; } diff --git a/src/DisallowedHelper.php b/src/DisallowedHelper.php index e91d3ad..0805b20 100644 --- a/src/DisallowedHelper.php +++ b/src/DisallowedHelper.php @@ -10,11 +10,11 @@ use PHPStan\Analyser\Scope; use PHPStan\Broker\ClassNotFoundException; use PHPStan\Reflection\MethodReflection; -use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\ConstantScalarType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use PHPStan\Type\TypeWithClassName; +use Spaze\PHPStan\Rules\Disallowed\Params\DisallowedCallParam; class DisallowedHelper { @@ -60,7 +60,7 @@ private function isAllowed(Scope $scope, ?Node $node, DisallowedCall $disallowed * @param Expr|null $node * @phpstan-param ForbiddenCalls|null $node * @noinspection PhpUndefinedClassInspection ForbiddenCalls is a type alias defined in PHPStan config - * @param array $allowConfig + * @param array $allowConfig * @return boolean */ private function hasAllowedParams(Scope $scope, ?Node $node, array $allowConfig): bool @@ -71,7 +71,10 @@ private function hasAllowedParams(Scope $scope, ?Node $node, array $allowConfig) foreach ($allowConfig as $param => $value) { $type = $this->getArgType($node, $scope, $param); - if (!$type instanceof ConstantScalarType || $value !== $type->getValue()) { + if (!$type instanceof ConstantScalarType) { + return false; + } + if (!$value->matches($type)) { return false; } } @@ -95,20 +98,10 @@ private function matchesAllowExceptParam(Scope $scope, ?Node $node, DisallowedCa foreach ($disallowedCall->getAllowExceptParams() as $param => $value) { $type = $this->getArgType($node, $scope, $param); - if ($type instanceof ConstantScalarType && $value === $type->getValue()) { + if ($type instanceof ConstantScalarType && $value->matches($type)) { return true; } } - foreach ($disallowedCall->getAllowExceptCaseInsensitiveParams() as $param => $value) { - $type = $this->getArgType($node, $scope, $param); - if ($type instanceof ConstantScalarType) { - $a = is_string($value) ? strtolower($value) : $value; - $b = $type instanceof ConstantStringType ? strtolower($type->getValue()) : $type->getValue(); - if ($a === $b) { - return true; - } - } - } return false; } @@ -169,8 +162,7 @@ public function getDisallowedMessage(?Node $node, Scope $scope, string $name, ?s private function callMatches(Scope $scope, ?Node $node, DisallowedCall $disallowedCall, string $name): bool { if ($name === $disallowedCall->getCall() || fnmatch($disallowedCall->getCall(), $name, FNM_NOESCAPE)) { - $noAllowExceptParams = count($disallowedCall->getAllowExceptParams()) === 0 && count($disallowedCall->getAllowExceptCaseInsensitiveParams()) === 0; - return $noAllowExceptParams || $this->matchesAllowExceptParam($scope, $node, $disallowedCall); + return count($disallowedCall->getAllowExceptParams()) === 0 || $this->matchesAllowExceptParam($scope, $node, $disallowedCall); } return false; } diff --git a/src/Params/DisallowedCallParam.php b/src/Params/DisallowedCallParam.php new file mode 100644 index 0000000..3817b60 --- /dev/null +++ b/src/Params/DisallowedCallParam.php @@ -0,0 +1,13 @@ +value = $value; + } + + + public function matches(ConstantScalarType $type): bool + { + $a = is_string($this->value) ? strtolower($this->value) : $this->value; + $b = $type instanceof ConstantStringType ? strtolower($type->getValue()) : $type->getValue(); + return $a === $b; + } + + + /** + * @return integer|boolean|string + */ + public function getValue() + { + return $this->value; + } + +} diff --git a/src/Params/DisallowedCallParamWithValue.php b/src/Params/DisallowedCallParamWithValue.php new file mode 100644 index 0000000..cb95fa0 --- /dev/null +++ b/src/Params/DisallowedCallParamWithValue.php @@ -0,0 +1,38 @@ +value = $value; + } + + + public function matches(ConstantScalarType $type): bool + { + return $this->value === $type->getValue(); + } + + + /** + * @return integer|boolean|string + */ + public function getValue() + { + return $this->value; + } + +}