16
16
use eZ \Publish \SPI \Persistence \Content \Language \Handler as LanguageHandler ;
17
17
use eZ \Publish \SPI \Persistence \Content \Relation ;
18
18
use eZ \Publish \SPI \Persistence \Content \Relation \CreateStruct as RelationCreateStruct ;
19
+ use eZ \Publish \SPI \Persistence \Content \Type \Handler as ContentTypeHandler ;
19
20
use eZ \Publish \SPI \Persistence \Content \VersionInfo ;
21
+ use Ibexa \Contracts \Core \Event \Mapper \ResolveMissingFieldEvent ;
22
+ use Symfony \Contracts \EventDispatcher \EventDispatcherInterface ;
20
23
21
24
/**
22
25
* Mapper for Content Handler.
23
26
*
24
27
* Performs mapping of Content objects.
28
+ *
29
+ * @phpstan-type TVersionedLanguageFieldDefinitionsMap array<
30
+ * int, array<
31
+ * int, array<
32
+ * string, array<
33
+ * int, \eZ\Publish\SPI\Persistence\Content\Type\FieldDefinition,
34
+ * >
35
+ * >
36
+ * >
37
+ * >
38
+ * @phpstan-type TVersionedFieldMap array<
39
+ * int, array<
40
+ * int, array<
41
+ * int, \eZ\Publish\SPI\Persistence\Content\Field,
42
+ * >
43
+ * >
44
+ * >
45
+ * @phpstan-type TVersionedNameMap array<
46
+ * int, array<
47
+ * int, array<
48
+ * string, array<int, string>
49
+ * >
50
+ * >
51
+ * >
52
+ * @phpstan-type TContentInfoMap array<int, \eZ\Publish\SPI\Persistence\Content\ContentInfo>
53
+ * @phpstan-type TVersionInfoMap array<
54
+ * int, array<
55
+ * int, \eZ\Publish\SPI\Persistence\Content\VersionInfo,
56
+ * >
57
+ * >
25
58
*/
26
59
class Mapper
27
60
{
@@ -40,15 +73,25 @@ class Mapper
40
73
protected $ languageHandler ;
41
74
42
75
/**
43
- * Creates a new mapper.
44
- *
45
- * @param \eZ\Publish\Core\Persistence\Legacy\Content\FieldValue\ConverterRegistry $converterRegistry
46
- * @param \eZ\Publish\SPI\Persistence\Content\Language\Handler $languageHandler
76
+ * @var \eZ\Publish\SPI\Persistence\Content\Type\Handler
47
77
*/
48
- public function __construct (Registry $ converterRegistry , LanguageHandler $ languageHandler )
49
- {
78
+ private $ contentTypeHandler ;
79
+
80
+ /**
81
+ * @var \Symfony\Contracts\EventDispatcher\EventDispatcherInterface
82
+ */
83
+ private $ eventDispatcher ;
84
+
85
+ public function __construct (
86
+ Registry $ converterRegistry ,
87
+ LanguageHandler $ languageHandler ,
88
+ ContentTypeHandler $ contentTypeHandler ,
89
+ EventDispatcherInterface $ eventDispatcher
90
+ ) {
50
91
$ this ->converterRegistry = $ converterRegistry ;
51
92
$ this ->languageHandler = $ languageHandler ;
93
+ $ this ->contentTypeHandler = $ contentTypeHandler ;
94
+ $ this ->eventDispatcher = $ eventDispatcher ;
52
95
}
53
96
54
97
/**
@@ -174,66 +217,166 @@ public function convertToStorageValue(Field $field)
174
217
*
175
218
* "$tableName_$columnName"
176
219
*
177
- * @param array $rows
178
- * @param array $nameRows
220
+ * @param array<array<string, scalar>> $rows
221
+ * @param array<array<string, scalar>> $nameRows
222
+ * @param string $prefix
179
223
*
180
224
* @return \eZ\Publish\SPI\Persistence\Content[]
225
+ *
226
+ * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
181
227
*/
182
- public function extractContentFromRows (array $ rows , array $ nameRows , $ prefix = 'ezcontentobject_ ' )
183
- {
228
+ public function extractContentFromRows (
229
+ array $ rows ,
230
+ array $ nameRows ,
231
+ string $ prefix = 'ezcontentobject_ '
232
+ ): array {
184
233
$ versionedNameData = [];
234
+
185
235
foreach ($ nameRows as $ row ) {
186
- $ contentId = (int )$ row ['ezcontentobject_name_contentobject_id ' ];
187
- $ versionNo = (int )$ row ['ezcontentobject_name_content_version ' ];
188
- $ versionedNameData [$ contentId ][$ versionNo ][$ row ['ezcontentobject_name_content_translation ' ]] = $ row ['ezcontentobject_name_name ' ];
236
+ $ contentId = (int )$ row ["{$ prefix }name_contentobject_id " ];
237
+ $ versionNo = (int )$ row ["{$ prefix }name_content_version " ];
238
+ $ languageCode = $ row ["{$ prefix }name_content_translation " ];
239
+ $ versionedNameData [$ contentId ][$ versionNo ][$ languageCode ] = $ row ["{$ prefix }name_name " ];
189
240
}
190
241
191
242
$ contentInfos = [];
192
243
$ versionInfos = [];
193
244
$ fields = [];
194
245
246
+ $ fieldDefinitions = $ this ->loadCachedVersionFieldDefinitionsPerLanguage (
247
+ $ rows ,
248
+ $ prefix
249
+ );
250
+
195
251
foreach ($ rows as $ row ) {
196
252
$ contentId = (int )$ row ["{$ prefix }id " ];
253
+ $ versionId = (int )$ row ["{$ prefix }version_id " ];
254
+
197
255
if (!isset ($ contentInfos [$ contentId ])) {
198
256
$ contentInfos [$ contentId ] = $ this ->extractContentInfoFromRow ($ row , $ prefix );
199
257
}
258
+
200
259
if (!isset ($ versionInfos [$ contentId ])) {
201
260
$ versionInfos [$ contentId ] = [];
202
261
}
203
262
204
- $ versionId = (int )$ row ['ezcontentobject_version_id ' ];
205
263
if (!isset ($ versionInfos [$ contentId ][$ versionId ])) {
206
264
$ versionInfos [$ contentId ][$ versionId ] = $ this ->extractVersionInfoFromRow ($ row );
207
265
}
208
266
209
- $ fieldId = (int )$ row ['ezcontentobject_attribute_id ' ];
210
- if (!isset ($ fields [$ contentId ][$ versionId ][$ fieldId ])) {
267
+ $ fieldId = (int )$ row ["{$ prefix }attribute_id " ];
268
+ $ fieldDefinitionId = (int )$ row ["{$ prefix }attribute_contentclassattribute_id " ];
269
+ $ languageCode = $ row ["{$ prefix }attribute_language_code " ];
270
+
271
+ if (!isset ($ fields [$ contentId ][$ versionId ][$ fieldId ])
272
+ && isset ($ fieldDefinitions [$ contentId ][$ versionId ][$ languageCode ][$ fieldDefinitionId ])
273
+ ) {
211
274
$ fields [$ contentId ][$ versionId ][$ fieldId ] = $ this ->extractFieldFromRow ($ row );
275
+ unset($ fieldDefinitions [$ contentId ][$ versionId ][$ languageCode ][$ fieldDefinitionId ]);
212
276
}
213
277
}
214
278
279
+ return $ this ->buildContentObjects (
280
+ $ contentInfos ,
281
+ $ versionInfos ,
282
+ $ fields ,
283
+ $ fieldDefinitions ,
284
+ $ versionedNameData
285
+ );
286
+ }
287
+
288
+ /**
289
+ * @phpstan-param TContentInfoMap $contentInfos
290
+ * @phpstan-param TVersionInfoMap $versionInfos
291
+ * @phpstan-param TVersionedFieldMap $fields
292
+ * @phpstan-param TVersionedLanguageFieldDefinitionsMap $missingFieldDefinitions
293
+ * @phpstan-param TVersionedNameMap $versionedNames
294
+ *
295
+ * @return \eZ\Publish\SPI\Persistence\Content[]
296
+ */
297
+ private function buildContentObjects (
298
+ array $ contentInfos ,
299
+ array $ versionInfos ,
300
+ array $ fields ,
301
+ array $ missingFieldDefinitions ,
302
+ array $ versionedNames
303
+ ): array {
215
304
$ results = [];
305
+
216
306
foreach ($ contentInfos as $ contentId => $ contentInfo ) {
217
307
foreach ($ versionInfos [$ contentId ] as $ versionId => $ versionInfo ) {
218
308
// Fallback to just main language name if versioned name data is missing
219
- if (isset ($ versionedNameData [$ contentId ][$ versionInfo ->versionNo ])) {
220
- $ names = $ versionedNameData [$ contentId ][$ versionInfo ->versionNo ];
221
- } else {
222
- $ names = [$ contentInfo ->mainLanguageCode => $ contentInfo ->name ];
223
- }
309
+ $ names = $ versionedNames [$ contentId ][$ versionInfo ->versionNo ]
310
+ ?? [$ contentInfo ->mainLanguageCode => $ contentInfo ->name ];
224
311
225
312
$ content = new Content ();
226
313
$ content ->versionInfo = $ versionInfo ;
227
314
$ content ->versionInfo ->names = $ names ;
228
315
$ content ->versionInfo ->contentInfo = $ contentInfo ;
229
316
$ content ->fields = array_values ($ fields [$ contentId ][$ versionId ]);
317
+
318
+ $ missingVersionFieldDefinitions = $ missingFieldDefinitions [$ contentId ][$ versionId ];
319
+ foreach ($ missingVersionFieldDefinitions as $ languageCode => $ versionFieldDefinitions ) {
320
+ foreach ($ versionFieldDefinitions as $ fieldDefinition ) {
321
+ $ event = $ this ->eventDispatcher ->dispatch (
322
+ new ResolveMissingFieldEvent (
323
+ $ content ,
324
+ $ fieldDefinition ,
325
+ $ languageCode
326
+ )
327
+ );
328
+
329
+ $ field = $ event ->getField ();
330
+ if ($ field !== null ) {
331
+ $ content ->fields [] = $ field ;
332
+ }
333
+ }
334
+ }
335
+
230
336
$ results [] = $ content ;
231
337
}
232
338
}
233
339
234
340
return $ results ;
235
341
}
236
342
343
+ /**
344
+ * @phpstan-return TVersionedLanguageFieldDefinitionsMap
345
+ *
346
+ * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
347
+ */
348
+ private function loadCachedVersionFieldDefinitionsPerLanguage (
349
+ array $ rows ,
350
+ string $ prefix
351
+ ): array {
352
+ $ fieldDefinitions = [];
353
+ $ contentTypes = [];
354
+ $ allLanguages = $ this ->loadAllLanguagesWithIdKey ();
355
+
356
+ foreach ($ rows as $ row ) {
357
+ $ contentId = (int )$ row ["{$ prefix }id " ];
358
+ $ versionId = (int )$ row ["{$ prefix }version_id " ];
359
+ $ contentTypeId = (int )$ row ["{$ prefix }contentclass_id " ];
360
+ $ languageMask = (int )$ row ["{$ prefix }version_language_mask " ];
361
+
362
+ if (isset ($ fieldDefinitions [$ contentId ][$ versionId ])) {
363
+ continue ;
364
+ }
365
+
366
+ $ languageCodes = $ this ->extractLanguageCodesFromMask ($ languageMask , $ allLanguages );
367
+ $ contentTypes [$ contentTypeId ] = $ contentTypes [$ contentTypeId ] ?? $ this ->contentTypeHandler ->load ($ contentTypeId );
368
+ $ contentType = $ contentTypes [$ contentTypeId ];
369
+ foreach ($ contentType ->fieldDefinitions as $ fieldDefinition ) {
370
+ foreach ($ languageCodes as $ languageCode ) {
371
+ $ id = $ fieldDefinition ->id ;
372
+ $ fieldDefinitions [$ contentId ][$ versionId ][$ languageCode ][$ id ] = $ fieldDefinition ;
373
+ }
374
+ }
375
+ }
376
+
377
+ return $ fieldDefinitions ;
378
+ }
379
+
237
380
/**
238
381
* Extracts a ContentInfo object from $row.
239
382
*
@@ -251,7 +394,6 @@ public function extractContentInfoFromRow(array $row, $prefix = '', $treePrefix
251
394
$ contentInfo ->contentTypeId = (int )$ row ["{$ prefix }contentclass_id " ];
252
395
$ contentInfo ->sectionId = (int )$ row ["{$ prefix }section_id " ];
253
396
$ contentInfo ->currentVersionNo = (int )$ row ["{$ prefix }current_version " ];
254
- $ contentInfo ->isPublished = ($ row ["{$ prefix }status " ] == ContentInfo::STATUS_PUBLISHED );
255
397
$ contentInfo ->ownerId = (int )$ row ["{$ prefix }owner_id " ];
256
398
$ contentInfo ->publicationDate = (int )$ row ["{$ prefix }published " ];
257
399
$ contentInfo ->modificationDate = (int )$ row ["{$ prefix }modified " ];
0 commit comments