diff --git a/src/bitExpert/PHPStan/Sylius/Collector/Grid/CollectFilterForGridClass.php b/src/bitExpert/PHPStan/Sylius/Collector/Grid/CollectFilterForGridClass.php index 1b87810..0b936ee 100644 --- a/src/bitExpert/PHPStan/Sylius/Collector/Grid/CollectFilterForGridClass.php +++ b/src/bitExpert/PHPStan/Sylius/Collector/Grid/CollectFilterForGridClass.php @@ -14,15 +14,17 @@ use PhpParser\Node; use PhpParser\Node\Arg; +use PhpParser\Node\Expr\Array_; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Identifier; +use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Scalar\String_; use PHPStan\Analyser\Scope; use PHPStan\Collectors\Collector; use PHPStan\Type\ObjectType; /** - * @implements Collector + * @implements Collector */ class CollectFilterForGridClass extends AbstractGridClassCollector implements Collector { @@ -58,11 +60,61 @@ public function processNode(Node $node, Scope $scope): ?array } $classType = new ObjectType($classReflection->getName()); - /** @var Arg $arg */ - $arg = $node->args[0]; - /** @var String_ $filterFieldName */ - $filterFieldName = $arg->value; + // first check if the various filter implementations have defined custom fields to filter on + $filterFields = []; + /** @var FullyQualified $nodeClass */ + $nodeClass = $node->class; + if ('Sylius\\Bundle\\GridBundle\\Builder\\Filter\\StringFilter' === $nodeClass->name) { + if (isset($node->args[1]) && $node->args[1] instanceof Arg) { + /** @var Array_ $array */ + $array = $node->args[1]->value; + foreach ($array->items as $item) { + /** @var String_ $value */ + $value = $item->value; + $filterFields[] = $this->convertSnakeToCamelCase($value->value); + } + } + } elseif ('Sylius\\Bundle\\GridBundle\\Builder\\Filter\\SelectFilter' === $nodeClass->name) { + if (isset($node->args[3])) { + /** @var Arg $arg */ + $arg = $node->args[3]; + /** @var String_ $value */ + $value = $arg->value; + $filterFields[] = $this->convertSnakeToCamelCase($value->value); + } + } elseif ('Sylius\\Bundle\\GridBundle\\Builder\\Filter\\ExistsFilter' === $nodeClass->name) { + if (isset($node->args[1])) { + /** @var Arg $arg */ + $arg = $node->args[1]; + /** @var String_ $value */ + $value = $arg->value; + $filterFields[] = $this->convertSnakeToCamelCase($value->value); + } + } elseif ('Sylius\\Bundle\\GridBundle\\Builder\\Filter\\EntityFilter' === $nodeClass->name) { + if (isset($node->args[3]) && $node->args[3] instanceof Arg) { + /** @var Array_ $array */ + $array = $node->args[3]->value; + foreach ($array->items as $item) { + /** @var String_ $value */ + $value = $item->value; + $filterFields[] = $this->convertSnakeToCamelCase($value->value); + } + } + } + + // if no $filterFields have been found, we fallback to the first parameter passed to the create() method + if ((0 === \count($filterFields)) && isset($node->args[0])) { + /** @var Arg $arg */ + $arg = $node->args[0]; + /** @var String_ $value */ + $value = $arg->value; + $filterFields[] = $this->convertSnakeToCamelCase($value->value); + } + + if (0 === \count($filterFields)) { + return null; + } - return [$classType->getClassName(), $this->convertSnakeToCamelCase($filterFieldName->value), $node->getLine()]; + return [$classType->getClassName(), $filterFields, $node->getLine()]; } } diff --git a/src/bitExpert/PHPStan/Sylius/Rule/Grid/GridBuilderFilterIsPartOfResourceClass.php b/src/bitExpert/PHPStan/Sylius/Rule/Grid/GridBuilderFilterIsPartOfResourceClass.php index 4f89cf1..10657f9 100644 --- a/src/bitExpert/PHPStan/Sylius/Rule/Grid/GridBuilderFilterIsPartOfResourceClass.php +++ b/src/bitExpert/PHPStan/Sylius/Rule/Grid/GridBuilderFilterIsPartOfResourceClass.php @@ -85,22 +85,24 @@ public function processNode(Node $node, Scope $scope): array $resourceClass = $this->broker->getClass($resourceClassName); foreach ($gridFilterFieldsMap[$gridClassName] as $field) { - $fieldName = $field[0]; + $fieldNames = $field[0]; $lineNo = $field[1]; - $getterMethod = 'get' . \ucfirst($fieldName); - if (!$resourceClass->hasProperty($fieldName) && !$resourceClass->hasMethod($getterMethod)) { - $message = \sprintf( - 'The filter field "%s" needs to exists as property in resource class "%s".', - $fieldName, - $resourceClassName, - ); - - $errors[] = RuleErrorBuilder::message($message) - ->identifier('sylius.grid.resourceClassMissingFilter') - ->file($gridFilesMap[$gridClassName]) - ->line($lineNo) - ->build(); + foreach ($fieldNames as $fieldName) { + $getterMethod = 'get' . \ucfirst($fieldName); + if (!$resourceClass->hasProperty($fieldName) && !$resourceClass->hasMethod($getterMethod)) { + $message = \sprintf( + 'The filter field "%s" needs to exists as property in resource class "%s".', + $fieldName, + $resourceClassName, + ); + + $errors[] = RuleErrorBuilder::message($message) + ->identifier('sylius.grid.resourceClassMissingFilter') + ->file($gridFilesMap[$gridClassName]) + ->line($lineNo) + ->build(); + } } } } diff --git a/tests/bitExpert/PHPStan/Sylius/Rule/Grid/GridBuilderFieldIsPartOfResourceClassUnitTest.php b/tests/bitExpert/PHPStan/Sylius/Rule/Grid/GridBuilderFieldIsPartOfResourceClassUnitTest.php index 0716860..53f2aee 100644 --- a/tests/bitExpert/PHPStan/Sylius/Rule/Grid/GridBuilderFieldIsPartOfResourceClassUnitTest.php +++ b/tests/bitExpert/PHPStan/Sylius/Rule/Grid/GridBuilderFieldIsPartOfResourceClassUnitTest.php @@ -42,7 +42,7 @@ public function testRule(): void [ [ 'The field "name" needs to exists as property in class "App\Entity\Supplier".', - 63, + 64, ], ], ); diff --git a/tests/bitExpert/PHPStan/Sylius/Rule/Grid/GridBuilderFilterIsPartOfResourceClassUnitTest.php b/tests/bitExpert/PHPStan/Sylius/Rule/Grid/GridBuilderFilterIsPartOfResourceClassUnitTest.php index b8840d8..9cc490c 100644 --- a/tests/bitExpert/PHPStan/Sylius/Rule/Grid/GridBuilderFilterIsPartOfResourceClassUnitTest.php +++ b/tests/bitExpert/PHPStan/Sylius/Rule/Grid/GridBuilderFilterIsPartOfResourceClassUnitTest.php @@ -42,7 +42,11 @@ public function testRule(): void [ [ 'The filter field "name" needs to exists as property in resource class "App\Entity\Supplier".', - 75, + 76, + ], + [ + 'The filter field "name" needs to exists as property in resource class "App\Entity\Supplier".', + 79, ], ], ); diff --git a/tests/bitExpert/PHPStan/Sylius/Rule/Grid/data/grid.php b/tests/bitExpert/PHPStan/Sylius/Rule/Grid/data/grid.php index 978e1d7..ffd83bd 100644 --- a/tests/bitExpert/PHPStan/Sylius/Rule/Grid/data/grid.php +++ b/tests/bitExpert/PHPStan/Sylius/Rule/Grid/data/grid.php @@ -43,6 +43,7 @@ public function getVatCode(): string use App\Entity\Supplier; use Sylius\Bundle\GridBundle\Builder\Field\StringField; use Sylius\Bundle\GridBundle\Builder\Filter\Filter; +use Sylius\Bundle\GridBundle\Builder\Filter\StringFilter; use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface; use Sylius\Bundle\GridBundle\Grid\AbstractGrid; use Sylius\Bundle\GridBundle\Grid\ResourceAwareGridInterface; @@ -72,7 +73,10 @@ public function buildGrid(GridBuilderInterface $gridBuilder): void StringField::create('.')->setLabel('app.ui.some_calculated_field'), ); $gridBuilder->addFilter( - Filter::create('name', 'string'), + StringFilter::create('name'), // Filter::create('name', 'string'), + ); + $gridBuilder->addFilter( + StringFilter::create('virtual-field', ['name']), ); }