Skip to content

Commit

Permalink
Added support for 'enumType' property option on entities having an enum
Browse files Browse the repository at this point in the history
value.
  • Loading branch information
pmishev committed Nov 11, 2024
1 parent 399224d commit 50fffdd
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 59 deletions.
4 changes: 3 additions & 1 deletion src/Annotation/Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ final class Property implements PropertyAnnotationInterface, DumperInterface
*/
public string $type;

public ?string $enumType = null;

public bool $multilanguage = false;

/**
Expand All @@ -37,7 +39,7 @@ final class Property implements PropertyAnnotationInterface, DumperInterface
/**
* The object name must be defined, if type is 'object' or 'nested'
*/
public string $objectName;
public ?string $objectName = null;

/**
* Defines if related object will have one or multiple values.
Expand Down
12 changes: 9 additions & 3 deletions src/Mapping/DocumentParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,12 @@ public function getPropertiesMetadata(\ReflectionClass $documentReflection): arr
switch ($propertyAnnotation::class) {
case Property::class:
$propertyMetadata[$propertyAnnotation->name] = [
'propertyName' => $propertyName,
'type' => $propertyAnnotation->type,
'multilanguage' => $propertyAnnotation->multilanguage,
'propertyName' => $propertyName,
'type' => $propertyAnnotation->type,
];
if ($propertyAnnotation->multilanguage) {
$propertyMetadata[$propertyAnnotation->name]['multilanguage'] = true;
}

// If property is a (nested) object
if (\in_array($propertyAnnotation->type, ['object', 'nested'])) {
Expand All @@ -122,6 +124,10 @@ public function getPropertiesMetadata(\ReflectionClass $documentReflection): arr
'className' => $child->getName(),
]
);
} else {
if (null !== $propertyAnnotation->enumType) {
$propertyMetadata[$propertyAnnotation->name]['enumType'] = $propertyAnnotation->enumType;
}
}
break;

Expand Down
4 changes: 3 additions & 1 deletion src/Result/DocumentConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ public function assignArrayToObject(array $array, ObjectInterface $object, array
continue;
}

if (\in_array($propertyMetadata['type'], ['string', 'keyword', 'text']) && !empty($propertyMetadata['multilanguage'])) {
if (!empty($propertyMetadata['enumType'])) {
$objectValue = $propertyMetadata['enumType']::from($array[$esField]);
} elseif (\in_array($propertyMetadata['type'], ['string', 'keyword', 'text']) && !empty($propertyMetadata['multilanguage'])) {
$objectValue = null;
foreach ($array as $fieldName => $value) {
$prefixLength = \strlen($esField.$this->languageSeparator);
Expand Down
16 changes: 12 additions & 4 deletions tests/App/fixture/Acme/FooBundle/Document/Customer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Sineflow\ElasticsearchBundle\Annotation as ES;
use Sineflow\ElasticsearchBundle\Document\AbstractDocument;
use Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Document\Provider\CustomerProvider;
use Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Enum\CustomerTypeEnum;

/**
* @ES\Document(
Expand All @@ -16,15 +17,22 @@ class Customer extends AbstractDocument
/**
* Test adding raw mapping.
*
* @var string
*
* @ES\Property(name="name", type="keyword")
*/
public $name;
public string $name;

/**
* @var bool
* Test adding raw mapping.
*
* @ES\Property(
* name="customer_type",
* type="integer",
* enumType=Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Enum\CustomerTypeEnum::class
* )
*/
public ?CustomerTypeEnum $customerType = null;

/**
* @ES\Property(name="active", type="boolean")
*/
private $active;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Document;

use Sineflow\ElasticsearchBundle\Annotation as ES;
use Sineflow\ElasticsearchBundle\Document\AbstractDocument;
use Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Enum\CustomerTypeEnum;

/**
* @ES\Document
*/
class EntityWithInvalidEnum extends AbstractDocument
{
/**
* @ES\Property(
* name="enum_test",
* type="string",
* enumType=nonExistingEnumClass
* )
*/
public ?CustomerTypeEnum $enumTest = null;
}
9 changes: 9 additions & 0 deletions tests/App/fixture/Acme/FooBundle/Enum/CustomerTypeEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Enum;

