Completed
Push — master ( bd1580...0ea8fb )
by Florian
09:56
created

EntityToDocumentMapper::getSearchService()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
declare(strict_types=1);
3
4
/*
5
 * This file is part of the Stinger Entity Search package.
6
 *
7
 * (c) Oliver Kotte <[email protected]>
8
 * (c) Florian Meyer <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
namespace StingerSoft\EntitySearchBundle\Services\Mapping;
14
15
use StingerSoft\EntitySearchBundle\Model\SearchableEntity;
16
use Doctrine\Common\Persistence\ObjectManager;
17
use StingerSoft\EntitySearchBundle\Model\Document;
18
use Symfony\Component\PropertyAccess\PropertyAccess;
19
use StingerSoft\EntitySearchBundle\Services\SearchService;
20
21
/**
22
 * Handles the creation of documents out of entities
23
 */
24
class EntityToDocumentMapper implements EntityToDocumentMapperInterface {
25
26
	/**
27
	 *
28
	 * @var SearchService
29
	 */
30
	protected $searchService;
31
32
	/**
33
	 *
34
	 * @var array
35
	 */
36
	protected $mapping = array();
37
38
	/**
39
	 *
40
	 * @var string[string]
41
	 */
42
	protected $cachedMapping = array();
43
44
	/**
45
	 * Constructor
46
	 *
47
	 * @param SearchService $searchService        	
48
	 */
49
	public function __construct(SearchService $searchService, array $mapping = array()) {
50
		$this->searchService = $searchService;
51
		foreach($mapping as $key => $config) {
52
			if(!isset($config['mappings'])) {
53
				throw new \InvalidArgumentException($key . ' has no mapping defined!');
54
			}
55
			if(!isset($config['persistence'])) {
56
				throw new \InvalidArgumentException($key . ' has no persistence defined!');
57
			}
58
			if(!isset($config['persistence']['model'])) {
59
				throw new \InvalidArgumentException($key . ' has no model defined!');
60
			}
61
			$map = array();
62
			foreach($config['mappings'] as $fieldKey => $fieldConfig) {
63
				$map[$fieldKey] = isset($fieldConfig['propertyPath']) && $fieldConfig['propertyPath'] ? $fieldConfig['propertyPath'] : $fieldKey;
64
			}
65
			
66
			$this->mapping[$config['persistence']['model']] = $map;
67
		}
68
	}
69
70
	/**
71
	 *
72
	 * {@inheritDoc}
73
	 *
74
	 * @see \StingerSoft\EntitySearchBundle\Services\Mapping\EntityToDocumentMapperInterface::isIndexable()
75
	 */
76
	public function isIndexable(object $object) : bool {
77
		if($object instanceof SearchableEntity) {
78
			return true;
79
		}
80
		if(count($this->getMapping(get_class($object))) > 0) {
81
			return true;
82
		}
83
		return false;
84
	}
85
86
	/**
87
	 *
88
	 * {@inheritDoc}
89
	 *
90
	 * @see \StingerSoft\EntitySearchBundle\Services\Mapping\EntityToDocumentMapperInterface::isClassIndexable()
91
	 * @throws \ReflectionException
92
	 */
93
	public function isClassIndexable(string $clazz) : bool {
94
		$reflectionClass = new \ReflectionClass($clazz);
95
		if(array_key_exists(SearchableEntity::class, $reflectionClass->getInterfaces())) {
96
			return true;
97
		}
98
		if(count($this->getMapping($clazz)) > 0) {
99
			return true;
100
		}
101
		return false;
102
	}
103
104
105
	/**
106
	 * {@inheritDoc}
107
	 * @see \StingerSoft\EntitySearchBundle\Services\Mapping\EntityToDocumentMapperInterface::createDocument()
108
	 */
109
	public function createDocument(ObjectManager $manager, object $object) : ?Document {
110
		if(!$this->isIndexable($object))
111
			return null;
112
		$document = $this->searchService->createEmptyDocumentFromEntity($object);
113
		$index = $this->fillDocument($document, $object);
114
		if($index === false)
115
			return null;
116
		
117
		return $document;
118
	}
119
120
	/**
121
	 * Fills the given document based on the object
122
	 *
123
	 * @param Document $document        	
124
	 * @param object $object        	
125
	 * @return boolean
126
	 */
127
	protected function fillDocument(Document $document, object $object) : bool {
128
		if($object instanceof SearchableEntity) {
129
			return $object->indexEntity($document);
130
		}
131
		$mapping = $this->getMapping(\get_class($object));
132
		$accessor = PropertyAccess::createPropertyAccessor();
133
		foreach($mapping as $fieldName => $propertyPath) {
134
			$document->addField($fieldName, $accessor->getValue($object, $propertyPath));
135
		}
136
		return true;
137
	}
138
139
	/**
140
	 * Fetches the mapping for the given object including the mapping of superclasses
141
	 *
142
	 * @return string[string]
0 ignored issues
show
Documentation introduced by
The doc-type string[string] could not be parsed: Expected "]" at position 2, but found "string". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
143
	 * @throws \ReflectionException
144
	 */
145
	protected function getMapping(string $clazz) : array {
146
		if(isset($this->cachedMapping[$clazz])) {
147
			return $this->cachedMapping[$clazz];
148
		}
149
		$ref = new \ReflectionClass($clazz);
150
		
151
		$mapping = array();
152
		
153
		foreach($this->mapping as $className => $config) {
154
			if($clazz === $className || $ref->isSubclassOf($className)) {
155
				$mapping = \array_merge($mapping, $config);
156
			}
157
		}
158
		
159
		$this->cachedMapping[$clazz] = $mapping;
160
		
161
		return $mapping;
162
	}
163
}