Skip to content

Instantly share code, notes, and snippets.

@blaues0cke
Created September 21, 2015 13:30
Show Gist options
  • Save blaues0cke/e45a56f32439d8882390 to your computer and use it in GitHub Desktop.
Save blaues0cke/e45a56f32439d8882390 to your computer and use it in GitHub Desktop.
DunglasApiBundle "IS NULL" custom filter
resource.empty_filter:
class: "Foo\AppBundle\Api\Filter\EmptyFilter"
arguments:
- @doctrine
- @api.iri_converter
- @property_accessor
<?php
namespace Foo\AppBundle\Api\Filter;
use Dunglas\ApiBundle\Doctrine\Orm\Filter\AbstractFilter;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\ORM\QueryBuilder;
use Dunglas\ApiBundle\Api\IriConverterInterface;
use Dunglas\ApiBundle\Api\ResourceInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
/**
* Description of EmptyFilter
*
* @author thomas.kekeisen
*/
class EmptyFilter extends AbstractFilter
{
/**
* @var IriConverterInterface
*/
private $iriConverter;
/**
* @var PropertyAccessorInterface
*/
private $propertyAccessor;
/**
* @param ManagerRegistry $managerRegistry
* @param IriConverterInterface $iriConverter
* @param PropertyAccessorInterface $propertyAccessor
* @param null|array $properties Null to allow filtering on all properties with the exact strategy or a map of property name with strategy.
*/
public function __construct(
ManagerRegistry $managerRegistry,
IriConverterInterface $iriConverter,
PropertyAccessorInterface $propertyAccessor,
array $properties = null
)
{
parent::__construct($managerRegistry, $properties);
$this->iriConverter = $iriConverter;
$this->propertyAccessor = $propertyAccessor;
}
/**
* {@inheritdoc}
*/
public function apply(ResourceInterface $resource, QueryBuilder $queryBuilder, Request $request)
{
$metadata = $this->getClassMetadata($resource);
$fieldNames = array_flip($metadata->getFieldNames());
foreach ($this->extractProperties($request) as $propertyRange => $value) {
if (strpos($propertyRange, '-empty') !== false) {
$property = str_replace('-empty', '', $propertyRange);
if (!is_string($value) || !$this->isPropertyEnabled($property)) {
continue;
}
if (isset($fieldNames[$property])) {
$where = sprintf('o.%1$s IS NULL', $property);
$queryBuilder
->andWhere($where)
;
}
}
}
}
/**
* Gets the ID from an URI or a raw ID.
*
* @param string $value
*
* @return string
*/
private function getFilterValueFromUrl($value)
{
try {
if ($item = $this->iriConverter->getItemFromIri($value)) {
return $this->propertyAccessor->getValue($item, 'id');
}
} catch (\InvalidArgumentException $e) {
// Do nothing, return the raw value
}
return $value;
}
/**
* {@inheritdoc}
*/
public function getDescription(ResourceInterface $resource)
{
$description = [];
$metadata = $this->getClassMetadata($resource);
foreach ($metadata->getFieldNames() as $fieldName) {
$found = isset($this->properties[$fieldName]);
if ($found || null === $this->properties) {
$description[$fieldName.'-empty'] = [
'property' => $fieldName.'-empty',
'type' => 'string',
'required' => false
];
}
}
return $description;
}
}
resource.address.address:
parent: "api.resource"
class: "Foo\\AppBundle\\Api\\Address\\AddressResource"
arguments: [ "Foo\\AppBundle\\Entity\\Address\\Address" ]
calls:
- ...
- [ "initFilters", [ [ "@resource.empty_filter", "@resource.search_filter" , "@resource.order_filter" ] ] ]
tags: [ { name: "api.resource" } ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment