Skip to content

Commit

Permalink
Add tests to ModelManager and DateFilter
Browse files Browse the repository at this point in the history
  • Loading branch information
franmomu committed Jul 25, 2020
1 parent c43f1e5 commit 0c3c71b
Show file tree
Hide file tree
Showing 12 changed files with 654 additions and 20 deletions.
41 changes: 34 additions & 7 deletions src/Filter/AbstractDateFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,43 +50,47 @@ public function filter(ProxyQueryInterface $queryBuilder, $alias, $field, $data)
$data['type'] = !isset($data['type']) || !is_numeric($data['type']) ? DateOperatorType::TYPE_EQUAL : $data['type'];

// Some types do not require a value to be set (NULL, NOT NULL).
if (!$this->typeRequiresValue($data['type']) && !$data['value']) {
if (!isset($data['value']) && $this->typeDoesRequireValue($data['type'])) {
return;
}

switch ($data['type']) {
case DateOperatorType::TYPE_EQUAL:
$this->active = true;

$this->applyTypeIsEqual($queryBuilder, $field, $data);

return;

case DateOperatorType::TYPE_GREATER_THAN:
if (!\array_key_exists('value', $data) || !$data['value']) {
return;
}
$this->active = true;

$this->applyTypeIsGreaterThan($queryBuilder, $field, $data);

return;

case DateOperatorType::TYPE_LESS_EQUAL:
if (!\array_key_exists('value', $data) || !$data['value']) {
return;
}
$this->active = true;

$this->applyTypeIsLessEqual($queryBuilder, $field, $data);

return;

case DateOperatorType::TYPE_NULL:
case DateOperatorType::TYPE_NOT_NULL:
$this->active = true;

$this->applyType($queryBuilder, $this->getOperator($data['type']), $field, null);

return;

case DateOperatorType::TYPE_GREATER_EQUAL:
case DateOperatorType::TYPE_LESS_THAN:
$this->active = true;

$this->applyType($queryBuilder, $this->getOperator($data['type']), $field, $data['value']);

return;
}
}

Expand Down Expand Up @@ -120,6 +124,12 @@ public function getRenderSettings()
]];
}

abstract protected function applyTypeIsLessEqual(ProxyQueryInterface $queryBuilder, string $field, array $data);

abstract protected function applyTypeIsGreaterThan(ProxyQueryInterface $queryBuilder, string $field, array $data);

abstract protected function applyTypeIsEqual(ProxyQueryInterface $queryBuilder, string $field, array $data);

