Skip to content

Commit

Permalink
Add support for Symfony Form inherit_data (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bartheyrman22 authored Sep 20, 2024
1 parent 87426de commit 7aaaf5c
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 53 deletions.
17 changes: 15 additions & 2 deletions Filter/FilterBuilderUpdater.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,11 @@ protected function addFilters(FormInterface $form, QueryInterface $filterQuery,
} elseif ($formType instanceof EmbeddedFilterTypeInterface) {
$this->addFilters($child, $filterQuery, $child->getConfig()->getAttribute('filter_field_name') ?? ($alias . '.' . $child->getName()));

// default case
// inherit_data set to true
} elseif ($child->getConfig()->getInheritData()) {
$this->addFilters($child, $filterQuery, $alias);

// default case
} else {
$condition = $this->getFilterCondition($child, $formType, $filterQuery, $alias);

Expand Down Expand Up @@ -194,7 +198,11 @@ protected function getFilterCondition(FormInterface $form, AbstractType $formTyp
$parentForm = $form;
do {
$parentForm = $parentForm->getParent();
if (!is_numeric($parentForm->getName()) && $parentForm->getConfig()->getMapped()) { // skip collection numeric index and not mapped fields
if (
!is_numeric($parentForm->getName())
&& $parentForm->getConfig()->getMapped()
&& !$parentForm->getConfig()->getInheritData()
) { // skip collection numeric index and not mapped fields and inherited data
$completeName = $parentForm->getName() . '.' . $completeName;
}
} while (!$parentForm->isRoot());
Expand Down Expand Up @@ -295,6 +303,11 @@ protected function buildDefaultConditionNode(Form $form, ConditionNodeInterface
$root->andX(),
$name
);
} elseif ($child->getConfig()->getInheritData()) {
$this->buildDefaultConditionNode(
$child,
$root
);
} else {
$root->field($name);
}
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ Please consider [opening a question on StackOverflow](http://stackoverflow.com/q

Github Issues are dedicated to bug reports and feature requests.

Symfony 2.8 and 3.4
-------------------
For compatibility with Symfony 2.8 and 3.4
------------------------------------------

Please use last tag v5.*

Expand Down
32 changes: 29 additions & 3 deletions Tests/Filter/Doctrine/ORMQueryBuilderUpdaterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

use Spiriit\Bundle\FormFilterBundle\Filter\Condition\ConditionBuilderInterface;
use Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item;
use Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Options;
use Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Filter\InheritDataFilterType;
use Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Filter\ItemEmbeddedOptionsFilterType;

/**
Expand Down Expand Up @@ -177,10 +179,34 @@ public function testWithDataClass()
$this->assertEquals(['p_opt_rank' => 6], $this->getQueryBuilderParameters($doctrineQueryBuilder));
}

protected function createDoctrineQueryBuilder()
public function testWithInheritDataFormOption()
{
// doctrine query builder without any joins + a data_class
$form = $this->formFactory->create(InheritDataFilterType::class, null, ['data_class' => Options::class]);
$filterQueryBuilder = $this->initQueryBuilderUpdater();

$doctrineQueryBuilder = $this->createDoctrineQueryBuilder(Options::class, 'o');

$form->submit(['option' => ['label' => 'dude', 'rank' => 1], 'item' => ['name' => 'blabla', 'position' => 2, 'enabled' => 'y']]);

$expectedDql = 'SELECT o FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Options o LEFT JOIN o.item item';
$expectedDql .= ' WHERE o.label LIKE \'dude\' AND o.rank = :p_o_rank AND (item.name LIKE \'blabla\' AND item.position > :p_item_position AND item.enabled = :p_item_enabled)';
$filterQueryBuilder->addFilterConditions($form, $doctrineQueryBuilder);

$this->assertEquals($expectedDql, $doctrineQueryBuilder->getDql());
$this->assertEquals([
'p_o_rank' => 1.0,
'p_item_position' => 2.0,
'p_item_enabled' => true,
], $this->getQueryBuilderParameters($doctrineQueryBuilder));
}

protected function createDoctrineQueryBuilder(
string $entityClassName = Item::class,
string $alias = 'i'
) {
return $this->em
->getRepository(Item::class)
->createQueryBuilder('i');
->getRepository($entityClassName)
->createQueryBuilder($alias);
}
}
12 changes: 6 additions & 6 deletions Tests/Fixtures/Entity/Item.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ class Item
protected int $id;

#[ORM\Column()]
protected string $name;
protected string $name = '';

#[ORM\Column(type: 'integer')]
protected int $position;
protected ?int $position = null;

#[ORM\Column(type: 'boolean')]
protected bool $enabled;
protected bool $enabled = false;

#[ORM\Column(type: 'datetime', nullable: true)]
protected ?\DateTime $createdAt = null;
Expand All @@ -41,7 +41,7 @@ class Item
protected ?\DateTime $updatedAt = null;

#[ORM\OneToMany(targetEntity: Options::class, mappedBy: 'item')]
private array $options;
private array $options = [];

public function getId(): int
{
Expand All @@ -58,12 +58,12 @@ public function setName(string $name): void
$this->name = $name;
}

public function getPosition(): int
public function getPosition(): ?int
{
return $this->position;
}

public function setPosition(int $position): void
public function setPosition(?int $position): void
{
$this->position = $position;
}
Expand Down
24 changes: 17 additions & 7 deletions Tests/Fixtures/Entity/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,37 +25,47 @@ class Options
protected int $id;

#[ORM\Column()]
protected string $label;
protected ?string $label = null;

#[ORM\Column(type: 'integer')]
protected int $rank;
protected ?int $rank = null;

#[ORM\ManyToOne(targetEntity: Item::class, inversedBy: 'options')]
#[ORM\JoinColumn()]
private Item $item;
private ?Item $item = null;

public function getId(): int
{
return $this->id;
}

public function getLabel(): string
public function getLabel(): ?string
{
return $this->label;
}

public function setLabel(string $label): void
public function setLabel(?string $label): void
{
$this->label = $label;
}

public function getRank(): int
public function getRank(): ?int
{
return $this->rank;
}

public function setRank(int $rank): void
public function setRank(?int $rank): void
{
$this->rank = $rank;
}

public function getItem(): ?Item
{
return $this->item;
}

public function setItem(?Item $item): void
{
$this->item = $item;
}
}
55 changes: 55 additions & 0 deletions Tests/Fixtures/Filter/InheritDataFilterType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

/*
* This file is part of the composer-write-changelogs project.
*
* (c) Dev Spiriit <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Filter;

use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder;
use Spiriit\Bundle\FormFilterBundle\Filter\FilterBuilderExecuterInterface;
use Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

/**
* Form filter for tests.
*
* @author Bart Heyrman <[email protected]>
*/
class InheritDataFilterType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('item', ItemFilterType::class, [
'add_shared' => function (FilterBuilderExecuterInterface $qbe) {
$closure = function (QueryBuilder $filterBuilder, $alias, $joinAlias, Expr $expr) {
$filterBuilder->leftJoin($alias . '.item', $joinAlias);
};


$qbe->addOnce($qbe->getAlias().'.item', 'item', $closure);
},
'data_class' => Item::class,
])
->add('option', OptionFilterType::class, [
'inherit_data' => true
])
;
}

/**
* @return string
*/
public function getBlockPrefix(): string
{
return 'inherit_filter';
}
}
6 changes: 6 additions & 0 deletions Tests/Fixtures/Filter/ItemFilterType.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Spiriit\Bundle\FormFilterBundle\Filter\Form\Type\DateFilterType;
use Spiriit\Bundle\FormFilterBundle\Filter\Form\Type\DateTimeFilterType;
use Spiriit\Bundle\FormFilterBundle\Filter\Form\Type\NumberFilterType;
use Spiriit\Bundle\FormFilterBundle\Filter\Form\Type\SharedableFilterType;
use Spiriit\Bundle\FormFilterBundle\Filter\Form\Type\TextFilterType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
Expand Down Expand Up @@ -49,4 +50,9 @@ public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults(['with_selector' => false, 'checkbox' => false, 'datetime' => false, 'disabled_name' => false]);
}

public function getParent(): string
{
return SharedableFilterType::class; // this allows us to use the "add_shared" option
}
}
66 changes: 33 additions & 33 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
backupGlobals="false"
backupStaticAttributes="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
bootstrap="vendor/autoload.php"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
>

<phpunit backupGlobals="false"
backupStaticAttributes="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
bootstrap="vendor/autoload.php"
>
<testsuites>
<testsuite name="SpiriitFormFilterBundle Test Suite">
<directory>./Tests/</directory>
</testsuite>
</testsuites>
<coverage>
<include>
<directory>./</directory>
</include>
<exclude>
<directory>./Resources</directory>
<directory>./Tests</directory>
<directory>./vendor</directory>
</exclude>
</coverage>

<testsuites>
<testsuite name="SpiriitFormFilterBundle Test Suite">
<directory>./Tests/</directory>
</testsuite>
</testsuites>
<filter>

<whitelist>
<directory>./</directory>
<exclude>
<directory>./Resources</directory>
<directory>./Tests</directory>
<directory>./vendor</directory>
</exclude>
</whitelist>
</filter>

<php>
<env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled"></env>
</php>

<listeners>
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener"/>
</listeners>
<php>
<env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled"/>
</php>
<listeners>
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener"/>
</listeners>
</phpunit>

0 comments on commit 7aaaf5c

Please sign in to comment.