1313
1414use Massive \Bundle \SearchBundle \Search \Converter \ConverterManagerInterface ;
1515use Massive \Bundle \SearchBundle \Search \Metadata \FieldEvaluator ;
16+ use Massive \Bundle \SearchBundle \Search \Metadata \FieldInterface ;
1617use Massive \Bundle \SearchBundle \Search \Metadata \IndexMetadata ;
1718
1819/**
@@ -110,7 +111,14 @@ public function objectToDocument(IndexMetadata $metadata, $object)
110111 $ document ->setLocale ($ locale );
111112 }
112113
113- $ this ->populateDocument ($ document , $ object , $ fieldMapping );
114+ $ blockValues = [];
115+ $ this ->populateDocument ($ document , $ object , $ fieldMapping , $ blockValues );
116+
117+ foreach ($ blockValues as $ name => $ values ) {
118+ $ mapping = $ this ->addMappingOptions ();
119+ $ values = \implode (' ' , $ values );
120+ $ this ->addDocumentField ($ document , $ name , $ values , $ mapping , Field::TYPE_STRING );
121+ }
114122
115123 return $ document ;
116124 }
@@ -122,35 +130,23 @@ public function objectToDocument(IndexMetadata $metadata, $object)
122130 * @param Document $document
123131 * @param mixed $object
124132 * @param array $fieldMapping
133+ * @param string[] $blockValues
125134 * @param string $prefix Prefix the document field name (used when called recursively)
126135 *
127136 * @throws \InvalidArgumentException
128137 */
129- private function populateDocument ($ document , $ object , $ fieldMapping , $ prefix = '' )
130- {
131- foreach ($ fieldMapping as $ fieldName => $ mapping ) {
132- $ requiredMappings = ['field ' , 'type ' ];
133-
134- foreach ($ requiredMappings as $ requiredMapping ) {
135- if (!isset ($ mapping [$ requiredMapping ])) {
136- throw new \RuntimeException (
137- \sprintf (
138- 'Mapping for "%s" does not have "%s" key ' ,
139- \get_class ($ document ),
140- $ requiredMapping
141- )
142- );
143- }
144- }
138+ private function populateDocument (
139+ $ document ,
140+ $ object ,
141+ $ fieldMapping ,
142+ &$ blockValues = [],
143+ $ prefix = ''
144+ ) {
145+ $ isBlockScope = '' !== $ prefix ;
145146
146- $ mapping = \array_merge (
147- [
148- 'stored ' => true ,
149- 'aggregate ' => false ,
150- 'indexed ' => true ,
151- ],
152- $ mapping
153- );
147+ foreach ($ fieldMapping as $ fieldName => $ mapping ) {
148+ $ this ->hasRequiredMapping ($ document , $ mapping );
149+ $ mapping = $ this ->addMappingOptions ($ mapping );
154150
155151 if ('complex ' == $ mapping ['type ' ]) {
156152 if (!isset ($ mapping ['mapping ' ])) {
@@ -174,15 +170,25 @@ private function populateDocument($document, $object, $fieldMapping, $prefix = '
174170 $ document ,
175171 $ childObject ,
176172 $ mapping ['mapping ' ]->getFieldMapping (),
177- $ prefix . $ fieldName . $ i
173+ $ blockValues ,
174+ $ prefix . $ fieldName . '_ '
178175 );
179176 }
180177
181178 continue ;
182179 }
183180
184181 $ type = $ mapping ['type ' ];
185- $ value = $ this ->fieldEvaluator ->getValue ($ object , $ mapping ['field ' ]);
182+ /** @var FieldInterface $mappingField */
183+ $ mappingField = $ mapping ['field ' ];
184+ $ condition = method_exists ($ mappingField , 'getCondition ' ) ? $ mappingField ->getCondition () : null ;
185+ $ validField = $ condition ? $ this ->fieldEvaluator ->evaluateCondition ($ object , $ condition ) : true ;
186+
187+ if (false === $ validField ) {
188+ continue ;
189+ }
190+
191+ $ value = $ this ->fieldEvaluator ->getValue ($ object , $ mappingField );
186192
187193 if (Field::TYPE_STRING !== $ type && Field::TYPE_ARRAY !== $ type ) {
188194 $ value = $ this ->converterManager ->convert ($ value , $ type , $ document );
@@ -199,25 +205,17 @@ private function populateDocument($document, $object, $fieldMapping, $prefix = '
199205 );
200206 }
201207
202- if (\is_array ($ value ) && (isset ($ value ['value ' ]) || isset ($ value ['fields ' ]))) {
208+ if (! $ isBlockScope && \is_array ($ value ) && (isset ($ value ['value ' ]) || isset ($ value ['fields ' ]))) {
203209 if (isset ($ value ['value ' ])) {
204- $ document ->addField (
205- $ this ->factory ->createField (
206- $ prefix . $ fieldName ,
207- $ value ['value ' ],
208- $ this ->getValueType ($ value ['value ' ]),
209- $ mapping ['stored ' ],
210- $ mapping ['indexed ' ],
211- $ mapping ['aggregate ' ]
212- )
213- );
210+ $ valueType = $ this ->getValueType ($ value ['value ' ]);
211+ $ this ->addDocumentField ($ document , $ fieldName , $ value ['value ' ], $ mapping , $ valueType );
214212 }
215213
216214 if (isset ($ value ['fields ' ])) {
217215 /** @var Field $field */
218216 foreach ($ value ['fields ' ] as $ field ) {
219217 $ field = clone $ field ;
220- $ field ->setName ($ prefix . $ fieldName . '# ' . $ field ->getName ());
218+ $ field ->setName ($ fieldName . '# ' . $ field ->getName ());
221219 $ document ->addField ($ field );
222220 }
223221 }
@@ -226,29 +224,82 @@ private function populateDocument($document, $object, $fieldMapping, $prefix = '
226224 }
227225
228226 if ('complex ' !== $ mapping ['type ' ]) {
229- $ document ->addField (
230- $ this ->factory ->createField (
231- $ prefix . $ fieldName ,
232- $ value ,
233- $ type ,
234- $ mapping ['stored ' ],
235- $ mapping ['indexed ' ],
236- $ mapping ['aggregate ' ]
237- )
238- );
227+ if ($ isBlockScope && $ value && Field::TYPE_STRING === $ type ) {
228+ $ blockValues [$ prefix . $ fieldName ][] = $ value ;
229+ } elseif (!$ isBlockScope ) {
230+ $ this ->addDocumentField ($ document , $ fieldName , $ value , $ mapping , $ type );
231+ }
239232
240233 continue ;
241234 }
242235
243236 foreach ($ value as $ key => $ itemValue ) {
244- $ document ->addField (
245- $ this ->factory ->createField (
246- $ prefix . $ fieldName . $ key ,
247- $ itemValue ,
248- $ mapping ['type ' ],
249- $ mapping ['stored ' ],
250- $ mapping ['indexed ' ],
251- $ mapping ['aggregate ' ]
237+ $ itemType = $ mapping ['type ' ];
238+
239+ if ($ isBlockScope && $ itemValue && Field::TYPE_STRING === $ itemType ) {
240+ $ blockValues [$ prefix . $ fieldName . $ key ][] = $ itemValue ;
241+ } elseif (!$ isBlockScope ) {
242+ $ this ->addDocumentField ($ document , $ fieldName . $ key , $ itemValue , $ mapping , $ itemType );
243+ }
244+ }
245+ }
246+ }
247+
248+ /**
249+ * Adds some default mapping options to the given array.
250+ */
251+ private function addMappingOptions ($ mapping = []): array
252+ {
253+ return \array_merge (
254+ [
255+ 'stored ' => true ,
256+ 'aggregate ' => false ,
257+ 'indexed ' => true ,
258+ ],
259+ $ mapping
260+ );
261+ }
262+
263+ /**
264+ * Adds a search field to the Document.
265+ *
266+ * @param Document $document
267+ * @param string $fieldName
268+ * @param mixed $value
269+ * @param array $mapping
270+ * @param string $type
271+ */
272+ private function addDocumentField ($ document , $ fieldName , $ value , $ mapping , $ type ): void
273+ {
274+ $ document ->addField (
275+ $ this ->factory ->createField (
276+ $ fieldName ,
277+ $ value ,
278+ $ type ,
279+ $ mapping ['stored ' ],
280+ $ mapping ['indexed ' ],
281+ $ mapping ['aggregate ' ]
282+ )
283+ );
284+ }
285+
286+ /**
287+ * Checks if all mandatory options are available in the given mapping.
288+ *
289+ * @param Document $document
290+ * @param array $mapping
291+ */
292+ private function hasRequiredMapping ($ document , $ mapping ): void
293+ {
294+ $ requiredMappings = ['field ' , 'type ' ];
295+
296+ foreach ($ requiredMappings as $ requiredMapping ) {
297+ if (!isset ($ mapping [$ requiredMapping ])) {
298+ throw new \RuntimeException (
299+ \sprintf (
300+ 'Mapping for "%s" does not have "%s" key ' ,
301+ \get_class ($ document ),
302+ $ requiredMapping
252303 )
253304 );
254305 }
0 commit comments