-
-
Notifications
You must be signed in to change notification settings - Fork 895
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
022fb6a
commit d161fe7
Showing
11 changed files
with
306 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,10 +13,62 @@ | |
|
||
namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension; | ||
|
||
class_exists(\ApiPlatform\Elasticsearch\Extension\AbstractFilterExtension::class); | ||
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; | ||
use Psr\Container\ContainerInterface; | ||
|
||
if (false) { | ||
class AbstractFilterExtension extends \ApiPlatform\Elasticsearch\Extension\AbstractFilterExtension | ||
/** | ||
* Abstract class for easing the implementation of a filter extension. | ||
* | ||
* @experimental | ||
* | ||
* @author Baptiste Meyer <[email protected]> | ||
*/ | ||
abstract class AbstractFilterExtension implements RequestBodySearchCollectionExtensionInterface | ||
{ | ||
private $resourceMetadataFactory; | ||
private $filterLocator; | ||
|
||
public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ContainerInterface $filterLocator) | ||
{ | ||
$this->resourceMetadataFactory = $resourceMetadataFactory; | ||
$this->filterLocator = $filterLocator; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function applyToCollection(array $requestBody, string $resourceClass, ?string $operationName = null, array $context = []): array | ||
{ | ||
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); | ||
$resourceFilters = $resourceMetadata->getCollectionOperationAttribute($operationName, 'filters', [], true); | ||
|
||
if (!$resourceFilters) { | ||
return $requestBody; | ||
} | ||
|
||
$context['filters'] = $context['filters'] ?? []; | ||
$clauseBody = []; | ||
|
||
foreach ($resourceFilters as $filterId) { | ||
if ($this->filterLocator->has($filterId) && is_a($filter = $this->filterLocator->get($filterId), $this->getFilterInterface())) { | ||
$clauseBody = $filter->apply($clauseBody, $resourceClass, $operationName, $context); | ||
} | ||
} | ||
|
||
if (!$clauseBody) { | ||
return $requestBody; | ||
} | ||
|
||
return $this->alterRequestBody($requestBody, $clauseBody); | ||
} | ||
|
||
/** | ||
* Gets the related filter interface. | ||
*/ | ||
abstract protected function getFilterInterface(): string; | ||
|
||
/** | ||
* Alters the request body. | ||
*/ | ||
abstract protected function alterRequestBody(array $requestBody, array $clauseBody): array; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,10 +13,39 @@ | |
|
||
namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension; | ||
|
||
class_exists(\ApiPlatform\Elasticsearch\Extension\ConstantScoreFilterExtension::class); | ||
use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\ConstantScoreFilterInterface; | ||
|
||
if (false) { | ||
final class ConstantScoreFilterExtension extends \ApiPlatform\Elasticsearch\Extension\ConstantScoreFilterExtension | ||
/** | ||
* Applies filter clauses while executing a constant score query. | ||
* | ||
* @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-constant-score-query.html | ||
* | ||
* @experimental | ||
* | ||
* @author Baptiste Meyer <[email protected]> | ||
*/ | ||
final class ConstantScoreFilterExtension extends AbstractFilterExtension | ||
{ | ||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function getFilterInterface(): string | ||
{ | ||
return ConstantScoreFilterInterface::class; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function alterRequestBody(array $requestBody, array $clauseBody): array | ||
{ | ||
$requestBody['query'] = $requestBody['query'] ?? []; | ||
$requestBody['query'] += [ | ||
'constant_score' => [ | ||
'filter' => $clauseBody, | ||
], | ||
]; | ||
|
||
return $requestBody; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,10 +13,88 @@ | |
|
||
namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension; | ||
|
||
class_exists(\ApiPlatform\Elasticsearch\Extension\SortExtension::class); | ||
use ApiPlatform\Core\Api\ResourceClassResolverInterface; | ||
use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; | ||
use ApiPlatform\Core\Bridge\Elasticsearch\Util\FieldDatatypeTrait; | ||
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; | ||
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; | ||
use Symfony\Component\Serializer\NameConverter\NameConverterInterface; | ||
|
||
if (false) { | ||
final class SortExtension extends \ApiPlatform\Elasticsearch\Extension\SortExtension | ||
/** | ||
* Applies selected sorting while querying resource collection. | ||
* | ||
* @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html | ||
* | ||
* @experimental | ||
* | ||
* @author Baptiste Meyer <[email protected]> | ||
*/ | ||
final class SortExtension implements RequestBodySearchCollectionExtensionInterface | ||
{ | ||
use FieldDatatypeTrait; | ||
|
||
private $defaultDirection; | ||
private $identifierExtractor; | ||
private $resourceMetadataFactory; | ||
private $nameConverter; | ||
|
||
public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, IdentifierExtractorInterface $identifierExtractor, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, ?NameConverterInterface $nameConverter = null, ?string $defaultDirection = null) | ||
{ | ||
$this->resourceMetadataFactory = $resourceMetadataFactory; | ||
$this->identifierExtractor = $identifierExtractor; | ||
$this->propertyMetadataFactory = $propertyMetadataFactory; | ||
$this->resourceClassResolver = $resourceClassResolver; | ||
$this->nameConverter = $nameConverter; | ||
$this->defaultDirection = $defaultDirection; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function applyToCollection(array $requestBody, string $resourceClass, ?string $operationName = null, array $context = []): array | ||
{ | ||
$orders = []; | ||
|
||
if ( | ||
null !== ($defaultOrder = $this->resourceMetadataFactory->create($resourceClass)->getAttribute('order')) | ||
&& \is_array($defaultOrder) | ||
) { | ||
foreach ($defaultOrder as $property => $direction) { | ||
if (\is_int($property)) { | ||
$property = $direction; | ||
$direction = 'asc'; | ||
} | ||
|
||
$orders[] = $this->getOrder($resourceClass, $property, $direction); | ||
} | ||
} elseif (null !== $this->defaultDirection) { | ||
$orders[] = $this->getOrder( | ||
$resourceClass, | ||
$this->identifierExtractor->getIdentifierFromResourceClass($resourceClass), | ||
$this->defaultDirection | ||
); | ||
} | ||
|
||
if (!$orders) { | ||
return $requestBody; | ||
} | ||
|
||
$requestBody['sort'] = array_merge_recursive($requestBody['sort'] ?? [], $orders); | ||
|
||
return $requestBody; | ||
} | ||
|
||
private function getOrder(string $resourceClass, string $property, string $direction): array | ||
{ | ||
$order = ['order' => strtolower($direction)]; | ||
|
||
if (null !== $nestedPath = $this->getNestedFieldPath($resourceClass, $property)) { | ||
$nestedPath = null === $this->nameConverter ? $nestedPath : $this->nameConverter->normalize($nestedPath, $resourceClass); | ||
$order['nested'] = ['path' => $nestedPath]; | ||
} | ||
|
||
$property = null === $this->nameConverter ? $property : $this->nameConverter->normalize($property, $resourceClass); | ||
|
||
return [$property => $order]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,10 +13,34 @@ | |
|
||
namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension; | ||
|
||
class_exists(\ApiPlatform\Elasticsearch\Extension\SortFilterExtension::class); | ||
use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter\SortFilterInterface; | ||
|
||
if (false) { | ||
final class SortFilterExtension extends \ApiPlatform\Elasticsearch\Extension\SortFilterExtension | ||
/** | ||
* Applies filters on the sort parameter while querying resource collection. | ||
* | ||
* @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html | ||
* | ||
* @experimental | ||
* | ||
* @author Baptiste Meyer <[email protected]> | ||
*/ | ||
final class SortFilterExtension extends AbstractFilterExtension | ||
{ | ||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function getFilterInterface(): string | ||
{ | ||
return SortFilterInterface::class; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function alterRequestBody(array $requestBody, array $clauseBody): array | ||
{ | ||
$requestBody['sort'] = array_merge_recursive($requestBody['sort'] ?? [], $clauseBody); | ||
|
||
return $requestBody; | ||
} | ||
} |
22 changes: 0 additions & 22 deletions
22
src/Core/Bridge/Elasticsearch/Serializer/DocumentNormalizer.php
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,10 +13,90 @@ | |
|
||
namespace ApiPlatform\Core\Bridge\Elasticsearch\Serializer; | ||
|
||
class_exists(\ApiPlatform\Elasticsearch\Serializer\ItemNormalizer::class); | ||
use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface; | ||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface; | ||
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; | ||
use Symfony\Component\Serializer\Exception\LogicException; | ||
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface; | ||
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; | ||
use Symfony\Component\Serializer\NameConverter\NameConverterInterface; | ||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; | ||
|
||
if (false) { | ||
final class ItemNormalizer extends \ApiPlatform\Elasticsearch\Serializer\ItemNormalizer | ||
/** | ||
* Item denormalizer for Elasticsearch. | ||
* | ||
* @experimental | ||
* | ||
* @author Baptiste Meyer <[email protected]> | ||
*/ | ||
final class ItemNormalizer extends ObjectNormalizer | ||
{ | ||
public const FORMAT = 'elasticsearch'; | ||
|
||
private $identifierExtractor; | ||
|
||
public function __construct(IdentifierExtractorInterface $identifierExtractor, ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null, array $defaultContext = []) | ||
{ | ||
parent::__construct($classMetadataFactory, $nameConverter, $propertyAccessor, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver, $defaultContext); | ||
|
||
$this->identifierExtractor = $identifierExtractor; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function supportsDenormalization($data, $type, $format = null): bool | ||
{ | ||
return self::FORMAT === $format && parent::supportsDenormalization($data, $type, $format); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
* | ||
* @return mixed | ||
*/ | ||
public function denormalize($data, $class, $format = null, array $context = []) | ||
{ | ||
if (\is_string($data['_id'] ?? null) && \is_array($data['_source'] ?? null)) { | ||
$data = $this->populateIdentifier($data, $class)['_source']; | ||
} | ||
|
||
return parent::denormalize($data, $class, $format, $context); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function supportsNormalization($data, $format = null): bool | ||
{ | ||
// prevent the use of lower priority normalizers (e.g. serializer.normalizer.object) for this format | ||
return self::FORMAT === $format; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
* | ||
* @throws LogicException | ||
* | ||
* @return mixed | ||
*/ | ||
public function normalize($object, $format = null, array $context = []) | ||
{ | ||
throw new LogicException(sprintf('%s is a write-only format.', self::FORMAT)); | ||
} | ||
|
||
/** | ||
* Populates the resource identifier with the document identifier if not present in the original JSON document. | ||
*/ | ||
private function populateIdentifier(array $data, string $class): array | ||
{ | ||
$identifier = $this->identifierExtractor->getIdentifierFromResourceClass($class); | ||
$identifier = null === $this->nameConverter ? $identifier : $this->nameConverter->normalize($identifier, $class, self::FORMAT); | ||
|
||
if (!isset($data['_source'][$identifier])) { | ||
$data['_source'][$identifier] = $data['_id']; | ||
} | ||
|
||
return $data; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.