/**
* @param string $operation
* @param string $field
Expand All @@ -132,14 +142,23 @@ protected function applyType(ProxyQueryInterface $queryBuilder, $operation, $fie
}

/**
* NEXT_MAJOR: Remove this method.
*
* Returns if the filter type requires a value to be set.
*
* @param int $type
*
* @deprecated since sonata-project/doctrine-mongodb-admin-bundle 3.x, to be removed in 4.0.'.
*
* @return bool
*/
protected function typeRequiresValue($type)
{
@trigger_error(sprintf(
'"%s()" is deprecated since sonata-project/doctrine-mongodb-admin-bundle 3.x and will be removed in version 4.0.',
__METHOD__
), E_USER_DEPRECATED);

return \in_array($type, [
DateOperatorType::TYPE_NULL,
DateOperatorType::TYPE_NOT_NULL,
Expand Down Expand Up @@ -167,4 +186,12 @@ protected function getOperator($type)

return $choices[(int) $type];
}

private function typeDoesRequireValue(int $type): bool
{
return !\in_array($type, [
DateOperatorType::TYPE_NULL,
DateOperatorType::TYPE_NOT_NULL,
], true);
}
}
6 changes: 6 additions & 0 deletions src/Filter/DateFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@
namespace Sonata\DoctrineMongoDBAdminBundle\Filter;

use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
use Symfony\Component\Form\Extension\Core\Type\DateType;

class DateFilter extends AbstractDateFilter
{
public function getFieldType(): string
{
return $this->getOption('field_type', DateType::class);
}

/**
* @param string $field
* @param array $data
Expand Down
6 changes: 6 additions & 0 deletions src/Filter/DateTimeFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace Sonata\DoctrineMongoDBAdminBundle\Filter;

use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;

class DateTimeFilter extends AbstractDateFilter
{
Expand All @@ -24,6 +25,11 @@ class DateTimeFilter extends AbstractDateFilter
*/
protected $time = true;

public function getFieldType(): string
{
return $this->getOption('field_type', DateTimeType::class);
}

/**
* @param string $field
* @param array $data
Expand Down
22 changes: 18 additions & 4 deletions src/Model/ModelManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
use Sonata\DoctrineMongoDBAdminBundle\Datagrid\ProxyQuery;
use Sonata\Exporter\Source\DoctrineODMQuerySourceIterator;
use Symfony\Bridge\Doctrine\ManagerRegistry;
use Symfony\Component\Form\Exception\PropertyAccessDeniedException;

class ModelManager implements ModelManagerInterface
{
Expand Down Expand Up @@ -364,6 +363,21 @@ public function getExportFields($class)
*/
public function getModelInstance($class)
{
if (!class_exists($class)) {
throw new \InvalidArgumentException(sprintf('Class "%s" not found', $class));
}

$r = new \ReflectionClass($class);
if ($r->isAbstract()) {
throw new \InvalidArgumentException(sprintf('Cannot initialize abstract class: %s', $class));
}

$constructor = $r->getConstructor();

if (null !== $constructor && (!$constructor->isPublic() || $constructor->getNumberOfRequiredParameters() > 0)) {
return $r->newInstanceWithoutConstructor();
}

return new $class();
}

Expand Down Expand Up @@ -455,7 +469,7 @@ public function modelReverseTransform($class, array $array = [])

if ($reflClass->hasMethod($setter)) {
if (!$reflClass->getMethod($setter)->isPublic()) {
throw new PropertyAccessDeniedException(sprintf('Method "%s()" is not public in class "%s"', $setter, $reflClass->getName()));
throw new \BadMethodCallException(sprintf('Method "%s()" is not public in class "%s"', $setter, $reflClass->getName()));
}

$instance->$setter($value);
Expand All @@ -464,7 +478,7 @@ public function modelReverseTransform($class, array $array = [])
$instance->$property = $value;
} elseif ($reflClass->hasProperty($property)) {
if (!$reflClass->getProperty($property)->isPublic()) {
throw new PropertyAccessDeniedException(sprintf('Property "%s" is not public in class "%s". Maybe you should create the method "set%s()"?', $property, $reflClass->getName(), ucfirst($property)));
throw new \BadMethodCallException(sprintf('Property "%s" is not public in class "%s". Maybe you should create the method "set%s()"?', $property, $reflClass->getName(), ucfirst($property)));
}

$instance->$property = $value;
Expand Down Expand Up @@ -525,7 +539,7 @@ public function collectionRemoveElement(&$collection, &$element)
*/
protected function camelize($property)
{
return preg_replace(['/(^|_)+(.)/e', '/\.(.)/e'], ["strtoupper('\\2')", "'_'.strtoupper('\\1')"], $property);
return str_replace(' ', '', ucwords(str_replace('_', ' ', $property)));
}

private function isFieldAlreadySorted(FieldDescriptionInterface $fieldDescription, DatagridInterface $datagrid): bool
Expand Down
81 changes: 81 additions & 0 deletions tests/Filter/DateTimeFilterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\DoctrineMongoDBAdminBundle\Tests\Filter;

use Sonata\AdminBundle\Form\Type\Filter\DateType;
use Sonata\DoctrineMongoDBAdminBundle\Datagrid\ProxyQuery;
use Sonata\DoctrineMongoDBAdminBundle\Filter\DateTimeFilter;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;

final class DateTimeFilterTest extends FilterWithQueryBuilderTest
{
public function testEmpty(): void
{
$filter = new DateTimeFilter();
$filter->initialize('field_name', ['field_options' => ['class' => 'FooBar']]);

$builder = new ProxyQuery($this->getQueryBuilder());

$builder->getQueryBuilder()
->expects($this->never())
->method('field')
;

$filter->filter($builder, 'alias', 'field', null);
$filter->filter($builder, 'alias', 'field', '');
$filter->filter($builder, 'alias', 'field', []);

$this->assertFalse($filter->isActive());
}

public function testGetType(): void
{
$this->assertSame(DateTimeType::class, (new DateTimeFilter())->getFieldType());
}

/**
* @dataProvider getExamples
*/
public function testFilter(array $data, string $method): void
{
$filter = new DateTimeFilter();
$filter->initialize('field_name', ['field_options' => ['class' => 'FooBar']]);

$builder = new ProxyQuery($this->getQueryBuilder());

$builder->getQueryBuilder()
->expects($this->once())
->method($method)
->with($data['value'] ?? null)
;

$filter->filter($builder, 'alias', 'field', $data);

$this->assertTrue($filter->isActive());
}

public function getExamples(): array
{
return [
[['type' => DateType::TYPE_EQUAL, 'value' => new \DateTime('now')], 'range'],
[['type' => DateType::TYPE_GREATER_EQUAL, 'value' => new \DateTime('now')], 'gte'],
[['type' => DateType::TYPE_GREATER_THAN, 'value' => new \DateTime('now')], 'gt'],
[['type' => DateType::TYPE_LESS_EQUAL, 'value' => new \DateTime('now')], 'lte'],
[['type' => DateType::TYPE_LESS_THAN, 'value' => new \DateTime('now')], 'lt'],
[['type' => DateType::TYPE_NULL], 'equals'],
[['type' => DateType::TYPE_NOT_NULL], 'notEqual'],
[['value' => new \DateTime('now')], 'range'],
];
}
}
18 changes: 18 additions & 0 deletions tests/Fixtures/Document/AbstractDocument.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\DoctrineMongoDBAdminBundle\Tests\Fixtures\Document;

abstract class AbstractDocument
{
}
31 changes: 31 additions & 0 deletions tests/Fixtures/Document/AssociatedDocument.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\DoctrineMongoDBAdminBundle\Tests\Fixtures\Document;

class AssociatedDocument
{
private $plainField;
private $embeddedDocument;

public function __construct(int $plainField, EmbeddedDocument $embeddedDocument)
{
$this->plainField = $plainField;
$this->embeddedDocument = $embeddedDocument;
}

public function getPlainField(): int
{
return $this->plainField;
}
}
32 changes: 32 additions & 0 deletions tests/Fixtures/Document/ContainerDocument.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\DoctrineMongoDBAdminBundle\Tests\Fixtures\Document;

class ContainerDocument
{
private $plainField;
private $associatedDocument;
private $embeddedDocument;

public function __construct(AssociatedDocument $associatedDocument, EmbeddedDocument $embeddedDocument)
{
$this->associatedDocument = $associatedDocument;
$this->embeddedDocument = $embeddedDocument;
}

public function getAssociatedDocument(): AssociatedDocument
{
return $this->associatedDocument;
}
}
22 changes: 22 additions & 0 deletions tests/Fixtures/Document/EmbeddedDocument.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\DoctrineMongoDBAdminBundle\Tests\Fixtures\Document;

class EmbeddedDocument
{
/**
* @var bool
*/
protected $plainField;
}

0 comments on commit 0c3c71b

Please sign in to comment.