From ad294134fd9490c2d23de95d0a42984736561d9b Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Sat, 2 Sep 2023 22:16:04 -0700 Subject: [PATCH 1/8] more dynamic phpstan extensions --- ...ndAllDynamicMethodReturnTypeReflection.php | 40 +++++ .../ModelMethodsClassReflectionExtension.php | 31 ++++ lib/PhpStan/ModelParameterReflection.php | 44 +++++ lib/PhpStan/ModelStaticMethodReflection.php | 161 ++++++++++++++++++ phpstan.neon.dist | 8 + ...tanReflectionTests.php => DynamicFInd.php} | 2 + test/phpstan/DynamicFIndAll.php | 14 ++ test/phpstan/DynamicFindBy.php | 14 ++ 8 files changed, 314 insertions(+) create mode 100644 lib/PhpStan/FindAllDynamicMethodReturnTypeReflection.php create mode 100644 lib/PhpStan/ModelMethodsClassReflectionExtension.php create mode 100644 lib/PhpStan/ModelParameterReflection.php create mode 100644 lib/PhpStan/ModelStaticMethodReflection.php rename test/phpstan/{PhpStanReflectionTests.php => DynamicFInd.php} (99%) create mode 100644 test/phpstan/DynamicFIndAll.php create mode 100644 test/phpstan/DynamicFindBy.php diff --git a/lib/PhpStan/FindAllDynamicMethodReturnTypeReflection.php b/lib/PhpStan/FindAllDynamicMethodReturnTypeReflection.php new file mode 100644 index 00000000..fca14adc --- /dev/null +++ b/lib/PhpStan/FindAllDynamicMethodReturnTypeReflection.php @@ -0,0 +1,40 @@ +getName(); + $pos = strpos($name, "find_all"); + return $pos === 0; + } + + public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope): Type + { + $class = $methodReflection->getDeclaringClass(); + return new ArrayType( + new IntegerType(), + new ObjectType($class->getName()) + ); + } +} diff --git a/lib/PhpStan/ModelMethodsClassReflectionExtension.php b/lib/PhpStan/ModelMethodsClassReflectionExtension.php new file mode 100644 index 00000000..b440cf0b --- /dev/null +++ b/lib/PhpStan/ModelMethodsClassReflectionExtension.php @@ -0,0 +1,31 @@ +isSubclassOf(Model::class)) { + if (preg_match("/find_(all_)?by_/", $methodName)) { + return true; + } + + if (str_ends_with($methodName, "_set")) { + return true; + } + } + + return false; + } + + public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection + { + return new ModelStaticMethodReflection($classReflection, $methodName); + } +} diff --git a/lib/PhpStan/ModelParameterReflection.php b/lib/PhpStan/ModelParameterReflection.php new file mode 100644 index 00000000..c2c3abe1 --- /dev/null +++ b/lib/PhpStan/ModelParameterReflection.php @@ -0,0 +1,44 @@ +classReflection = $classReflection; + $this->name = $name; + } + + public function isFinal(): \PHPStan\TrinaryLogic + { + // TODO: Implement isFinal() method. + return TrinaryLogic::createNo(); + } + + public function isInternal(): \PHPStan\TrinaryLogic + { + // TODO: Implement isInternal() method. + return TrinaryLogic::createNo(); + } + + public function getDocComment(): ?string + { + // TODO: Implement getDocComment() method. + return null; + } + + public function isDeprecated(): \PHPStan\TrinaryLogic + { + // TODO: Implement isDeprecated() method. + return TrinaryLogic::createNo(); + } + + public function hasSideEffects(): \PHPStan\TrinaryLogic + { + // TODO: Implement hasSideEffects() method. + return TrinaryLogic::createMaybe(); + } + + public function getThrowType(): ?\PHPStan\Type\Type + { + // TODO: Implement getThrowType() method. + return null; + } + + public function getDeprecatedDescription(): ?string + { + // TODO: Implement getDeprecatedDescription() method. + return null; + } + + public function getDeclaringClass(): ClassReflection + { + return $this->classReflection; + } + + public function getPrototype(): ClassMemberReflection + { + return $this; + } + + public function isStatic(): bool + { + return true; + } + + public function isPrivate(): bool + { + return false; + } + + public function isPublic(): bool + { + return true; + } + + public function getName(): string + { + return $this->name; + } + + public function isVariadic(): bool + { + return false; + } + + /** + * @return \PHPStan\Reflection\ParametersAcceptor[] + */ + public function getVariants(): array + { + if (preg_match("/find_(all_)?by_/", $this->name)) { + return [ + new FunctionVariant( + TemplateTypeMap::createEmpty(), + TemplateTypeMap::createEmpty(), + [new ModelParameterReflection()], + false, + new ObjectType($this->classReflection->getDisplayName()) + ) + ]; + } elseif (preg_match("/_set$/", $this->name)) { + return [ + new FunctionVariant( + TemplateTypeMap::createEmpty(), + TemplateTypeMap::createEmpty(), + [new ModelParameterReflection()], + false, + new ObjectType($this->classReflection->getDisplayName()) + ) + ]; + } elseif (preg_match("/_refresh/", $this->name)) { + return [ + new FunctionVariant( + TemplateTypeMap::createEmpty(), + TemplateTypeMap::createEmpty(), + [], + false, + new VoidType() + ) + ]; + } elseif (preg_match("/_dirty/", $this->name)) { + return [ + new FunctionVariant( + TemplateTypeMap::createEmpty(), + TemplateTypeMap::createEmpty(), + [], + false, + new VoidType() + ) + ]; + } + + return [ + new FunctionVariant( + TemplateTypeMap::createEmpty(), + TemplateTypeMap::createEmpty(), + [], + false, + new ObjectType($this->classReflection->getDisplayName()) + ), + ]; + } +} diff --git a/phpstan.neon.dist b/phpstan.neon.dist index bf5a659d..5dca0cd0 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -13,6 +13,14 @@ services: class: ActiveRecord\PhpStan\FindDynamicMethodReturnTypeReflection tags: - phpstan.broker.dynamicStaticMethodReturnTypeExtension + - + class: ActiveRecord\PhpStan\FindAllDynamicMethodReturnTypeReflection + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + - + class: ActiveRecord\PhpStan\ModelMethodsClassReflectionExtension + tags: + - phpstan.broker.methodsClassReflectionExtension includes: - vendor/phpstan/phpstan-phpunit/extension.neon diff --git a/test/phpstan/PhpStanReflectionTests.php b/test/phpstan/DynamicFInd.php similarity index 99% rename from test/phpstan/PhpStanReflectionTests.php rename to test/phpstan/DynamicFInd.php index 2e88ded2..bd539496 100644 --- a/test/phpstan/PhpStanReflectionTests.php +++ b/test/phpstan/DynamicFInd.php @@ -45,3 +45,5 @@ $books = Book::find(['conditions'=> ['name' => 'Kurt']]); assert(0==count($books)); + + diff --git a/test/phpstan/DynamicFIndAll.php b/test/phpstan/DynamicFIndAll.php new file mode 100644 index 00000000..afa13abd --- /dev/null +++ b/test/phpstan/DynamicFIndAll.php @@ -0,0 +1,14 @@ + Date: Sat, 2 Sep 2023 22:23:53 -0700 Subject: [PATCH 2/8] linting --- ...indAllDynamicMethodReturnTypeReflection.php | 7 ++++--- .../ModelMethodsClassReflectionExtension.php | 4 ++-- lib/PhpStan/ModelParameterReflection.php | 5 ++--- lib/PhpStan/ModelStaticMethodReflection.php | 18 +++++++++--------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/PhpStan/FindAllDynamicMethodReturnTypeReflection.php b/lib/PhpStan/FindAllDynamicMethodReturnTypeReflection.php index fca14adc..c38069e3 100644 --- a/lib/PhpStan/FindAllDynamicMethodReturnTypeReflection.php +++ b/lib/PhpStan/FindAllDynamicMethodReturnTypeReflection.php @@ -13,7 +13,6 @@ use PHPStan\Type\IntegerType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; -use PHPStan\Type\UnionType; class FindAllDynamicMethodReturnTypeReflection implements DynamicStaticMethodReturnTypeExtension { @@ -25,13 +24,15 @@ public function getClass(): string public function isStaticMethodSupported(MethodReflection $methodReflection): bool { $name = $methodReflection->getName(); - $pos = strpos($name, "find_all"); - return $pos === 0; + $pos = strpos($name, 'find_all'); + + return 0 === $pos; } public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope): Type { $class = $methodReflection->getDeclaringClass(); + return new ArrayType( new IntegerType(), new ObjectType($class->getName()) diff --git a/lib/PhpStan/ModelMethodsClassReflectionExtension.php b/lib/PhpStan/ModelMethodsClassReflectionExtension.php index b440cf0b..8297bc72 100644 --- a/lib/PhpStan/ModelMethodsClassReflectionExtension.php +++ b/lib/PhpStan/ModelMethodsClassReflectionExtension.php @@ -12,11 +12,11 @@ class ModelMethodsClassReflectionExtension implements MethodsClassReflectionExte public function hasMethod(ClassReflection $classReflection, string $methodName): bool { if ($classReflection->isSubclassOf(Model::class)) { - if (preg_match("/find_(all_)?by_/", $methodName)) { + if (preg_match('/find_(all_)?by_/', $methodName)) { return true; } - if (str_ends_with($methodName, "_set")) { + if (str_ends_with($methodName, '_set')) { return true; } } diff --git a/lib/PhpStan/ModelParameterReflection.php b/lib/PhpStan/ModelParameterReflection.php index c2c3abe1..7ed44f2f 100644 --- a/lib/PhpStan/ModelParameterReflection.php +++ b/lib/PhpStan/ModelParameterReflection.php @@ -4,10 +4,9 @@ namespace ActiveRecord\PhpStan; -use PHPStan\Reflection\PassedByReference; use PHPStan\Reflection\ParameterReflection; +use PHPStan\Reflection\PassedByReference; use PHPStan\Type\MixedType; -use PHPStan\Type\StringType; use PHPStan\Type\Type; class ModelParameterReflection implements ParameterReflection @@ -22,7 +21,7 @@ public function isOptional(): bool return false; } - public function getDefaultValue(): ?\PHPStan\Type\Type + public function getDefaultValue(): ?Type { return null; } diff --git a/lib/PhpStan/ModelStaticMethodReflection.php b/lib/PhpStan/ModelStaticMethodReflection.php index 361b69bc..617c5bd7 100644 --- a/lib/PhpStan/ModelStaticMethodReflection.php +++ b/lib/PhpStan/ModelStaticMethodReflection.php @@ -6,8 +6,8 @@ use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\FunctionVariant; +use PHPStan\Reflection\MethodReflection; use PHPStan\TrinaryLogic; use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\ObjectType; @@ -24,13 +24,13 @@ public function __construct(ClassReflection $classReflection, string $name) $this->name = $name; } - public function isFinal(): \PHPStan\TrinaryLogic + public function isFinal(): TrinaryLogic { // TODO: Implement isFinal() method. return TrinaryLogic::createNo(); } - public function isInternal(): \PHPStan\TrinaryLogic + public function isInternal(): TrinaryLogic { // TODO: Implement isInternal() method. return TrinaryLogic::createNo(); @@ -42,13 +42,13 @@ public function getDocComment(): ?string return null; } - public function isDeprecated(): \PHPStan\TrinaryLogic + public function isDeprecated(): TrinaryLogic { // TODO: Implement isDeprecated() method. return TrinaryLogic::createNo(); } - public function hasSideEffects(): \PHPStan\TrinaryLogic + public function hasSideEffects(): TrinaryLogic { // TODO: Implement hasSideEffects() method. return TrinaryLogic::createMaybe(); @@ -106,7 +106,7 @@ public function isVariadic(): bool */ public function getVariants(): array { - if (preg_match("/find_(all_)?by_/", $this->name)) { + if (preg_match('/find_(all_)?by_/', $this->name)) { return [ new FunctionVariant( TemplateTypeMap::createEmpty(), @@ -116,7 +116,7 @@ public function getVariants(): array new ObjectType($this->classReflection->getDisplayName()) ) ]; - } elseif (preg_match("/_set$/", $this->name)) { + } elseif (preg_match('/_set$/', $this->name)) { return [ new FunctionVariant( TemplateTypeMap::createEmpty(), @@ -126,7 +126,7 @@ public function getVariants(): array new ObjectType($this->classReflection->getDisplayName()) ) ]; - } elseif (preg_match("/_refresh/", $this->name)) { + } elseif (preg_match('/_refresh/', $this->name)) { return [ new FunctionVariant( TemplateTypeMap::createEmpty(), @@ -136,7 +136,7 @@ public function getVariants(): array new VoidType() ) ]; - } elseif (preg_match("/_dirty/", $this->name)) { + } elseif (preg_match('/_dirty/', $this->name)) { return [ new FunctionVariant( TemplateTypeMap::createEmpty(), From f5593e703a40d37780a817d2813c25e53a63f003 Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Sun, 3 Sep 2023 08:43:09 -0700 Subject: [PATCH 3/8] dynamic number of arguments for find_by --- lib/Model.php | 4 ++-- lib/PhpStan/ModelStaticMethodReflection.php | 13 ++++++++++--- lib/SQLBuilder.php | 8 +++++++- test/phpstan/DynamicFindBy.php | 11 ++++++++++- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/lib/Model.php b/lib/Model.php index 36a64ce9..0ad1dcfb 100644 --- a/lib/Model.php +++ b/lib/Model.php @@ -1515,7 +1515,7 @@ public static function __callStatic(string $method, mixed $args): mixed $method = 'find_by' . substr($method, 17); } - if ('find_by' === substr($method, 0, 7)) { + if (str_starts_with($method, 'find_by')) { $attributes = substr($method, 8); $options['conditions'] = SQLBuilder::create_conditions_from_underscored_string(static::connection(), $attributes, $args, static::$alias_attribute); @@ -1524,7 +1524,7 @@ public static function __callStatic(string $method, mixed $args): mixed } return $ret; - } elseif ('find_all_by' === substr($method, 0, 11)) { + } elseif (str_starts_with($method, 'find_all_by')) { $options['conditions'] = SQLBuilder::create_conditions_from_underscored_string(static::connection(), substr($method, 12), $args, static::$alias_attribute); return static::find('all', $options); diff --git a/lib/PhpStan/ModelStaticMethodReflection.php b/lib/PhpStan/ModelStaticMethodReflection.php index 617c5bd7..8a85f9b9 100644 --- a/lib/PhpStan/ModelStaticMethodReflection.php +++ b/lib/PhpStan/ModelStaticMethodReflection.php @@ -4,13 +4,16 @@ namespace ActiveRecord\PhpStan; +use ActiveRecord\SQLBuilder; use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\FunctionVariant; use PHPStan\Reflection\MethodReflection; use PHPStan\TrinaryLogic; use PHPStan\Type\Generic\TemplateTypeMap; +use PHPStan\Type\NullType; use PHPStan\Type\ObjectType; +use PHPStan\Type\UnionType; use PHPStan\Type\VoidType; class ModelStaticMethodReflection implements MethodReflection @@ -106,14 +109,18 @@ public function isVariadic(): bool */ public function getVariants(): array { - if (preg_match('/find_(all_)?by_/', $this->name)) { + if (str_starts_with($this->name, "find_by")) { + $parts = SQLBuilder::underscored_string_to_parts(substr($this->name, 8), 0); return [ new FunctionVariant( TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), - [new ModelParameterReflection()], + array_fill(0, count($parts), new ModelParameterReflection()), false, - new ObjectType($this->classReflection->getDisplayName()) + new UnionType([ + new ObjectType($this->classReflection->getDisplayName()), + new NullType() + ]) ) ]; } elseif (preg_match('/_set$/', $this->name)) { diff --git a/lib/SQLBuilder.php b/lib/SQLBuilder.php index 61759a90..ee8810ec 100644 --- a/lib/SQLBuilder.php +++ b/lib/SQLBuilder.php @@ -251,6 +251,10 @@ public static function reverse_order(string $order = ''): string return join(',', $parts); } + public static function underscored_string_to_parts(string $string, int $flags=PREG_SPLIT_DELIM_CAPTURE): array { + return preg_split('/(_and_|_or_)/i', $string, -1, $flags); + } + /** * Converts a string like "id_and_name_or_z" into a conditions value like array("id=? AND name=? OR z=?", values, ...). * @@ -267,10 +271,12 @@ public static function create_conditions_from_underscored_string(Connection $con return null; } - $parts = preg_split('/(_and_|_or_)/i', $name, -1, PREG_SPLIT_DELIM_CAPTURE); + $num_values = count((array) $values); $conditions = ['']; + $parts = static::underscored_string_to_parts($name); + for ($i = 0, $j = 0, $n = count($parts); $i < $n; $i += 2, ++$j) { if ($i >= 2) { $res = preg_replace(['/_and_/i', '/_or_/i'], [' AND ', ' OR '], $parts[$i - 1]); diff --git a/test/phpstan/DynamicFindBy.php b/test/phpstan/DynamicFindBy.php index 5713cc13..eb23c89c 100644 --- a/test/phpstan/DynamicFindBy.php +++ b/test/phpstan/DynamicFindBy.php @@ -8,7 +8,16 @@ * see lib/PhpStan/FindDynamicByMethodReturnTypeReflection.php */ +use ActiveRecord\Exception\ConnectionException; +use ActiveRecord\Exception\RecordNotFound; use test\models\Book; +use function PHPStan\dumpType; -$book = Book::find_by_name("Foo"); +$book = Book::find_by_name("Walden"); assert($book instanceof Book); + +$book = Book::find_by_name_and_publisher("Walden", "Random House"); +assert(is_null($book)); + + + From d73fed670987ede5ff75c6b32355ed502b889d3c Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Sun, 3 Sep 2023 08:44:34 -0700 Subject: [PATCH 4/8] stanning --- lib/SQLBuilder.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/SQLBuilder.php b/lib/SQLBuilder.php index ee8810ec..95ae8a42 100644 --- a/lib/SQLBuilder.php +++ b/lib/SQLBuilder.php @@ -251,6 +251,9 @@ public static function reverse_order(string $order = ''): string return join(',', $parts); } + /** + * @return array + */ public static function underscored_string_to_parts(string $string, int $flags=PREG_SPLIT_DELIM_CAPTURE): array { return preg_split('/(_and_|_or_)/i', $string, -1, $flags); } From 3ef50edfcbb972000dca9f9bb836964de46ce2d5 Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Sun, 3 Sep 2023 08:54:53 -0700 Subject: [PATCH 5/8] fixes --- lib/PhpStan/ModelStaticMethodReflection.php | 20 ++++++++++++++++++- ...{DynamicFIndAll.php => DynamicFindAll.php} | 4 ++++ 2 files changed, 23 insertions(+), 1 deletion(-) rename test/phpstan/{DynamicFIndAll.php => DynamicFindAll.php} (77%) diff --git a/lib/PhpStan/ModelStaticMethodReflection.php b/lib/PhpStan/ModelStaticMethodReflection.php index 8a85f9b9..02f0ebd1 100644 --- a/lib/PhpStan/ModelStaticMethodReflection.php +++ b/lib/PhpStan/ModelStaticMethodReflection.php @@ -10,7 +10,9 @@ use PHPStan\Reflection\FunctionVariant; use PHPStan\Reflection\MethodReflection; use PHPStan\TrinaryLogic; +use PHPStan\Type\ArrayType; use PHPStan\Type\Generic\TemplateTypeMap; +use PHPStan\Type\IntegerType; use PHPStan\Type\NullType; use PHPStan\Type\ObjectType; use PHPStan\Type\UnionType; @@ -123,7 +125,23 @@ public function getVariants(): array ]) ) ]; - } elseif (preg_match('/_set$/', $this->name)) { + } + elseif (str_starts_with($this->name, "find_all")) { + $parts = SQLBuilder::underscored_string_to_parts(substr($this->name, 8), 0); + return [ + new FunctionVariant( + TemplateTypeMap::createEmpty(), + TemplateTypeMap::createEmpty(), + array_fill(0, count($parts), new ModelParameterReflection()), + false, + new ArrayType( + new IntegerType(), + new ObjectType($this->classReflection->getDisplayName()), + ) + ) + ]; + } + elseif (preg_match('/_set$/', $this->name)) { return [ new FunctionVariant( TemplateTypeMap::createEmpty(), diff --git a/test/phpstan/DynamicFIndAll.php b/test/phpstan/DynamicFindAll.php similarity index 77% rename from test/phpstan/DynamicFIndAll.php rename to test/phpstan/DynamicFindAll.php index afa13abd..f61e5fa2 100644 --- a/test/phpstan/DynamicFIndAll.php +++ b/test/phpstan/DynamicFindAll.php @@ -9,6 +9,10 @@ */ use test\models\Book; +use function PHPStan\dumpType; $book = Book::find_all_by_name("Foo"); assert(is_array($book)); + +$book = Book::find_all_by_name_and_publisher("Foo", "Penguin"); +assert(is_array($book)); From 579e7efc8b3ad6b04a97208b49d403f5e0802cbb Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Sun, 3 Sep 2023 08:58:25 -0700 Subject: [PATCH 6/8] linting --- lib/PhpStan/ModelStaticMethodReflection.php | 10 +++++----- lib/SQLBuilder.php | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/PhpStan/ModelStaticMethodReflection.php b/lib/PhpStan/ModelStaticMethodReflection.php index 02f0ebd1..a42b5e33 100644 --- a/lib/PhpStan/ModelStaticMethodReflection.php +++ b/lib/PhpStan/ModelStaticMethodReflection.php @@ -111,8 +111,9 @@ public function isVariadic(): bool */ public function getVariants(): array { - if (str_starts_with($this->name, "find_by")) { + if (str_starts_with($this->name, 'find_by')) { $parts = SQLBuilder::underscored_string_to_parts(substr($this->name, 8), 0); + return [ new FunctionVariant( TemplateTypeMap::createEmpty(), @@ -125,9 +126,9 @@ public function getVariants(): array ]) ) ]; - } - elseif (str_starts_with($this->name, "find_all")) { + } elseif (str_starts_with($this->name, 'find_all')) { $parts = SQLBuilder::underscored_string_to_parts(substr($this->name, 8), 0); + return [ new FunctionVariant( TemplateTypeMap::createEmpty(), @@ -140,8 +141,7 @@ public function getVariants(): array ) ) ]; - } - elseif (preg_match('/_set$/', $this->name)) { + } elseif (preg_match('/_set$/', $this->name)) { return [ new FunctionVariant( TemplateTypeMap::createEmpty(), diff --git a/lib/SQLBuilder.php b/lib/SQLBuilder.php index 95ae8a42..be5b58fb 100644 --- a/lib/SQLBuilder.php +++ b/lib/SQLBuilder.php @@ -254,7 +254,8 @@ public static function reverse_order(string $order = ''): string /** * @return array */ - public static function underscored_string_to_parts(string $string, int $flags=PREG_SPLIT_DELIM_CAPTURE): array { + public static function underscored_string_to_parts(string $string, int $flags=PREG_SPLIT_DELIM_CAPTURE): array + { return preg_split('/(_and_|_or_)/i', $string, -1, $flags); } @@ -274,7 +275,6 @@ public static function create_conditions_from_underscored_string(Connection $con return null; } - $num_values = count((array) $values); $conditions = ['']; From df45d53604efef37a0d0bc3be2db0cccebd80413 Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Sun, 3 Sep 2023 09:07:50 -0700 Subject: [PATCH 7/8] linting --- test/phpstan/DynamicFInd.php | 2 -- test/phpstan/DynamicFindAll.php | 5 ++--- test/phpstan/DynamicFindBy.php | 10 ++-------- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/test/phpstan/DynamicFInd.php b/test/phpstan/DynamicFInd.php index bd539496..2e88ded2 100644 --- a/test/phpstan/DynamicFInd.php +++ b/test/phpstan/DynamicFInd.php @@ -45,5 +45,3 @@ $books = Book::find(['conditions'=> ['name' => 'Kurt']]); assert(0==count($books)); - - diff --git a/test/phpstan/DynamicFindAll.php b/test/phpstan/DynamicFindAll.php index f61e5fa2..808ce4fd 100644 --- a/test/phpstan/DynamicFindAll.php +++ b/test/phpstan/DynamicFindAll.php @@ -9,10 +9,9 @@ */ use test\models\Book; -use function PHPStan\dumpType; -$book = Book::find_all_by_name("Foo"); +$book = Book::find_all_by_name('Foo'); assert(is_array($book)); -$book = Book::find_all_by_name_and_publisher("Foo", "Penguin"); +$book = Book::find_all_by_name_and_publisher('Foo', 'Penguin'); assert(is_array($book)); diff --git a/test/phpstan/DynamicFindBy.php b/test/phpstan/DynamicFindBy.php index eb23c89c..4621b7e5 100644 --- a/test/phpstan/DynamicFindBy.php +++ b/test/phpstan/DynamicFindBy.php @@ -8,16 +8,10 @@ * see lib/PhpStan/FindDynamicByMethodReturnTypeReflection.php */ -use ActiveRecord\Exception\ConnectionException; -use ActiveRecord\Exception\RecordNotFound; use test\models\Book; -use function PHPStan\dumpType; -$book = Book::find_by_name("Walden"); +$book = Book::find_by_name('Walden'); assert($book instanceof Book); -$book = Book::find_by_name_and_publisher("Walden", "Random House"); +$book = Book::find_by_name_and_publisher('Walden', 'Random House'); assert(is_null($book)); - - - From 5ef3b14361716041c96f1569c5a3ce9372bd1121 Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Sun, 3 Sep 2023 09:12:48 -0700 Subject: [PATCH 8/8] fix possible bug --- lib/PhpStan/ModelStaticMethodReflection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/PhpStan/ModelStaticMethodReflection.php b/lib/PhpStan/ModelStaticMethodReflection.php index a42b5e33..3c60985f 100644 --- a/lib/PhpStan/ModelStaticMethodReflection.php +++ b/lib/PhpStan/ModelStaticMethodReflection.php @@ -127,7 +127,7 @@ public function getVariants(): array ) ]; } elseif (str_starts_with($this->name, 'find_all')) { - $parts = SQLBuilder::underscored_string_to_parts(substr($this->name, 8), 0); + $parts = SQLBuilder::underscored_string_to_parts(substr($this->name, 9), 0); return [ new FunctionVariant(