Skip to content

Commit 29b9008

Browse files
einorlersaimaz
authored andcommitted
Separate dir mapping fix (#765)
* updated the entity products * updated a functional test * implemented guessing the dir name in parser * fixed getRepository method in manager * implemented document dir handling in finder * implemented dynamically setting the default dir name * updated the test entities to fit the document structure
1 parent 2ed93a2 commit 29b9008

File tree

8 files changed

+152
-25
lines changed

8 files changed

+152
-25
lines changed

DependencyInjection/Compiler/MappingPass.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ public function process(ContainerBuilder $container)
6666
'ONGR\ElasticsearchBundle\Service\Repository',
6767
[$repositoryDetails['namespace']]
6868
);
69+
70+
if (isset($repositoryDetails['directory_name']) && $managerName == 'default') {
71+
$container->get('es.document_finder')->setDocumentDir($repositoryDetails['directory_name']);
72+
}
73+
6974
$repositoryDefinition->setFactory(
7075
[
7176
new Reference(sprintf('es.manager.%s', $managerName)),

Mapping/DocumentFinder.php

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class DocumentFinder
2424
/**
2525
* @var string Directory in bundle to load documents from.
2626
*/
27-
const DOCUMENT_DIR = 'Document';
27+
private $documentDir;
2828

2929
/**
3030
* Constructor.
@@ -33,9 +33,26 @@ class DocumentFinder
3333
*/
3434
public function __construct(array $bundles)
3535
{
36+
$this->documentDir = 'Document';
3637
$this->bundles = $bundles;
3738
}
3839

40+
/**
41+
* @return string
42+
*/
43+
public function getDocumentDir()
44+
{
45+
return $this->documentDir;
46+
}
47+
48+
/**
49+
* @param string $documentDir
50+
*/
51+
public function setDocumentDir($documentDir)
52+
{
53+
$this->documentDir = $documentDir;
54+
}
55+
3956
/**
4057
* Formats namespace from short syntax.
4158
*
@@ -47,12 +64,28 @@ public function __construct(array $bundles)
4764
public function getNamespace($namespace, $documentsDirectory = null)
4865
{
4966
if (!$documentsDirectory) {
50-
$documentsDirectory = self::DOCUMENT_DIR;
67+
$documentsDirectory = $this->documentDir;
5168
}
5269

5370
if (strpos($namespace, ':') !== false) {
5471
list($bundle, $document) = explode(':', $namespace);
5572
$bundle = $this->getBundleClass($bundle);
73+
74+
// If bundle has a sub-namespace it needs to be replaced
75+
if (strpos($documentsDirectory, '\\')) {
76+
$bundleSubNamespace = substr(
77+
$bundle,
78+
$start = strpos($bundle, '\\') + 1,
79+
strrpos($bundle, '\\') - $start + 1
80+
);
81+
82+
$documentsDirectory = str_replace(
83+
$bundleSubNamespace,
84+
'',
85+
$documentsDirectory
86+
);
87+
}
88+
5689
$namespace = substr($bundle, 0, strrpos($bundle, '\\')) . '\\' .
5790
$documentsDirectory . '\\' . $document;
5891
}
@@ -97,7 +130,7 @@ public function getBundleClass($name)
97130
public function getBundleDocumentClasses($bundle, $documentsDirectory = null)
98131
{
99132
if (!$documentsDirectory) {
100-
$documentsDirectory = self::DOCUMENT_DIR;
133+
$documentsDirectory = $this->documentDir;
101134
}
102135

103136
$bundleReflection = new \ReflectionClass($this->getBundleClass($bundle));

Mapping/DocumentParser.php

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,11 @@ private function getHashMapAnnotationData(\ReflectionProperty $property)
187187
* Returns meta field annotation data from reader.
188188
*
189189
* @param \ReflectionProperty $property
190+
* @param string $directory The name of the Document directory in the bundle
190191
*
191192
* @return array
192193
*/
193-
private function getMetaFieldAnnotationData($property)
194+
private function getMetaFieldAnnotationData($property, $directory)
194195
{
195196
/** @var MetaField $annotation */
196197
$annotation = $this->reader->getPropertyAnnotation($property, self::ID_ANNOTATION);
@@ -208,7 +209,7 @@ private function getMetaFieldAnnotationData($property)
208209
];
209210

210211
if ($annotation instanceof ParentDocument) {
211-
$data['settings']['type'] = $this->getDocumentType($annotation->class);
212+
$data['settings']['type'] = $this->getDocumentType($annotation->class, $directory);
212213
}
213214

214215
return $data;
@@ -235,6 +236,7 @@ private function getObjects()
235236
private function getAliases(\ReflectionClass $reflectionClass, array &$metaFields = null)
236237
{
237238
$reflectionName = $reflectionClass->getName();
239+
$directory = $this->guessDirName($reflectionClass);
238240

239241
// We skip cache in case $metaFields is given. This should not affect performance
240242
// because for each document this method is called only once. For objects it might
@@ -254,7 +256,7 @@ private function getAliases(\ReflectionClass $reflectionClass, array &$metaField
254256
$type = $type !== null ? $type : $this->getHashMapAnnotationData($property);
255257

256258
if ($type === null && $metaFields !== null
257-
&& ($metaData = $this->getMetaFieldAnnotationData($property)) !== null) {
259+
&& ($metaData = $this->getMetaFieldAnnotationData($property, $directory)) !== null) {
258260
$metaFields[$metaData['name']] = $metaData['settings'];
259261
$type = new \stdClass();
260262
$type->name = $metaData['name'];
@@ -299,11 +301,11 @@ private function getAliases(\ReflectionClass $reflectionClass, array &$metaField
299301
$alias[$type->name]['propertyType'] = $propertyType;
300302

301303
if ($type instanceof Embedded) {
302-
$child = new \ReflectionClass($this->finder->getNamespace($type->class));
304+
$child = new \ReflectionClass($this->finder->getNamespace($type->class, $directory));
303305
$alias[$type->name] = array_merge(
304306
$alias[$type->name],
305307
[
306-
'type' => $this->getObjectMapping($type->class)['type'],
308+
'type' => $this->getObjectMapping($type->class, $directory)['type'],
307309
'multiple' => $type->multiple,
308310
'aliases' => $this->getAliases($child, $metaFields),
309311
'namespace' => $child->getName(),
@@ -397,13 +399,14 @@ private function registerAnnotations()
397399
/**
398400
* Returns document type.
399401
*
400-
* @param string $document Format must be like AcmeBundle:Document.
402+
* @param string $document Format must be like AcmeBundle:Document.
403+
* @param string $directory The Document directory name of the bundle.
401404
*
402405
* @return string
403406
*/
404-
private function getDocumentType($document)
407+
private function getDocumentType($document, $directory)
405408
{
406-
$namespace = $this->finder->getNamespace($document);
409+
$namespace = $this->finder->getNamespace($document, $directory);
407410
$reflectionClass = new \ReflectionClass($namespace);
408411
$document = $this->getDocumentAnnotationData($reflectionClass);
409412

@@ -453,14 +456,16 @@ private function getDocumentPropertiesReflection(\ReflectionClass $reflectionCla
453456
private function getAnalyzers(\ReflectionClass $reflectionClass)
454457
{
455458
$analyzers = [];
459+
$directory = $this->guessDirName($reflectionClass);
460+
456461
foreach ($this->getDocumentPropertiesReflection($reflectionClass) as $name => $property) {
457462
$type = $this->getPropertyAnnotationData($property);
458463
$type = $type !== null ? $type : $this->getEmbeddedAnnotationData($property);
459464

460465
if ($type instanceof Embedded) {
461466
$analyzers = array_merge(
462467
$analyzers,
463-
$this->getAnalyzers(new \ReflectionClass($this->finder->getNamespace($type->class)))
468+
$this->getAnalyzers(new \ReflectionClass($this->finder->getNamespace($type->class, $directory)))
464469
);
465470
}
466471

@@ -499,6 +504,8 @@ private function getAnalyzers(\ReflectionClass $reflectionClass)
499504
private function getProperties(\ReflectionClass $reflectionClass, $properties = [], $flag = false)
500505
{
501506
$mapping = [];
507+
$directory = $this->guessDirName($reflectionClass);
508+
502509
/** @var \ReflectionProperty $property */
503510
foreach ($this->getDocumentPropertiesReflection($reflectionClass) as $name => $property) {
504511
$type = $this->getPropertyAnnotationData($property);
@@ -516,7 +523,7 @@ private function getProperties(\ReflectionClass $reflectionClass, $properties =
516523

517524
// Inner object
518525
if ($type instanceof Embedded) {
519-
$map = array_replace_recursive($map, $this->getObjectMapping($type->class));
526+
$map = array_replace_recursive($map, $this->getObjectMapping($type->class, $directory));
520527
}
521528

522529
// HashMap object
@@ -546,12 +553,13 @@ private function getProperties(\ReflectionClass $reflectionClass, $properties =
546553
* Loads from cache if it's already loaded.
547554
*
548555
* @param string $className
556+
* @param string $directory Name of the directory where the Document is
549557
*
550558
* @return array
551559
*/
552-
private function getObjectMapping($className)
560+
private function getObjectMapping($className, $directory)
553561
{
554-
$namespace = $this->finder->getNamespace($className);
562+
$namespace = $this->finder->getNamespace($className, $directory);
555563

556564
if (array_key_exists($namespace, $this->objects)) {
557565
return $this->objects[$namespace];
@@ -582,4 +590,18 @@ private function getObjectMapping($className)
582590

583591
return $this->objects[$namespace];
584592
}
593+
594+
/**
595+
* @param \ReflectionClass $reflection
596+
*
597+
* @return string
598+
*/
599+
private function guessDirName(\ReflectionClass $reflection)
600+
{
601+
return substr(
602+
$directory = $reflection->getName(),
603+
$start = strpos($directory, '\\') + 1,
604+
strrpos($directory, '\\') - $start
605+
);
606+
}
585607
}

Mapping/MetadataCollector.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public function getBundleMapping($name, $config = [])
117117
}
118118

119119
$mappings = [];
120-
$documentDir = isset($config['document_dir']) ? $config['document_dir'] : DocumentFinder::DOCUMENT_DIR;
120+
$documentDir = isset($config['document_dir']) ? $config['document_dir'] : $this->finder->getDocumentDir();
121121

122122
// Handle the case when single document mapping requested
123123
// Usage od ":" in name is deprecated. This if is only for BC.
@@ -356,11 +356,12 @@ public function getMapping($namespace)
356356
* Returns fully qualified class name.
357357
*
358358
* @param string $className
359+
* @param string $directory The name of the directory
359360
*
360361
* @return string
361362
*/
362-
public function getClassName($className)
363+
public function getClassName($className, $directory = null)
363364
{
364-
return $this->finder->getNamespace($className);
365+
return $this->finder->getNamespace($className, $directory);
365366
}
366367
}

Service/Manager.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,17 @@ public function getRepository($className)
183183
throw new \InvalidArgumentException('Document class must be a string.');
184184
}
185185

186-
$namespace = $this->getMetadataCollector()->getClassName($className);
186+
$directory = null;
187+
188+
if (strpos($className, ':')) {
189+
$bundle = explode(':', $className)[0];
190+
191+
if (isset($this->config['mappings'][$bundle]['document_dir'])) {
192+
$directory = $this->config['mappings'][$bundle]['document_dir'];
193+
}
194+
}
195+
196+
$namespace = $this->getMetadataCollector()->getClassName($className, $directory);
187197

188198
if (isset($this->repositories[$namespace])) {
189199
return $this->repositories[$namespace];

Tests/Functional/Service/ManagerTest.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -340,16 +340,22 @@ public function testCustomManagerWithCustomMappingDir()
340340
{
341341
$manager = $this->getManager('custom_dir');
342342

343+
$category = new \ONGR\ElasticsearchBundle\Tests\app\fixture\TestBundle\Entity\CategoryObject();
344+
$category->title = 'foo';
343345
$product = new \ONGR\ElasticsearchBundle\Tests\app\fixture\TestBundle\Entity\Product();
344-
$product->setId('custom');
345-
$product->setTitle('Custom product');
346+
$product->id = 'custom';
347+
$product->title = 'Custom product';
348+
$product->categories[] = $category;
346349
$manager->persist($product);
347350
$manager->commit();
348351

349352
$repo = $manager->getRepository('TestBundle:Product');
353+
354+
$this->assertEquals(get_class($product), $repo->getClassName());
355+
350356
/** @var \ONGR\ElasticsearchBundle\Tests\app\fixture\TestBundle\Entity\Product $actualProduct */
351-
$actualProduct = $repo->find('custom');
357+
$actualProduct = $repo->findOneBy(['categories.title' => 'foo']);
352358

353-
$this->assertEquals('Custom product', $actualProduct->getTitle());
359+
$this->assertEquals('Custom product', $actualProduct->title);
354360
}
355361
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the ONGR package.
5+
*
6+
* (c) NFQ Technologies UAB <info@nfq.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace ONGR\ElasticsearchBundle\Tests\app\fixture\TestBundle\Entity;
13+
14+
use ONGR\ElasticsearchBundle\Annotation as ES;
15+
16+
/**
17+
* @ES\Object
18+
*/
19+
class CategoryObject
20+
{
21+
/**
22+
* @var string
23+
* @ES\Property(type="text", options={"index"="not_analyzed"})
24+
*/
25+
public $title;
26+
}

Tests/app/fixture/TestBundle/Entity/Product.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,37 @@
1212
namespace ONGR\ElasticsearchBundle\Tests\app\fixture\TestBundle\Entity;
1313

1414
use ONGR\ElasticsearchBundle\Annotation as ES;
15-
use ONGR\ElasticsearchBundle\Tests\app\fixture\TestBundle\Document\Product as BaseProduct;
15+
use ONGR\ElasticsearchBundle\Collection\Collection;
1616

1717
/**
1818
* Product document for testing.
1919
*
2020
* @ES\Document()
2121
*/
22-
class Product extends BaseProduct
22+
class Product
2323
{
24+
/**
25+
* @var string
26+
*
27+
* @ES\Id()
28+
*/
29+
public $id;
30+
31+
/**
32+
* @var string
33+
* @ES\Property(type="keyword", name="title")
34+
*/
35+
public $title;
36+
37+
/**
38+
* @var CategoryObject[]
39+
*
40+
* @ES\Embedded(class="TestBundle:CategoryObject", multiple=true)
41+
*/
42+
public $categories;
43+
44+
public function __construct()
45+
{
46+
$this->categories = new Collection();
47+
}
2448
}

0 commit comments

Comments
 (0)