From b2f4a01a38d598a0d581e1f6d56ac421fa1954a9 Mon Sep 17 00:00:00 2001 From: Marcel Thole Date: Wed, 10 Jul 2024 12:48:15 +0200 Subject: [PATCH] Add a Rector Rule to change the argument type from array to ArrayCollection for the setParameters ORM QueryBuilder method --- .../Fixture/array-with-parameters.php.inc | 31 ++++ .../Fixture/collection-with-key-value.php.inc | 31 ++++ .../Fixture/key-value.php.inc | 31 ++++ .../Fixture/no-change.php.inc | 17 +++ .../Fixture/numeric_list.php.inc | 31 ++++ ...tParametersArrayToCollectionRectorTest.php | 28 ++++ .../configured_rule.php | 8 ++ .../SetParametersArrayToCollectionRector.php | 133 ++++++++++++++++++ 8 files changed, 310 insertions(+) create mode 100644 rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/array-with-parameters.php.inc create mode 100644 rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/collection-with-key-value.php.inc create mode 100644 rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/key-value.php.inc create mode 100644 rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/no-change.php.inc create mode 100644 rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/numeric_list.php.inc create mode 100644 rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/SetParametersArrayToCollectionRectorTest.php create mode 100644 rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/configured_rule.php create mode 100644 rules/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector.php diff --git a/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/array-with-parameters.php.inc b/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/array-with-parameters.php.inc new file mode 100644 index 00000000..621a698e --- /dev/null +++ b/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/array-with-parameters.php.inc @@ -0,0 +1,31 @@ +setParameters([ + new \Doctrine\ORM\Query\Parameter('foo', 'bar'), + new \Doctrine\ORM\Query\Parameter('bar', 1), + new \Doctrine\ORM\Query\Parameter('baz', false), + ]); + } +} +?> +----- +setParameters(new \Doctrine\Common\Collections\ArrayCollection([new \Doctrine\ORM\Query\Parameter('foo', 'bar'), new \Doctrine\ORM\Query\Parameter('bar', 1), new \Doctrine\ORM\Query\Parameter('baz', false)])); + } +} +?> diff --git a/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/collection-with-key-value.php.inc b/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/collection-with-key-value.php.inc new file mode 100644 index 00000000..1ddb55ca --- /dev/null +++ b/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/collection-with-key-value.php.inc @@ -0,0 +1,31 @@ +setParameters(new \Doctrine\Common\Collections\ArrayCollection([ + 'foo' => 'bar', + 'bar' => 1, + 'baz' => false + ])); + } +} +?> +----- +setParameters(new \Doctrine\Common\Collections\ArrayCollection([new \Doctrine\ORM\Query\Parameter('foo', 'bar'), new \Doctrine\ORM\Query\Parameter('bar', 1), new \Doctrine\ORM\Query\Parameter('baz', false)])); + } +} +?> diff --git a/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/key-value.php.inc b/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/key-value.php.inc new file mode 100644 index 00000000..e860b531 --- /dev/null +++ b/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/key-value.php.inc @@ -0,0 +1,31 @@ +setParameters([ + 'foo' => 'bar', + 'bar' => 1, + 'baz' => false + ]); + } +} +?> +----- +setParameters(new \Doctrine\Common\Collections\ArrayCollection([new \Doctrine\ORM\Query\Parameter('foo', 'bar'), new \Doctrine\ORM\Query\Parameter('bar', 1), new \Doctrine\ORM\Query\Parameter('baz', false)])); + } +} +?> diff --git a/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/no-change.php.inc b/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/no-change.php.inc new file mode 100644 index 00000000..a53a8e41 --- /dev/null +++ b/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/no-change.php.inc @@ -0,0 +1,17 @@ +setParameters(new \Doctrine\Common\Collections\ArrayCollection([ + new \Doctrine\ORM\Query\Parameter('foo', 'bar'), + new \Doctrine\ORM\Query\Parameter('bar', 1), + new \Doctrine\ORM\Query\Parameter('baz', false), + ])); + } +} +?> diff --git a/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/numeric_list.php.inc b/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/numeric_list.php.inc new file mode 100644 index 00000000..685810e8 --- /dev/null +++ b/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/Fixture/numeric_list.php.inc @@ -0,0 +1,31 @@ +setParameters([ + 'one', + 'two', + 'three' + ]); + } +} +?> +----- +setParameters(new \Doctrine\Common\Collections\ArrayCollection([new \Doctrine\ORM\Query\Parameter(0, 'one'), new \Doctrine\ORM\Query\Parameter(1, 'two'), new \Doctrine\ORM\Query\Parameter(2, 'three')])); + } +} +?> diff --git a/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/SetParametersArrayToCollectionRectorTest.php b/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/SetParametersArrayToCollectionRectorTest.php new file mode 100644 index 00000000..b2e74e10 --- /dev/null +++ b/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/SetParametersArrayToCollectionRectorTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/configured_rule.php'; + } +} diff --git a/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/configured_rule.php b/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/configured_rule.php new file mode 100644 index 00000000..ea99f69b --- /dev/null +++ b/rules-tests/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector/configured_rule.php @@ -0,0 +1,8 @@ +withRules([\Rector\Doctrine\Orm30\Rector\MethodCall\SetParametersArrayToCollectionRector::class]); diff --git a/rules/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector.php b/rules/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector.php new file mode 100644 index 00000000..1e449b18 --- /dev/null +++ b/rules/Orm30/Rector/MethodCall/SetParametersArrayToCollectionRector.php @@ -0,0 +1,133 @@ +createQueryBuilder()->setParameters([ + 'foo' => 'bar' + ]); + CODE_SAMPLE + , + <<<'CODE_SAMPLE' + $entityManager->createQueryBuilder()->setParameters(new \Doctrine\Common\Collections\ArrayCollection([ + new \Doctrine\ORM\Query\Parameter('foo', 'bar') + ])); + CODE_SAMPLE + )] + ); + } + + /** + * @return array> + */ + public function getNodeTypes(): array + { + return [MethodCall::class]; + } + + /** + * @param MethodCall $node + */ + public function refactor(Node $node): Node|null + { + $varType = $this->nodeTypeResolver->getType($node->var); + + if (! $varType instanceof ObjectType) { + return null; + } + + if (! $varType->isInstanceOf('Doctrine\\ORM\\QueryBuilder')->yes()) { + return null; + } + + if ($node->isFirstClassCallable()) { + return null; + } + + if (! $this->isNames($node->name, ['setParameters'])) { + return null; + } + + $args = $node->getArgs(); + if (\count($args) !== 1) { + return null; + } + + $currentArg = $args[0]->value; + $isAlreadyAnArrayCollection = false; + + $currentArgType = $this->nodeTypeResolver->getType($currentArg); + if ( + $currentArgType instanceof ObjectType + && $currentArgType->isInstanceOf('Doctrine\\Common\\Collections\\ArrayCollection') + ->yes() + && $currentArg instanceof New_ + && count($currentArg->args) === 1 + && $currentArg->args[0] instanceof Arg + ) { + $currentArg = $currentArg->args[0]->value; + $isAlreadyAnArrayCollection = true; + } + + if (! $currentArg instanceof Array_) { + return null; + } + + $changedParameterType = false; + $parameters = []; + foreach ($currentArg->items as $index => $value) { + if (! $value instanceof ArrayItem) { + return null; + } + + $arrayValueType = $this->nodeTypeResolver->getType($value->value); + if (! $arrayValueType instanceof ObjectType || ! $arrayValueType->isInstanceOf( + 'Doctrine\\ORM\\Query\\Parameter' + )->yes()) { + $newParameter = new New_(new FullyQualified('Doctrine\\ORM\\Query\\Parameter')); + $newParameter->args = [new Arg($value->key ?? new LNumber($index)), new Arg($value->value)]; + $value->value = $newParameter; + $changedParameterType = true; + } + + $parameters[] = new ArrayItem($value->value); + } + + if ($changedParameterType === false && $isAlreadyAnArrayCollection) { + return null; + } + + $newCollection = new New_(new FullyQualified('Doctrine\\Common\\Collections\\ArrayCollection')); + $newCollection->args = [new Arg(new Array_($parameters))]; + + $node->args = [new Arg($newCollection)]; + return $node; + } +}