enum CustomerTypeEnum: int
{
case INDIVIDUAL = 1;
case COMPANY = 2;
}
55 changes: 44 additions & 11 deletions tests/Functional/Finder/FinderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Sineflow\ElasticsearchBundle\Tests\AbstractElasticsearchTestCase;
use Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\BarBundle\Document\Product;
use Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Document\Customer;
use Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Enum\CustomerTypeEnum;

/**
* Class FinderTest
Expand Down Expand Up @@ -39,10 +40,17 @@ protected function getDataArray()
],
'customer' => [
[
'_id' => 111,
'name' => 'Jane Doe',
'title' => 'aaa bbb',
'active' => true,
'_id' => 111,
'name' => 'Jane Doe',
'title' => 'aaa bbb',
'active' => true,
'customer_type' => CustomerTypeEnum::COMPANY, // When php-elasticsearch serializes the request, json_encode will convert this to a scalar value
],
[
'_id' => 222,
'name' => 'John Doe',
'title' => 'bbb',
'customer_type' => 1,
],
],
];
Expand Down Expand Up @@ -153,22 +161,47 @@ public function testFindInMultipleTypesAndIndices(): void
'title' => 'bbb',
],
],
'sort' => [
'_id' => 'asc',
],
];

$res = $finder->find(['AcmeBarBundle:Product', 'AcmeFooBundle:Customer'], $searchBody, Finder::RESULTS_OBJECT, [], $totalHits);
$this->assertInstanceOf(DocumentIterator::class, $res);
$this->assertCount(2, $res);
$this->assertEquals(2, $totalHits);
$this->assertCount(3, $res);
$this->assertEquals(3, $totalHits);
$resAsArray = iterator_to_array($res);

$this->assertInstanceOf(Customer::class, $resAsArray[0]);
$this->assertInstanceOf(Customer::class, $resAsArray[1]);
$this->assertInstanceOf(Product::class, $resAsArray[2]);

$this->assertEquals(111, $resAsArray[0]->id);
$this->assertSame('Jane Doe', $resAsArray[0]->name);
$this->assertSame(CustomerTypeEnum::COMPANY, $resAsArray[0]->customerType);

$this->assertEquals(222, $resAsArray[1]->id);
$this->assertSame('John Doe', $resAsArray[1]->name);
$this->assertSame(CustomerTypeEnum::INDIVIDUAL, $resAsArray[1]->customerType);

$this->assertSame('doc2', $resAsArray[2]->id);
$this->assertSame('bbb', $resAsArray[2]->title);

$res = $finder->find(['AcmeBarBundle:Product', 'AcmeFooBundle:Customer'], $searchBody, Finder::RESULTS_ARRAY);
$this->assertArraySubset([
'doc2' => [
'title' => 'bbb',
],
111 => [
'name' => 'Jane Doe',
'title' => 'aaa bbb',
'active' => true,
'name' => 'Jane Doe',
'title' => 'aaa bbb',
'active' => true,
'customer_type' => 2,
],
222 => [
'name' => 'John Doe',
'title' => 'bbb',
'customer_type' => 1,
],
], $res);

Expand Down Expand Up @@ -214,8 +247,8 @@ public function testCount(): void
],
];

$this->assertEquals(1, $finder->count(['AcmeFooBundle:Customer'], $searchBody));
$this->assertEquals(2, $finder->count(['AcmeBarBundle:Product', 'AcmeFooBundle:Customer'], $searchBody));
$this->assertEquals(2, $finder->count(['AcmeFooBundle:Customer'], $searchBody));
$this->assertEquals(3, $finder->count(['AcmeBarBundle:Product', 'AcmeFooBundle:Customer'], $searchBody));
}

public function testGetTargetIndices(): void
Expand Down
35 changes: 13 additions & 22 deletions tests/Functional/Mapping/DocumentMetadataCollectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\BarBundle\Document\Repository\ProductRepository;
use Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Document\Customer;
use Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Document\Provider\CustomerProvider;
use Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Enum\CustomerTypeEnum;
use Symfony\Contracts\Cache\CacheInterface;

/**
Expand Down Expand Up @@ -41,21 +42,28 @@ class DocumentMetadataCollectorTest extends AbstractContainerAwareTestCase
'active' => [
'type' => 'boolean',
],
'customer_type' => [
'type' => 'integer',
],
],
'fields' => [
],
'propertiesMetadata' => [
'name' => [
'propertyName' => 'name',
'type' => 'keyword',
'multilanguage' => null,
'propertyAccess' => 1,
],
'customer_type' => [
'propertyName' => 'customerType',
'type' => 'integer',
'enumType' => CustomerTypeEnum::class,
'propertyAccess' => 1,
],
'active' => [
'propertyName' => 'active',
'type' => 'boolean',
'multilanguage' => null,
'methods' => [
'propertyName' => 'active',
'type' => 'boolean',
'methods' => [
'getter' => 'isActive',
'setter' => 'setActive',
],
Expand Down Expand Up @@ -190,43 +198,36 @@ class DocumentMetadataCollectorTest extends AbstractContainerAwareTestCase
'title' => [
'propertyName' => 'title',
'type' => 'text',
'multilanguage' => null,
'propertyAccess' => 1,
],
'description' => [
'propertyName' => 'description',
'type' => 'text',
'multilanguage' => null,
'propertyAccess' => 1,
],
'category' => [
'propertyName' => 'category',
'type' => 'object',
'multilanguage' => null,
'multiple' => null,
'propertiesMetadata' => [
'id' => [
'propertyName' => 'id',
'type' => 'integer',
'multilanguage' => null,
'propertyAccess' => 1,
],
'title' => [
'propertyName' => 'title',
'type' => 'keyword',
'multilanguage' => null,
'propertyAccess' => 1,
],
'tags' => [
'propertyName' => 'tags',
'type' => 'object',
'multilanguage' => null,
'multiple' => true,
'propertiesMetadata' => [
'tagname' => [
'propertyName' => 'tagName',
'type' => 'text',
'multilanguage' => null,
'propertyAccess' => 1,
],
],
Expand All @@ -240,31 +241,26 @@ class DocumentMetadataCollectorTest extends AbstractContainerAwareTestCase
'related_categories' => [
'propertyName' => 'relatedCategories',
'type' => 'object',
'multilanguage' => null,
'multiple' => true,
'propertiesMetadata' => [
'id' => [
'propertyName' => 'id',
'type' => 'integer',
'multilanguage' => null,
'propertyAccess' => 1,
],
'title' => [
'propertyName' => 'title',
'type' => 'keyword',
'multilanguage' => null,
'propertyAccess' => 1,
],
'tags' => [
'propertyName' => 'tags',
'type' => 'object',
'multilanguage' => null,
'multiple' => true,
'propertiesMetadata' => [
'tagname' => [
'propertyName' => 'tagName',
'type' => 'text',
'multilanguage' => null,
'propertyAccess' => 1,
],
],
Expand All @@ -278,25 +274,21 @@ class DocumentMetadataCollectorTest extends AbstractContainerAwareTestCase
'price' => [
'propertyName' => 'price',
'type' => 'float',
'multilanguage' => null,
'propertyAccess' => 1,
],
'location' => [
'propertyName' => 'location',
'type' => 'geo_point',
'multilanguage' => null,
'propertyAccess' => 1,
],
'limited' => [
'propertyName' => 'limited',
'type' => 'boolean',
'multilanguage' => null,
'propertyAccess' => 1,
],
'released' => [
'propertyName' => 'released',
'type' => 'date',
'multilanguage' => null,
'propertyAccess' => 1,
],
'ml_info' => [
Expand All @@ -314,7 +306,6 @@ class DocumentMetadataCollectorTest extends AbstractContainerAwareTestCase
'pieces_count' => [
'propertyName' => 'tokenPiecesCount',
'type' => 'text',
'multilanguage' => null,
'propertyAccess' => 1,
],
'_id' => [
Expand Down
Loading

0 comments on commit 50fffdd

Please sign in to comment.