From b4301a01973457bee3996bbc8ff366e7a8dbaf38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simonas=20=C5=A0erlinskas?= Date: Thu, 21 Mar 2019 22:25:09 +0200 Subject: [PATCH 01/17] adding missing symfony/asset closes #859 (#871) --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 1151f665..d4c734b2 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,7 @@ "symfony/console": "^2.8|^3.0|^4", "symfony/stopwatch": "^2.8|^3.0|^4", "symfony/templating": "^2.8|^3.0|^4", + "symfony/asset": "^2.8|^3.0|^4", "doctrine/annotations": "~1.2", "doctrine/inflector": "~1.0", "doctrine/cache": "~1.4", From b2e40024680c0939a88562dba416548574c57685 Mon Sep 17 00:00:00 2001 From: esynaps <30432290+esynaps@users.noreply.github.com> Date: Thu, 30 May 2019 15:58:15 +0200 Subject: [PATCH 02/17] Add condition to ignore unused managers in TerminateListener (#878) --- EventListener/TerminateListener.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/EventListener/TerminateListener.php b/EventListener/TerminateListener.php index 4393419b..c7922ebf 100644 --- a/EventListener/TerminateListener.php +++ b/EventListener/TerminateListener.php @@ -46,8 +46,15 @@ public function onKernelTerminate() foreach ($this->managers as $key => $value) { if ($value['force_commit']) { try { + $managerName = sprintf('es.manager.%s', $key); + + // Ignore managers who have not been initialized. + if(!$this->container->initialized($managerName)) { + continue; + } + /** @var Manager $manager */ - $manager = $this->container->get(sprintf('es.manager.%s', $key)); + $manager = $this->container->get($managerName); } catch (\Exception $e) { continue; } From 494c5af9a9b5ae42915a247157319cd3a82606d0 Mon Sep 17 00:00:00 2001 From: PWalkow Date: Mon, 17 Jun 2019 07:49:09 +0100 Subject: [PATCH 03/17] Fix for memory problem in export index (#879) As file value was used to store all of the documents it stopped the script when the value was getting too big due to number of documents stored in it. Value was not used so I just removed it. --- Service/ExportService.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/Service/ExportService.php b/Service/ExportService.php index 71281fe8..5977f9c1 100644 --- a/Service/ExportService.php +++ b/Service/ExportService.php @@ -82,7 +82,6 @@ public function exportIndex( $filename = str_replace('.json', '', $filename); $writer = $this->getWriter($this->getFilePath($filename.'.json'), $metadata); - $file = []; foreach ($results as $data) { if ($counter >= $maxLinesInFile) { $writer->finalize(); @@ -99,7 +98,6 @@ public function exportIndex( $doc = array_intersect_key($data, array_flip(['_id', '_type', '_source'])); $writer->push($doc); - $file[] = $doc; $progress->advance(); $counter++; } From 1cb4cbb7a431b2e3a2f41fb07aa18742cf2f4ed1 Mon Sep 17 00:00:00 2001 From: Mantas Marcinkevicius Date: Thu, 24 Oct 2019 00:21:26 +0300 Subject: [PATCH 04/17] reimplemented document serialization --- DependencyInjection/Compiler/MappingPass.php | 14 ++- Mapping/Converter.php | 91 ++++++++++++++++--- Mapping/DocumentParser.php | 87 ++++++++++++++++++ Mapping/NameConverter.php | 4 +- Resources/config/services.yml | 1 - Result/AbstractResultsIterator.php | 4 - Result/DocumentIterator.php | 6 +- Result/ObjectIterator.php | 11 +-- Service/ExportService.php | 1 - Service/IndexService.php | 11 +-- .../Functional/Result/PersistObjectsTest.php | 15 +++ Tests/Unit/Mapping/DocumentParserTest.php | 4 +- .../Result/AbstractResultsIteratorTest.php | 2 +- Tests/Unit/Result/DocumentIteratorTest.php | 2 +- .../Document/IndexWithFieldsDataDocument.php | 10 +- 15 files changed, 209 insertions(+), 54 deletions(-) diff --git a/DependencyInjection/Compiler/MappingPass.php b/DependencyInjection/Compiler/MappingPass.php index 3f696a9e..dc739659 100644 --- a/DependencyInjection/Compiler/MappingPass.php +++ b/DependencyInjection/Compiler/MappingPass.php @@ -59,6 +59,7 @@ private function handleDirectoryMapping(ContainerBuilder $container, string $dir /** @var DocumentParser $parser */ $parser = $container->get(DocumentParser::class); $indexesOverride = $container->getParameter(Configuration::ONGR_INDEXES_OVERRIDE); + $converterDefinition = $container->getDefinition(Converter::class); foreach ($this->getNamespaces($dir) as $namespace) { $class = new \ReflectionClass($namespace); @@ -71,10 +72,9 @@ private function handleDirectoryMapping(ContainerBuilder $container, string $dir /** @var Index $document */ $document = $parser->getIndexAnnotation($class); - $indexMapping = $parser->getIndexMetadata($class); $indexMetadata = $parser->getIndexMetadata($class); - if (!empty($indexMapping)) { + if (!empty($indexMetadata)) { $indexMetadata['settings'] = array_filter(array_merge_recursive( $indexMetadata['settings'] ?? [], [ @@ -99,14 +99,20 @@ private function handleDirectoryMapping(ContainerBuilder $container, string $dir $indexServiceDefinition = new Definition(IndexService::class, [ $namespace, - $container->getDefinition(Converter::class), + $converterDefinition, $container->getDefinition('event_dispatcher'), - $container->getDefinition('serializer'), $indexSettings, $container->getParameter(Configuration::ONGR_PROFILER_CONFIG) ? $container->getDefinition('ongr.esb.tracer') : null ]); $indexServiceDefinition->setPublic(true); + $converterDefinition->addMethodCall( + 'addClassMetadata', + [ + $namespace, + $parser->getPropertyMetadata($class) + ] + ); $container->setDefinition($namespace, $indexServiceDefinition); $this->indexes[$indexAlias] = $namespace; diff --git a/Mapping/Converter.php b/Mapping/Converter.php index f347cb5a..adf6ce47 100644 --- a/Mapping/Converter.php +++ b/Mapping/Converter.php @@ -11,34 +11,97 @@ namespace ONGR\ElasticsearchBundle\Mapping; -use ONGR\ElasticsearchBundle\Annotation\NestedType; -use ONGR\ElasticsearchBundle\Annotation\ObjectType; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Symfony\Component\Serializer\Serializer; -use Symfony\Component\Serializer\SerializerAwareTrait; -use Symfony\Component\Serializer\SerializerInterface; +use ONGR\ElasticsearchBundle\Result\ObjectIterator; /** * This class converts array to document object. */ class Converter { - use SerializerAwareTrait; + private $propertyMetadata = []; - private $documentParser; + public function addClassMetadata(string $class, array $metadata): void + { + $this->propertyMetadata[$class] = $metadata; + } + + public function convertArrayToDocument(string $namespace, array $raw) + { + if (!isset($this->propertyMetadata[$namespace])) { + echo json_encode($raw, JSON_PRETTY_PRINT); - public function __construct(DocumentParser $documentParser) + return []; + } + + return $this->denormalize($raw, $namespace); + } + + public function convertDocumentToArray($document): array { - $this->documentParser = $documentParser; + $class = get_class($document); + + if (!isset($this->propertyMetadata[$class])) { + throw new \Exception("Cannot convert object of class `$class` to array."); + } + + return $this->normalize($document); } - public function convertArrayToDocument(string $namespace, array $raw, Serializer $serializer) + protected function normalize($document, $metadata = null) { - return $serializer->denormalize($raw, $namespace); + $metadata = $metadata ?? $this->propertyMetadata[get_class($document)]; + $result = []; + + foreach ($metadata as $field => $fieldMeta) { + $getter = $fieldMeta['getter']; + $value = $fieldMeta['public'] ? $document->{$fieldMeta['name']} : $document->$getter(); + + if ($fieldMeta['embeded']) { + if (is_iterable($value)) { + foreach ($value as $item) { + $result[$field][] = $this->normalize($item, $fieldMeta['sub_properties']); + } + } else { + $result[$field] = $this->normalize($item, $fieldMeta['sub_properties']); + } + } else { + $result[$field] = $value; + } + } + + return $result; } - public function convertDocumentToArray($document, Serializer $serializer): array + protected function denormalize(array $raw, string $namespace) { - return $serializer->normalize($document, 'array'); + $metadata = $this->propertyMetadata[$namespace]; + $object = new $namespace(); + + foreach ($raw as $field => $value) { + $fieldMeta = $metadata[$field]; + $setter = $fieldMeta['setter']; + + if ($fieldMeta['embeded']) { + $this->addClassMetadata($fieldMeta['class'], $fieldMeta['sub_properties']); + $object->$setter(new ObjectIterator($fieldMeta['class'], $value, $this)); + } else { + if ($fieldMeta['public']) { + $object->{$fieldMeta['name']} = $value; + } else { + if ($fieldMeta['identifier']) { + $setter = function ($field, $value) { + $this->$field = $value; + }; + + $setter = \Closure::bind($setter, $object, $object); + $setter($fieldMeta['name'], $value); + } else { + $object->$setter($value); + } + } + } + } + + return $object; } } diff --git a/Mapping/DocumentParser.php b/Mapping/DocumentParser.php index b8b74cdc..95137d0b 100644 --- a/Mapping/DocumentParser.php +++ b/Mapping/DocumentParser.php @@ -16,6 +16,7 @@ use Doctrine\Common\Cache\Cache; use ONGR\ElasticsearchBundle\Annotation\AbstractAnnotation; use ONGR\ElasticsearchBundle\Annotation\Embedded; +use ONGR\ElasticsearchBundle\Annotation\Id; use ONGR\ElasticsearchBundle\Annotation\Index; use ONGR\ElasticsearchBundle\Annotation\NestedType; use ONGR\ElasticsearchBundle\Annotation\ObjectType; @@ -186,6 +187,66 @@ private function getClassMetadata(\ReflectionClass $class): array return $mapping; } + public function getPropertyMetadata(\ReflectionClass $class, bool $subClass = false): array + { + if ($class->isTrait() || (!$this->reader->getClassAnnotation($class, Index::class) && !$subClass)) { + return []; + } + + $metadata = []; + + /** @var \ReflectionProperty $property */ + foreach ($this->getDocumentPropertiesReflection($class) as $name => $property) { + /** @var AbstractAnnotation $annotation */ + foreach ($this->reader->getPropertyAnnotations($property) as $annotation) { + if (!$annotation instanceof PropertiesAwareInterface) { + continue; + } + + $propertyMetadata = [ + 'identifier' => false, + 'class' => null, + 'embeded' => false, + 'public' => $property->isPublic(), + 'getter' => null, + 'setter' => null, + 'sub_properties' => [] + ]; + + $name = $property->getName(); + $propertyMetadata['name'] = $name; + + if (!$propertyMetadata['public']) { + $propertyMetadata['getter'] = $this->guessGetter($class, $name); + } + + $fieldMapping = $annotation->getSettings(); + + if ($annotation instanceof Id) { + $propertyMetadata['identifier'] = true; + $propertyMetadata['setter'] = null; + } else { + if (!$propertyMetadata['public']) { + $propertyMetadata['setter'] = $this->guessSetter($class, $name); + } + } + + if ($annotation instanceof Embedded) { + $propertyMetadata['embeded'] = true; + $propertyMetadata['class'] = $annotation->class; + $propertyMetadata['sub_properties'] = $this->getPropertyMetadata( + new \ReflectionClass($annotation->class), + true + ); + } + + $metadata[$annotation->getName() ?? Caser::snake($name)] = $propertyMetadata; + } + } + + return $metadata; + } + public function getAnalysisConfig(\ReflectionClass $class): array { $config = []; @@ -215,6 +276,32 @@ public function getAnalysisConfig(\ReflectionClass $class): array return $config; } + private function guessGetter(\ReflectionClass $class, $name): string + { + if ($class->hasMethod($name)) { + return $name; + } + + if ($class->hasMethod('get' . ucfirst($name))) { + return 'get' . ucfirst($name); + } + + if ($class->hasMethod('is' . ucfirst($name))) { + return 'get' . ucfirst($name); + } + + throw new \Exception("Could not determine a getter for `$name` of class `{$class->getNamespaceName()}`"); + } + + private function guessSetter(\ReflectionClass $class, $name): string + { + if ($class->hasMethod('set' . ucfirst($name))) { + return 'set' . ucfirst($name); + } + + throw new \Exception("Could not determine a setter for `$name` of class `{$class->getNamespaceName()}`"); + } + private function getListFromArrayByKey(string $searchKey, array $array): array { $list = []; diff --git a/Mapping/NameConverter.php b/Mapping/NameConverter.php index dfd6b398..f76eeae9 100644 --- a/Mapping/NameConverter.php +++ b/Mapping/NameConverter.php @@ -12,9 +12,9 @@ namespace ONGR\ElasticsearchBundle\Mapping; use Doctrine\Common\Cache\Cache; -use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; +use Symfony\Component\Serializer\NameConverter\NameConverterInterface; -class NameConverter implements AdvancedNameConverterInterface +class NameConverter implements NameConverterInterface { private $cache; diff --git a/Resources/config/services.yml b/Resources/config/services.yml index b34204a7..39322050 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -34,7 +34,6 @@ services: arguments: ["@ongr.esb.cache_reader", "@ongr.esb.cache", "%ongr.esb.analysis%"] ONGR\ElasticsearchBundle\Mapping\Converter: - arguments: ['@ONGR\ElasticsearchBundle\Mapping\DocumentParser'] ONGR\ElasticsearchBundle\Profiler\Handler\CollectionHandler: public: false diff --git a/Result/AbstractResultsIterator.php b/Result/AbstractResultsIterator.php index fc35b851..39061833 100644 --- a/Result/AbstractResultsIterator.php +++ b/Result/AbstractResultsIterator.php @@ -13,7 +13,6 @@ use ONGR\ElasticsearchBundle\Mapping\Converter; use ONGR\ElasticsearchBundle\Service\IndexService; -use Symfony\Component\Serializer\Serializer; abstract class AbstractResultsIterator implements \Countable, \Iterator { @@ -30,13 +29,11 @@ abstract class AbstractResultsIterator implements \Countable, \Iterator //Used to count scroll iteration. private $key = 0; - protected $serializer; public function __construct( array $rawData, IndexService $index, Converter $converter = null, - Serializer $serializer = null, array $scroll = [] ) { $this->raw = $rawData; @@ -58,7 +55,6 @@ public function __construct( if (isset($rawData['hits']['total'])) { $this->count = $rawData['hits']['total']; } - $this->serializer = $serializer; } public function __destruct() diff --git a/Result/DocumentIterator.php b/Result/DocumentIterator.php index e680fb19..7665fe9f 100644 --- a/Result/DocumentIterator.php +++ b/Result/DocumentIterator.php @@ -41,10 +41,6 @@ protected function convertDocument(array $raw) $data = $raw['_source'] ?? $raw['_fields'] ?? null; $data['_id'] = $raw['_id'] ?? null; - return $this->getConverter()->convertArrayToDocument( - $this->getIndex()->getNamespace(), - array_filter($data), - $this->serializer - ); + return $this->getConverter()->convertArrayToDocument($this->getIndex()->getNamespace(), array_filter($data)); } } diff --git a/Result/ObjectIterator.php b/Result/ObjectIterator.php index ab239c95..502dcca9 100644 --- a/Result/ObjectIterator.php +++ b/Result/ObjectIterator.php @@ -14,7 +14,6 @@ use Doctrine\Common\Collections\AbstractLazyCollection; use Doctrine\Common\Collections\ArrayCollection; use ONGR\ElasticsearchBundle\Mapping\Converter; -use Symfony\Component\Serializer\Serializer; /** * This is for embedded ObjectType's or NestedType's iterator implemented with a lazy loading. @@ -24,23 +23,17 @@ class ObjectIterator extends AbstractLazyCollection private $converter; protected $collection; private $namespace; - private $serializer; - public function __construct(string $namespace, array $array, Converter $converter, Serializer $serializer) + public function __construct(string $namespace, array $array, Converter $converter) { $this->converter = $converter; $this->collection = new ArrayCollection($array); $this->namespace = $namespace; - $this->serializer = $serializer; } protected function convertDocument(array $data) { - return $this->converter->convertArrayToDocument( - $this->namespace, - $data, - $this->serializer - ); + return $this->converter->convertArrayToDocument($this->namespace, $data); } protected function doInitialize() diff --git a/Service/ExportService.php b/Service/ExportService.php index 6cfafdef..28dfe828 100644 --- a/Service/ExportService.php +++ b/Service/ExportService.php @@ -43,7 +43,6 @@ public function exportIndex( $searchResults, $index, null, - null, [ 'duration' => '2m', '_scroll_id' => $searchResults['_scroll_id'], diff --git a/Service/IndexService.php b/Service/IndexService.php index e6efc973..5f202d42 100644 --- a/Service/IndexService.php +++ b/Service/IndexService.php @@ -28,7 +28,6 @@ use ONGR\ElasticsearchDSL\Sort\FieldSort; use ONGR\ElasticsearchBundle\Result\DocumentIterator; use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Serializer\Serializer; class IndexService { @@ -41,21 +40,18 @@ class IndexService private $bulkCommitSize = 100; private $bulkQueries = []; private $indexSettings = []; - private $serializer; private $tracer; public function __construct( string $namespace, Converter $converter, EventDispatcherInterface $eventDispatcher, - Serializer $serializer, IndexSettings $indexSettings, $tracer = null ) { $this->namespace = $namespace; $this->converter = $converter; $this->eventDispatcher = $eventDispatcher; - $this->serializer = $serializer; $this->indexSettings = $indexSettings; $this->tracer = $tracer; $this->getClient(); @@ -207,7 +203,7 @@ public function find($id, $params = []) $result['_source']['_id'] = $result['_id']; - return $this->converter->convertArrayToDocument($this->namespace, $result['_source'], $this->serializer); + return $this->converter->convertArrayToDocument($this->namespace, $result['_source']); } public function findByIds(array $ids): DocumentIterator @@ -286,7 +282,6 @@ public function findDocuments(Search $search): DocumentIterator $results, $this, $this->converter, - $this->serializer, $this->getScrollConfiguration($results, $search->getScroll()) ); } @@ -299,7 +294,6 @@ public function findArray(Search $search): ArrayIterator $results, $this, $this->converter, - $this->serializer, $this->getScrollConfiguration($results, $search->getScroll()) ); } @@ -312,7 +306,6 @@ public function findRaw(Search $search): RawIterator $results, $this, $this->converter, - $this->serializer, $this->getScrollConfiguration($results, $search->getScroll()) ); } @@ -439,7 +432,7 @@ public function bulk(string $operation, array $data = [], $autoCommit = true): a */ public function persist($document): void { - $documentArray = array_filter($this->converter->convertDocumentToArray($document, $this->serializer)); + $documentArray = array_filter($this->converter->convertDocumentToArray($document)); $this->bulk('index', $documentArray); } diff --git a/Tests/Functional/Result/PersistObjectsTest.php b/Tests/Functional/Result/PersistObjectsTest.php index bd3d633c..951e4c6c 100644 --- a/Tests/Functional/Result/PersistObjectsTest.php +++ b/Tests/Functional/Result/PersistObjectsTest.php @@ -12,6 +12,7 @@ namespace ONGR\ElasticsearchBundle\Tests\Functional\Result; use ONGR\ElasticsearchBundle\Test\AbstractElasticsearchTestCase; +use ONGR\App\Document\IndexWithFieldsDataDocument; use ONGR\App\Document\CollectionNested; use ONGR\App\Document\DummyDocument; @@ -44,4 +45,18 @@ public function testPersistObject() $document = $index->find(5); $this->assertEquals('bar bar', $document->title); } + + public function testAddingValuesToPrivateIdsWithoutSetters() + { + $index = $this->getIndex(IndexWithFieldsDataDocument::class); + + $document = new IndexWithFieldsDataDocument(); + $document->title = 'acme'; + + $index->persist($document); + $index->commit(); + + $document = $index->findOneBy(['private' => 'acme']); + $this->assertNotNull($document->getId()); + } } diff --git a/Tests/Unit/Mapping/DocumentParserTest.php b/Tests/Unit/Mapping/DocumentParserTest.php index 71de8db6..48fd6067 100644 --- a/Tests/Unit/Mapping/DocumentParserTest.php +++ b/Tests/Unit/Mapping/DocumentParserTest.php @@ -31,9 +31,9 @@ public function testDocumentParsing() 'mappings' => [ '_doc' => [ 'properties' => [ - 'keyword_field' => [ + 'keyword_field' => [ 'type' => 'keyword', - ] + ] ] ] ] diff --git a/Tests/Unit/Result/AbstractResultsIteratorTest.php b/Tests/Unit/Result/AbstractResultsIteratorTest.php index 5c7e6e4a..2fe363ff 100644 --- a/Tests/Unit/Result/AbstractResultsIteratorTest.php +++ b/Tests/Unit/Result/AbstractResultsIteratorTest.php @@ -34,7 +34,7 @@ public function testClearScroll() $index->expects($this->once())->method('clearScroll')->with('foo'); $scroll = ['_scroll_id' => 'foo', 'duration' => '5m']; - $iterator = new RawIterator($rawData, $index, null, null, $scroll); + $iterator = new RawIterator($rawData, $index, null, $scroll); // Trigger destructor call unset($iterator); diff --git a/Tests/Unit/Result/DocumentIteratorTest.php b/Tests/Unit/Result/DocumentIteratorTest.php index f7b9d2d2..f19fde65 100644 --- a/Tests/Unit/Result/DocumentIteratorTest.php +++ b/Tests/Unit/Result/DocumentIteratorTest.php @@ -69,7 +69,7 @@ public function testResultConvert() $index->expects($this->any())->method('getNamespace')->willReturn(DummyDocument::class); - $iterator = new DocumentIterator($rawData, $index, $converter, $this->createMock(Serializer::class)); + $iterator = new DocumentIterator($rawData, $index, $converter); $this->assertEquals($document, $iterator->first()); } } diff --git a/Tests/app/src/Document/IndexWithFieldsDataDocument.php b/Tests/app/src/Document/IndexWithFieldsDataDocument.php index f31fe6ba..5b0279c2 100644 --- a/Tests/app/src/Document/IndexWithFieldsDataDocument.php +++ b/Tests/app/src/Document/IndexWithFieldsDataDocument.php @@ -26,10 +26,18 @@ class IndexWithFieldsDataDocument /** * @ES\Id() */ - public $id; + private $id; /** * @ES\Property(type="text", name="private", settings={"fielddata"=true}) */ public $title; + + /** + * @return mixed + */ + public function getId() + { + return $this->id; + } } From 1b9ec8a6e03e35bfdc5bafcaa1536129e1e323af Mon Sep 17 00:00:00 2001 From: Mantas Marcinkevicius Date: Thu, 24 Oct 2019 00:26:40 +0300 Subject: [PATCH 05/17] removed unnecessary serialization classes --- Mapping/NameConverter.php | 47 ------------------------------- Mapping/ObjectNormalizer.php | 53 ----------------------------------- Resources/config/services.yml | 11 +------- 3 files changed, 1 insertion(+), 110 deletions(-) delete mode 100644 Mapping/NameConverter.php delete mode 100644 Mapping/ObjectNormalizer.php diff --git a/Mapping/NameConverter.php b/Mapping/NameConverter.php deleted file mode 100644 index f76eeae9..00000000 --- a/Mapping/NameConverter.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace ONGR\ElasticsearchBundle\Mapping; - -use Doctrine\Common\Cache\Cache; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - -class NameConverter implements NameConverterInterface -{ - private $cache; - - public function __construct(Cache $cache) - { - $this->cache = $cache; - } - - public function normalize($propertyName, string $class = null, string $format = null, array $context = []) - { - $fields = $this->cache->fetch(DocumentParser::OBJ_CACHED_FIELDS); - - if (isset($fields[$class])) { - return $fields[$class][$propertyName] ?? $propertyName; - } - - return $propertyName; - } - - public function denormalize($propertyName, string $class = null, string $format = null, array $context = []) - { - $fields = $this->cache->fetch(DocumentParser::ARRAY_CACHED_FIELDS); - - if (isset($fields[$class])) { - return $fields[$class][$propertyName] ?? $propertyName; - } - - return $propertyName; - } -} diff --git a/Mapping/ObjectNormalizer.php b/Mapping/ObjectNormalizer.php deleted file mode 100644 index daac1f05..00000000 --- a/Mapping/ObjectNormalizer.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace ONGR\ElasticsearchBundle\Mapping; - -use Doctrine\Common\Cache\Cache; -use ONGR\ElasticsearchBundle\Result\ObjectIterator; -use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -use Symfony\Component\Serializer\NameConverter\NameConverterInterface; -use Symfony\Component\Serializer\Normalizer\ObjectNormalizer as SymfonyObjectNormalizer; - -class ObjectNormalizer extends SymfonyObjectNormalizer -{ - private $cache; - private $converter; - - public function __construct( - Cache $cache, - Converter $converter, - NameConverterInterface $nameConverter = null, - PropertyAccessorInterface $propertyAccessor = null - ) { - parent::__construct(null, $nameConverter, $propertyAccessor, null, null, null, []); - - $this->cache = $cache; - $this->converter = $converter; - } - - protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = []) - { - $embeddedFields = $this->cache->fetch(DocumentParser::EMBEDDED_CACHED_FIELDS); - - $class = $embeddedFields[get_class($object)][$attribute] ?? null; - - try { - if ($class && is_array($value)) { - $value = new ObjectIterator($class, $value, $this->converter, $this->serializer); - } - - $this->propertyAccessor->setValue($object, $attribute, $value); - } catch (NoSuchPropertyException $exception) { - // Properties not found are ignored - } - } -} diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 39322050..6b9ac085 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -21,20 +21,11 @@ services: ONGR\ElasticsearchBundle\Service\ExportService: ~ ONGR\ElasticsearchBundle\Service\ImportService: ~ ONGR\ElasticsearchBundle\Service\IndexSuffixFinder: ~ - - ONGR\ElasticsearchBundle\Mapping\ObjectNormalizer: - arguments: ["@ongr.esb.cache", '@ONGR\ElasticsearchBundle\Mapping\Converter', '@ONGR\ElasticsearchBundle\Mapping\NameConverter'] - tags: - - { name: serializer.normalizer, priority: 100} - - ONGR\ElasticsearchBundle\Mapping\NameConverter: - arguments: ["@ongr.esb.cache"] + ONGR\ElasticsearchBundle\Mapping\Converter: ~ ONGR\ElasticsearchBundle\Mapping\DocumentParser: arguments: ["@ongr.esb.cache_reader", "@ongr.esb.cache", "%ongr.esb.analysis%"] - ONGR\ElasticsearchBundle\Mapping\Converter: - ONGR\ElasticsearchBundle\Profiler\Handler\CollectionHandler: public: false From 22fdb0dc68745d8c4b1b4dc15adab01eb3469148 Mon Sep 17 00:00:00 2001 From: Mantas Marcinkevicius Date: Thu, 24 Oct 2019 00:46:55 +0300 Subject: [PATCH 06/17] minor fixes to serialization --- Mapping/Converter.php | 4 +--- Mapping/DocumentParser.php | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Mapping/Converter.php b/Mapping/Converter.php index adf6ce47..fd767c7b 100644 --- a/Mapping/Converter.php +++ b/Mapping/Converter.php @@ -28,9 +28,7 @@ public function addClassMetadata(string $class, array $metadata): void public function convertArrayToDocument(string $namespace, array $raw) { if (!isset($this->propertyMetadata[$namespace])) { - echo json_encode($raw, JSON_PRETTY_PRINT); - - return []; + throw new \Exception("Cannot convert array to object of class `$class`."); } return $this->denormalize($raw, $namespace); diff --git a/Mapping/DocumentParser.php b/Mapping/DocumentParser.php index 95137d0b..c58a2c98 100644 --- a/Mapping/DocumentParser.php +++ b/Mapping/DocumentParser.php @@ -287,7 +287,7 @@ private function guessGetter(\ReflectionClass $class, $name): string } if ($class->hasMethod('is' . ucfirst($name))) { - return 'get' . ucfirst($name); + return 'is' . ucfirst($name); } throw new \Exception("Could not determine a getter for `$name` of class `{$class->getNamespaceName()}`"); From 4c76fe5402299c69cb60103538488a83e93a7849 Mon Sep 17 00:00:00 2001 From: Mantas Marcinkevicius Date: Thu, 24 Oct 2019 09:01:29 +0300 Subject: [PATCH 07/17] implemented embedded public property serialization --- Mapping/Converter.php | 8 +++++++- Mapping/DocumentParser.php | 5 ++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Mapping/Converter.php b/Mapping/Converter.php index fd767c7b..3b022d32 100644 --- a/Mapping/Converter.php +++ b/Mapping/Converter.php @@ -81,7 +81,13 @@ protected function denormalize(array $raw, string $namespace) if ($fieldMeta['embeded']) { $this->addClassMetadata($fieldMeta['class'], $fieldMeta['sub_properties']); - $object->$setter(new ObjectIterator($fieldMeta['class'], $value, $this)); + $iterator = new ObjectIterator($fieldMeta['class'], $value, $this); + + if ($fieldMeta['public']) { + $object->{$fieldMeta['name']} = $iterator; + } else { + $object->$setter($iterator); + } } else { if ($fieldMeta['public']) { $object->{$fieldMeta['name']} = $value; diff --git a/Mapping/DocumentParser.php b/Mapping/DocumentParser.php index c58a2c98..a390f3d6 100644 --- a/Mapping/DocumentParser.php +++ b/Mapping/DocumentParser.php @@ -224,7 +224,6 @@ public function getPropertyMetadata(\ReflectionClass $class, bool $subClass = fa if ($annotation instanceof Id) { $propertyMetadata['identifier'] = true; - $propertyMetadata['setter'] = null; } else { if (!$propertyMetadata['public']) { $propertyMetadata['setter'] = $this->guessSetter($class, $name); @@ -276,7 +275,7 @@ public function getAnalysisConfig(\ReflectionClass $class): array return $config; } - private function guessGetter(\ReflectionClass $class, $name): string + protected function guessGetter(\ReflectionClass $class, $name): string { if ($class->hasMethod($name)) { return $name; @@ -293,7 +292,7 @@ private function guessGetter(\ReflectionClass $class, $name): string throw new \Exception("Could not determine a getter for `$name` of class `{$class->getNamespaceName()}`"); } - private function guessSetter(\ReflectionClass $class, $name): string + protected function guessSetter(\ReflectionClass $class, $name): string { if ($class->hasMethod('set' . ucfirst($name))) { return 'set' . ucfirst($name); From b3b44e41690b451e4adb191ad809593860dd128e Mon Sep 17 00:00:00 2001 From: Christoph Singer Date: Tue, 26 Nov 2019 17:16:12 +0100 Subject: [PATCH 08/17] do not set _index in bulk data in order to prevent error "explicit index in bulk is not allowed" in ES instances where rest.action.multi.allow_explicit_index is set to false. We don't need this _index setting in `bulk` method because in `commit` method index is set to $this->getIndexName() --- Service/IndexService.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Service/IndexService.php b/Service/IndexService.php index 5f202d42..e65b61ec 100644 --- a/Service/IndexService.php +++ b/Service/IndexService.php @@ -397,7 +397,6 @@ public function search(array $query, array $params = []): array public function bulk(string $operation, array $data = [], $autoCommit = true): array { $bulkParams = [ - '_index' => $this->getIndexName(), '_type' => $this->getTypeName(), '_id' => $data['_id'] ?? null, ]; From 5b3d495f295b3a2ee7d3735465f8ae8267f7f1b9 Mon Sep 17 00:00:00 2001 From: Christoph Singer Date: Wed, 27 Nov 2019 15:55:55 +0100 Subject: [PATCH 09/17] guess getters with underscore-to-camelcase conversion --- Mapping/DocumentParser.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Mapping/DocumentParser.php b/Mapping/DocumentParser.php index a390f3d6..710b6ae8 100644 --- a/Mapping/DocumentParser.php +++ b/Mapping/DocumentParser.php @@ -289,6 +289,17 @@ protected function guessGetter(\ReflectionClass $class, $name): string return 'is' . ucfirst($name); } + // if there are underscores in the name convert them to CamelCase + if (strpos($name, '_')) { + $name = Caser::camel($name); + if ($class->hasMethod('get' . ucfirst($name))) { + return 'get' . $name; + } + if ($class->hasMethod('is' . ucfirst($name))) { + return 'is' . $name; + } + } + throw new \Exception("Could not determine a getter for `$name` of class `{$class->getNamespaceName()}`"); } @@ -298,6 +309,14 @@ protected function guessSetter(\ReflectionClass $class, $name): string return 'set' . ucfirst($name); } + // if there are underscores in the name convert them to CamelCase + if (strpos($name, '_')) { + $name = Caser::camel($name); + if ($class->hasMethod('set' . ucfirst($name))) { + return 'set' . $name; + } + } + throw new \Exception("Could not determine a setter for `$name` of class `{$class->getNamespaceName()}`"); } From ef8bea06afabee06a3d158b0b36b8e2c786dfc37 Mon Sep 17 00:00:00 2001 From: Christoph Singer Date: Fri, 29 Nov 2019 11:42:30 +0100 Subject: [PATCH 10/17] Added support for fields of type `date` - `type` annotation property included in metadata - Support for DateTime conversion in Converter::normalize and Converter::denormalize - added test --- Mapping/Converter.php | 8 +++++++- Mapping/DocumentParser.php | 9 +++++++-- Tests/Functional/Result/PersistObjectsTest.php | 3 +++ Tests/app/src/Document/DummyDocument.php | 17 +++++++++++++++++ 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Mapping/Converter.php b/Mapping/Converter.php index 3b022d32..c5f7eb5c 100644 --- a/Mapping/Converter.php +++ b/Mapping/Converter.php @@ -60,9 +60,12 @@ protected function normalize($document, $metadata = null) $result[$field][] = $this->normalize($item, $fieldMeta['sub_properties']); } } else { - $result[$field] = $this->normalize($item, $fieldMeta['sub_properties']); + $result[$field] = $this->normalize($value, $fieldMeta['sub_properties']); } } else { + if ($value instanceof \DateTime) { + $value = $value->format(\DateTimeInterface::ISO8601); + } $result[$field] = $value; } } @@ -89,6 +92,9 @@ protected function denormalize(array $raw, string $namespace) $object->$setter($iterator); } } else { + if ($fieldMeta['type'] == 'date') { + $value = \DateTime::createFromFormat(\DateTimeInterface::ISO8601, $value); + } if ($fieldMeta['public']) { $object->{$fieldMeta['name']} = $value; } else { diff --git a/Mapping/DocumentParser.php b/Mapping/DocumentParser.php index a390f3d6..a96768f7 100644 --- a/Mapping/DocumentParser.php +++ b/Mapping/DocumentParser.php @@ -207,6 +207,7 @@ public function getPropertyMetadata(\ReflectionClass $class, bool $subClass = fa 'identifier' => false, 'class' => null, 'embeded' => false, + 'type' => null, 'public' => $property->isPublic(), 'getter' => null, 'setter' => null, @@ -220,8 +221,6 @@ public function getPropertyMetadata(\ReflectionClass $class, bool $subClass = fa $propertyMetadata['getter'] = $this->guessGetter($class, $name); } - $fieldMapping = $annotation->getSettings(); - if ($annotation instanceof Id) { $propertyMetadata['identifier'] = true; } else { @@ -230,6 +229,12 @@ public function getPropertyMetadata(\ReflectionClass $class, bool $subClass = fa } } + if ($annotation instanceof Property) { + // we need the type (and possibly settings?) in Converter::denormalize() + $propertyMetadata['type'] = $annotation->type; + $propertyMetadata['settings'] = $annotation->settings; + } + if ($annotation instanceof Embedded) { $propertyMetadata['embeded'] = true; $propertyMetadata['class'] = $annotation->class; diff --git a/Tests/Functional/Result/PersistObjectsTest.php b/Tests/Functional/Result/PersistObjectsTest.php index 951e4c6c..2a4716cb 100644 --- a/Tests/Functional/Result/PersistObjectsTest.php +++ b/Tests/Functional/Result/PersistObjectsTest.php @@ -39,11 +39,14 @@ public function testPersistObject() $nested->value = 'delta'; $document->getNestedCollection()->add($nested); + $document->setDatetimefield(new \DateTime('2010-01-01 10:10:56')); $index->persist($document); $index->commit(); $document = $index->find(5); $this->assertEquals('bar bar', $document->title); + $this->assertInstanceOf(\DateTimeInterface::class, $document->getDatetimefield()); + $this->assertEquals('2010-01-01', $document->getDatetimefield()->format('Y-m-d')); } public function testAddingValuesToPrivateIdsWithoutSetters() diff --git a/Tests/app/src/Document/DummyDocument.php b/Tests/app/src/Document/DummyDocument.php index 111559d3..be26d977 100644 --- a/Tests/app/src/Document/DummyDocument.php +++ b/Tests/app/src/Document/DummyDocument.php @@ -69,6 +69,12 @@ class DummyDocument */ private $objectCollection; + /** + * @var \DateTimeInterface + * @ES\Property(type="date") + */ + private $datetimefield; + public function __construct() { $this->nestedCollection = new ArrayCollection(); @@ -107,4 +113,15 @@ public function setObjectCollection($objectCollection) $this->objectCollection = $objectCollection; return $this; } + + public function getDatetimefield(): ?\DateTimeInterface + { + return $this->datetimefield; + } + + public function setDatetimefield(\DateTimeInterface $datetimefield): void + { + $this->datetimefield = $datetimefield; + } + } From 7b8cca15d4dad72ee2a4534fc5037dbd8c9cf983 Mon Sep 17 00:00:00 2001 From: Christoph Singer Date: Fri, 29 Nov 2019 15:07:05 +0100 Subject: [PATCH 11/17] compatibility with PHP 7.1 --- Mapping/Converter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mapping/Converter.php b/Mapping/Converter.php index c5f7eb5c..50cbacdb 100644 --- a/Mapping/Converter.php +++ b/Mapping/Converter.php @@ -64,7 +64,7 @@ protected function normalize($document, $metadata = null) } } else { if ($value instanceof \DateTime) { - $value = $value->format(\DateTimeInterface::ISO8601); + $value = $value->format(\DateTime::ISO8601); } $result[$field] = $value; } @@ -93,7 +93,7 @@ protected function denormalize(array $raw, string $namespace) } } else { if ($fieldMeta['type'] == 'date') { - $value = \DateTime::createFromFormat(\DateTimeInterface::ISO8601, $value); + $value = \DateTime::createFromFormat(\DateTime::ISO8601, $value); } if ($fieldMeta['public']) { $object->{$fieldMeta['name']} = $value; From 5e440a95e0d65dd8b3f0959b7b15c9bcdb17759f Mon Sep 17 00:00:00 2001 From: Konstantin Myakshin Date: Mon, 30 Dec 2019 10:57:00 +0200 Subject: [PATCH 12/17] Remove dependency from symfony/templating (#905) --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index 8526765d..f9cff7b2 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,6 @@ "symfony/dependency-injection": "^3.4|^4.1", "symfony/console": "^3.4|^4.1", "symfony/stopwatch": "^3.4|^4.1", - "symfony/templating": "^3.4|^4.1", "symfony/finder": "^3.4|^4.1", "symfony/serializer": "^3.4|^4.1", "symfony/cache": "^3.4|^4.1", From e0b93a30655561067b6cb0ae20a89be338c72df6 Mon Sep 17 00:00:00 2001 From: Christoph Singer Date: Mon, 30 Dec 2019 09:57:42 +0100 Subject: [PATCH 13/17] Set date field value to NULL from previous FALSE (#898) * Set date field value to NULL from previous FALSE * PHP 7.1 compatibility, again --- Mapping/Converter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mapping/Converter.php b/Mapping/Converter.php index 50cbacdb..6778c0f6 100644 --- a/Mapping/Converter.php +++ b/Mapping/Converter.php @@ -93,7 +93,7 @@ protected function denormalize(array $raw, string $namespace) } } else { if ($fieldMeta['type'] == 'date') { - $value = \DateTime::createFromFormat(\DateTime::ISO8601, $value); + $value = \DateTime::createFromFormat(\DateTime::ISO8601, $value) ?: null; } if ($fieldMeta['public']) { $object->{$fieldMeta['name']} = $value; From dd323e3ef4b4791f52d9b0f26349140d471134be Mon Sep 17 00:00:00 2001 From: Christoph Singer Date: Mon, 30 Dec 2019 09:58:11 +0100 Subject: [PATCH 14/17] Fix index configuration (#897) --- DependencyInjection/Configuration.php | 1 + 1 file changed, 1 insertion(+) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index f73b1bd1..bc2c665b 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -68,6 +68,7 @@ public function getConfigTreeBuilder() ->arrayNode('indexes') ->defaultValue([]) + ->useAttributeAsKey('namespace') ->info( 'In case you want to override index settings defined in the annotation.' . ' e.g. use env variables instead.' From 1cc5c65af694ed90ed9a635d73790c80a9fc5a88 Mon Sep 17 00:00:00 2001 From: Christoph Singer Date: Mon, 30 Dec 2019 09:59:20 +0100 Subject: [PATCH 15/17] do not remove fields with falsy values while persisting (#896) * do not remove fields with falsy values while persisting * CS Fix --- Service/IndexService.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Service/IndexService.php b/Service/IndexService.php index e65b61ec..a9cc924f 100644 --- a/Service/IndexService.php +++ b/Service/IndexService.php @@ -431,7 +431,10 @@ public function bulk(string $operation, array $data = [], $autoCommit = true): a */ public function persist($document): void { - $documentArray = array_filter($this->converter->convertDocumentToArray($document)); + $documentArray = array_filter($this->converter->convertDocumentToArray($document), function ($val) { + // remove unset properties but keep other falsy values + return !($val === null); + }); $this->bulk('index', $documentArray); } From 9a9b81510348ba086117ddc92173d46eb9743f22 Mon Sep 17 00:00:00 2001 From: Christoph Singer Date: Mon, 30 Dec 2019 09:59:47 +0100 Subject: [PATCH 16/17] Fix "fields" annotation (#894) * Fix "fields" annotation * Bugfix: correct handling of `normalizer` in analysis config * Better unit test for DocumentParser tests `fields` mapping and `normalizer` settings --- Mapping/DocumentParser.php | 12 ++- Tests/Unit/Mapping/DocumentParserTest.php | 98 ++++++++++++++++++++++- Tests/app/src/Document/DummyDocument.php | 8 +- Tests/app/src/Document/TestDocument.php | 44 ++++++++++ 4 files changed, 155 insertions(+), 7 deletions(-) create mode 100644 Tests/app/src/Document/TestDocument.php diff --git a/Mapping/DocumentParser.php b/Mapping/DocumentParser.php index a30cc6c3..b929bce2 100644 --- a/Mapping/DocumentParser.php +++ b/Mapping/DocumentParser.php @@ -151,6 +151,9 @@ private function getClassMetadata(\ReflectionClass $class): array if ($annotation instanceof Property) { $fieldMapping['type'] = $annotation->type; + if ($annotation->fields) { + $fieldMapping['fields'] = $annotation->fields; + } $fieldMapping['analyzer'] = $annotation->analyzer; $fieldMapping['search_analyzer'] = $annotation->searchAnalyzer; $fieldMapping['search_quote_analyzer'] = $annotation->searchQuoteAnalyzer; @@ -267,7 +270,14 @@ public function getAnalysisConfig(\ReflectionClass $class): array } } - foreach (['tokenizer', 'filter', 'normalizer', 'char_filter'] as $type) { + $normalizers = $this->getListFromArrayByKey('normalizer', $mapping); + foreach ($normalizers as $normalizer) { + if (isset($this->analysisConfig['normalizer'][$normalizer])) { + $config['normalizer'][$normalizer] = $this->analysisConfig['normalizer'][$normalizer]; + } + } + + foreach (['tokenizer', 'filter', 'char_filter'] as $type) { $list = $this->getListFromArrayByKey($type, $config); foreach ($list as $listItem) { diff --git a/Tests/Unit/Mapping/DocumentParserTest.php b/Tests/Unit/Mapping/DocumentParserTest.php index 48fd6067..d6d6d501 100644 --- a/Tests/Unit/Mapping/DocumentParserTest.php +++ b/Tests/Unit/Mapping/DocumentParserTest.php @@ -13,9 +13,12 @@ use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Cache\Cache; +use ONGR\App\Document\DummyDocument; +use ONGR\App\Document\TestDocument; use ONGR\App\Entity\DummyDocumentInTheEntityDirectory; use ONGR\ElasticsearchBundle\Mapping\DocumentParser; use PHPUnit\Framework\TestCase; +use Symfony\Component\Yaml\Yaml; class DocumentParserTest extends TestCase { @@ -23,7 +26,6 @@ public function testDocumentParsing() { $parser = new DocumentParser(new AnnotationReader(), $this->createMock(Cache::class)); - ; $indexMetadata = $parser->getIndexMetadata(new \ReflectionClass(DummyDocumentInTheEntityDirectory::class)); @@ -41,4 +43,98 @@ public function testDocumentParsing() $this->assertEquals($expected, $indexMetadata); } + + public function testParsingWithMultiFieldsMapping() + { + $parser = new DocumentParser(new AnnotationReader(), $this->createMock(Cache::class)); + + $indexMetadata = $parser->getIndexMetadata(new \ReflectionClass(TestDocument::class)); + + // Mapping definition for field "title" should be there + $this->assertNotEmpty($indexMetadata['mappings']['_doc']['properties']['title']); + $title_field_def = $indexMetadata['mappings']['_doc']['properties']['title']; + + // title should have `fields` sub-array + $this->assertArrayHasKey('fields', $title_field_def); + + // `fields` should look like so: + $expected = [ + 'raw' => ['type' => 'keyword'], + 'increment' => ['type' => 'text', 'analyzer' => 'incrementalAnalyzer'], + 'sorting' => ['type' => 'keyword', 'normalizer' => 'lowercase_normalizer'] + ]; + + $this->assertEquals($expected, $title_field_def['fields']); + } + + public function testGetAnalysisConfig() + { + // Global analysis settings used for this test, usually set in the bundle configuration + // sets custom analyzer, filter, and normalizer + $config_analysis = [ + 'analyzer' => [ + 'incrementalAnalyzer' => [ + 'type' => 'custom', + 'tokenizer' => 'standard', + 'filter' => [ + 0 => 'lowercase', + 1 => 'edge_ngram_filter', + ], + ], + 'unusedAnalyzer' => [ + 'type' => 'custom', + 'tokenizer' => 'standard' + ] + ], + 'filter' => [ + 'edge_ngram_filter' => [ + 'type' => 'edge_ngram', + 'min_gram' => 1, + 'max_gram' => 20, + ], + ], + 'normalizer' => [ + 'lowercase_normalizer' => [ + 'type' => 'custom', + 'filter' => ['lowercase'] + ], + 'unused_normalizer' => [ + 'type' => 'custom' + ] + ] + ]; + + $parser = new DocumentParser(new AnnotationReader(), $this->createMock(Cache::class), $config_analysis); + $analysis = $parser->getAnalysisConfig(new \ReflectionClass(TestDocument::class)); + + $expected = [ + 'analyzer' => [ + 'incrementalAnalyzer' => [ + 'type' => 'custom', + 'tokenizer' => 'standard', + 'filter' => [ + 0 => 'lowercase', + 1 => 'edge_ngram_filter', + ], + ], + ], + // 'unusedAnalyzer' must not be there because it is not used + 'filter' => [ + 'edge_ngram_filter' => [ + 'type' => 'edge_ngram', + 'min_gram' => 1, + 'max_gram' => 20, + ], + ], + 'normalizer' => [ + 'lowercase_normalizer' => [ + 'type' => 'custom', + 'filter' => ['lowercase'] + ] + // 'unused_normalizer' must not be there + ] + ]; + + $this->assertEquals($expected, $analysis); + } } diff --git a/Tests/app/src/Document/DummyDocument.php b/Tests/app/src/Document/DummyDocument.php index be26d977..5fa0ecec 100644 --- a/Tests/app/src/Document/DummyDocument.php +++ b/Tests/app/src/Document/DummyDocument.php @@ -39,11 +39,9 @@ class DummyDocument * @ES\Property( * type="text", * name="title", - * settings={ - * "fields"={ - * "raw"={"type"="keyword"}, - * "increment"={"type"="text", "analyzer"="incrementalAnalyzer"} - * } + * fields={ + * "raw"={"type"="keyword"}, + * "increment"={"type"="text", "analyzer"="incrementalAnalyzer"} * } * ) */ diff --git a/Tests/app/src/Document/TestDocument.php b/Tests/app/src/Document/TestDocument.php new file mode 100644 index 00000000..9518ed79 --- /dev/null +++ b/Tests/app/src/Document/TestDocument.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ONGR\App\Document; + +use Doctrine\Common\Collections\ArrayCollection; +use ONGR\ElasticsearchBundle\Annotation as ES; + +/** + * test document for unit testing of DocumentParser class + * + * @ES\Index(alias="testdocument") + */ +class TestDocument +{ + // This con't is only as a helper. + CONST INDEX_NAME = 'testdocument'; + + /** + * @ES\Id() + */ + public $id; + + /** + * @ES\Property( + * type="text", + * name="title", + * fields={ + * "raw"={"type"="keyword"}, + * "increment"={"type"="text", "analyzer"="incrementalAnalyzer"}, + * "sorting"={"type"="keyword", "normalizer"="lowercase_normalizer"} + * } + * ) + */ + public $title; +} From c9f626c30fe28db633302c56d7815fac7a374c3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simonas=20=C5=A0erlinskas?= Date: Mon, 30 Dec 2019 11:12:23 +0200 Subject: [PATCH 17/17] update dev version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f9cff7b2..988b1e0a 100644 --- a/composer.json +++ b/composer.json @@ -55,7 +55,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "6.0-dev" + "dev-master": "6.1-dev" } } }