13
13
14
14
use Massive \Bundle \SearchBundle \Search \Converter \ConverterManagerInterface ;
15
15
use Massive \Bundle \SearchBundle \Search \Metadata \FieldEvaluator ;
16
+ use Massive \Bundle \SearchBundle \Search \Metadata \FieldInterface ;
16
17
use Massive \Bundle \SearchBundle \Search \Metadata \IndexMetadata ;
17
18
18
19
/**
@@ -110,7 +111,14 @@ public function objectToDocument(IndexMetadata $metadata, $object)
110
111
$ document ->setLocale ($ locale );
111
112
}
112
113
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
+ }
114
122
115
123
return $ document ;
116
124
}
@@ -122,35 +130,23 @@ public function objectToDocument(IndexMetadata $metadata, $object)
122
130
* @param Document $document
123
131
* @param mixed $object
124
132
* @param array $fieldMapping
133
+ * @param string[] $blockValues
125
134
* @param string $prefix Prefix the document field name (used when called recursively)
126
135
*
127
136
* @throws \InvalidArgumentException
128
137
*/
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 ;
145
146
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 );
154
150
155
151
if ('complex ' == $ mapping ['type ' ]) {
156
152
if (!isset ($ mapping ['mapping ' ])) {
@@ -174,15 +170,25 @@ private function populateDocument($document, $object, $fieldMapping, $prefix = '
174
170
$ document ,
175
171
$ childObject ,
176
172
$ mapping ['mapping ' ]->getFieldMapping (),
177
- $ prefix . $ fieldName . $ i
173
+ $ blockValues ,
174
+ $ prefix . $ fieldName . '_ '
178
175
);
179
176
}
180
177
181
178
continue ;
182
179
}
183
180
184
181
$ 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 );
186
192
187
193
if (Field::TYPE_STRING !== $ type && Field::TYPE_ARRAY !== $ type ) {
188
194
$ value = $ this ->converterManager ->convert ($ value , $ type , $ document );
@@ -199,25 +205,17 @@ private function populateDocument($document, $object, $fieldMapping, $prefix = '
199
205
);
200
206
}
201
207
202
- if (\is_array ($ value ) && (isset ($ value ['value ' ]) || isset ($ value ['fields ' ]))) {
208
+ if (! $ isBlockScope && \is_array ($ value ) && (isset ($ value ['value ' ]) || isset ($ value ['fields ' ]))) {
203
209
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 );
214
212
}
215
213
216
214
if (isset ($ value ['fields ' ])) {
217
215
/** @var Field $field */
218
216
foreach ($ value ['fields ' ] as $ field ) {
219
217
$ field = clone $ field ;
220
- $ field ->setName ($ prefix . $ fieldName . '# ' . $ field ->getName ());
218
+ $ field ->setName ($ fieldName . '# ' . $ field ->getName ());
221
219
$ document ->addField ($ field );
222
220
}
223
221
}
@@ -226,29 +224,82 @@ private function populateDocument($document, $object, $fieldMapping, $prefix = '
226
224
}
227
225
228
226
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
+ }
239
232
240
233
continue ;
241
234
}
242
235
243
236
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
252
303
)
253
304
);
254
305
}
0 commit comments