Completed
Push — 6.13 ( 878d09...f11ecd )
by
unknown
26:52
created

DomainMapper::buildLocationDomainObject()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 2
dl 0
loc 57
rs 8.9381
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * File containing the DomainMapper class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\Core\Repository\Helper;
10
11
use eZ\Publish\SPI\Persistence\Content\Handler as ContentHandler;
12
use eZ\Publish\SPI\Persistence\Content\Location\Handler as LocationHandler;
13
use eZ\Publish\SPI\Persistence\Content\Language\Handler as LanguageHandler;
14
use eZ\Publish\SPI\Persistence\Content\Type\Handler as TypeHandler;
15
use eZ\Publish\Core\Repository\Values\Content\Content;
16
use eZ\Publish\API\Repository\Values\Content\VersionInfo as APIVersionInfo;
17
use eZ\Publish\Core\Repository\Values\Content\VersionInfo;
18
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
19
use eZ\Publish\API\Repository\Values\ContentType\ContentType;
20
use eZ\Publish\API\Repository\Values\Content\Field;
21
use eZ\Publish\Core\Repository\Values\Content\Relation;
22
use eZ\Publish\API\Repository\Values\Content\Location as APILocation;
23
use eZ\Publish\Core\Repository\Values\Content\Location;
24
use eZ\Publish\SPI\Persistence\Content as SPIContent;
25
use eZ\Publish\SPI\Persistence\Content\Location as SPILocation;
26
use eZ\Publish\SPI\Persistence\Content\VersionInfo as SPIVersionInfo;
27
use eZ\Publish\SPI\Persistence\Content\ContentInfo as SPIContentInfo;
28
use eZ\Publish\SPI\Persistence\Content\Relation as SPIRelation;
29
use eZ\Publish\SPI\Persistence\Content\Type as SPIType;
30
use eZ\Publish\SPI\Persistence\Content\Location\CreateStruct as SPILocationCreateStruct;
31
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
32
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;
33
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentValue;
34
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentType;
35
use DateTime;
36
37
/**
38
 * DomainMapper is an internal service.
39
 *
40
 * @internal Meant for internal use by Repository.
41
 */
42
class DomainMapper
43
{
44
    /**
45
     * @var \eZ\Publish\SPI\Persistence\Content\Handler
46
     */
47
    protected $contentHandler;
48
49
    /**
50
     * @var \eZ\Publish\SPI\Persistence\Content\Location\Handler
51
     */
52
    protected $locationHandler;
53
54
    /**
55
     * @var \eZ\Publish\SPI\Persistence\Content\Type\Handler
56
     */
57
    protected $contentTypeHandler;
58
59
    /**
60
     * @var \eZ\Publish\SPI\Persistence\Content\Language\Handler
61
     */
62
    protected $contentLanguageHandler;
63
64
    /**
65
     * @var FieldTypeRegistry
66
     */
67
    protected $fieldTypeRegistry;
68
69
    /**
70
     * Setups service with reference to repository.
71
     *
72
     * @param \eZ\Publish\SPI\Persistence\Content\Handler $contentHandler
73
     * @param \eZ\Publish\SPI\Persistence\Content\Location\Handler $locationHandler
74
     * @param \eZ\Publish\SPI\Persistence\Content\Type\Handler $contentTypeHandler
75
     * @param \eZ\Publish\SPI\Persistence\Content\Language\Handler $contentLanguageHandler
76
     * @param FieldTypeRegistry $fieldTypeRegistry
77
     */
78
    public function __construct(
79
        ContentHandler $contentHandler,
80
        LocationHandler $locationHandler,
81
        TypeHandler $contentTypeHandler,
82
        LanguageHandler $contentLanguageHandler,
83
        FieldTypeRegistry $fieldTypeRegistry
84
    ) {
85
        $this->contentHandler = $contentHandler;
86
        $this->locationHandler = $locationHandler;
87
        $this->contentTypeHandler = $contentTypeHandler;
88
        $this->contentLanguageHandler = $contentLanguageHandler;
89
        $this->fieldTypeRegistry = $fieldTypeRegistry;
90
    }
91
92
    /**
93
     * Builds a Content domain object from value object returned from persistence.
94
     *
95
     * @param \eZ\Publish\SPI\Persistence\Content $spiContent
96
     * @param ContentType|SPIType $contentType
97
     * @param array|null $fieldLanguages Language codes to filter fields on
98
     * @param string|null $fieldAlwaysAvailableLanguage Language code fallback if a given field is not found in $fieldLanguages
99
     *
100
     * @return \eZ\Publish\Core\Repository\Values\Content\Content
101
     */
102
    public function buildContentDomainObject(SPIContent $spiContent, $contentType = null, array $fieldLanguages = null, $fieldAlwaysAvailableLanguage = null)
103
    {
104
        if ($contentType === null) {
105
            $contentType = $this->contentTypeHandler->load(
106
                $spiContent->versionInfo->contentInfo->contentTypeId
107
            );
108
        }
109
110
        $prioritizedFieldLanguageCode = null;
111
        $prioritizedLanguages = $fieldLanguages ?: [];
112
        if (!empty($prioritizedLanguages)) {
113
            $availableFieldLanguageMap = array_fill_keys($spiContent->versionInfo->languageCodes, true);
114
            foreach ($prioritizedLanguages as $prioritizedLanguage) {
115
                if (isset($availableFieldLanguageMap[$prioritizedLanguage])) {
116
                    $prioritizedFieldLanguageCode = $prioritizedLanguage;
117
                    break;
118
                }
119
            }
120
        }
121
122
        return new Content(
123
            array(
124
                'internalFields' => $this->buildDomainFields($spiContent->fields, $contentType, $fieldLanguages, $fieldAlwaysAvailableLanguage),
125
                'versionInfo' => $this->buildVersionInfoDomainObject($spiContent->versionInfo, $prioritizedLanguages),
126
                'prioritizedFieldLanguageCode' => $prioritizedFieldLanguageCode,
127
            )
128
        );
129
    }
130
131
    /**
132
     * Returns an array of domain fields created from given array of SPI fields.
133
     *
134
     * @throws InvalidArgumentType On invalid $contentType
135
     *
136
     * @param \eZ\Publish\SPI\Persistence\Content\Field[] $spiFields
137
     * @param ContentType|SPIType $contentType
138
     * @param array $languages A language priority, filters returned fields and is used as prioritized language code on
139
     *                         returned value object. If not given all languages are returned.
140
     * @param string|null $alwaysAvailableLanguage Language code fallback if a given field is not found in $languages
141
     *
142
     * @return array
143
     */
144
    public function buildDomainFields(
145
        array $spiFields,
146
        $contentType,
147
        array $languages = null,
148
        $alwaysAvailableLanguage = null
149
    ) {
150
        if (!$contentType instanceof SPIType && !$contentType instanceof ContentType) {
151
            throw new InvalidArgumentType('$contentType', 'SPI ContentType | API ContentType');
152
        }
153
154
        $fieldIdentifierMap = array();
155
        foreach ($contentType->fieldDefinitions as $fieldDefinitions) {
156
            $fieldIdentifierMap[$fieldDefinitions->id] = $fieldDefinitions->identifier;
157
        }
158
159
        $fieldInFilterLanguagesMap = array();
160
        if (!empty($languages) && $alwaysAvailableLanguage !== null) {
161
            foreach ($spiFields as $spiField) {
162
                if (in_array($spiField->languageCode, $languages)) {
163
                    $fieldInFilterLanguagesMap[$spiField->fieldDefinitionId] = true;
164
                }
165
            }
166
        }
167
168
        $fields = array();
169
        foreach ($spiFields as $spiField) {
170
            // We ignore fields in content not part of the content type
171
            if (!isset($fieldIdentifierMap[$spiField->fieldDefinitionId])) {
172
                continue;
173
            }
174
175
            if (!empty($languages) && !in_array($spiField->languageCode, $languages)) {
176
                // If filtering is enabled we ignore fields in other languages then $fieldLanguages, if:
177
                if ($alwaysAvailableLanguage === null) {
178
                    // Ignore field if we don't have $alwaysAvailableLanguageCode fallback
179
                    continue;
180
                } elseif (!empty($fieldInFilterLanguagesMap[$spiField->fieldDefinitionId])) {
181
                    // Ignore field if it exists in one of the filtered languages
182
                    continue;
183
                } elseif ($spiField->languageCode !== $alwaysAvailableLanguage) {
184
                    // Also ignore if field is not in $alwaysAvailableLanguageCode
185
                    continue;
186
                }
187
            }
188
189
            $fields[] = new Field(
190
                array(
191
                    'id' => $spiField->id,
192
                    'value' => $this->fieldTypeRegistry->getFieldType($spiField->type)
193
                        ->fromPersistenceValue($spiField->value),
194
                    'languageCode' => $spiField->languageCode,
195
                    'fieldDefIdentifier' => $fieldIdentifierMap[$spiField->fieldDefinitionId],
196
                    'fieldTypeIdentifier' => $spiField->type,
197
                )
198
            );
199
        }
200
201
        return $fields;
202
    }
203
204
    /**
205
     * Builds a VersionInfo domain object from value object returned from persistence.
206
     *
207
     * @param \eZ\Publish\SPI\Persistence\Content\VersionInfo $spiVersionInfo
208
     * @param array $prioritizedLanguages
209
     *
210
     * @return \eZ\Publish\Core\Repository\Values\Content\VersionInfo
211
     */
212
    public function buildVersionInfoDomainObject(SPIVersionInfo $spiVersionInfo, array $prioritizedLanguages = [])
213
    {
214
        // Map SPI statuses to API
215
        switch ($spiVersionInfo->status) {
216
            case SPIVersionInfo::STATUS_ARCHIVED:
217
                $status = APIVersionInfo::STATUS_ARCHIVED;
218
                break;
219
220
            case SPIVersionInfo::STATUS_PUBLISHED:
221
                $status = APIVersionInfo::STATUS_PUBLISHED;
222
                break;
223
224
            case SPIVersionInfo::STATUS_DRAFT:
225
            default:
226
                $status = APIVersionInfo::STATUS_DRAFT;
227
        }
228
229
        // Find prioritised language among names
230
        $prioritizedNameLanguageCode = null;
231
        foreach ($prioritizedLanguages as $prioritizedLanguage) {
232
            if (isset($spiVersionInfo->names[$prioritizedLanguage])) {
233
                $prioritizedNameLanguageCode = $prioritizedLanguage;
234
                break;
235
            }
236
        }
237
238
        return new VersionInfo(
239
            array(
240
                'id' => $spiVersionInfo->id,
241
                'versionNo' => $spiVersionInfo->versionNo,
242
                'modificationDate' => $this->getDateTime($spiVersionInfo->modificationDate),
243
                'creatorId' => $spiVersionInfo->creatorId,
244
                'creationDate' => $this->getDateTime($spiVersionInfo->creationDate),
245
                'status' => $status,
246
                'initialLanguageCode' => $spiVersionInfo->initialLanguageCode,
247
                'languageCodes' => $spiVersionInfo->languageCodes,
248
                'names' => $spiVersionInfo->names,
249
                'contentInfo' => $this->buildContentInfoDomainObject($spiVersionInfo->contentInfo),
250
                'prioritizedNameLanguageCode' => $prioritizedNameLanguageCode,
251
            )
252
        );
253
    }
254
255
    /**
256
     * Builds a ContentInfo domain object from value object returned from persistence.
257
     *
258
     * @param \eZ\Publish\SPI\Persistence\Content\ContentInfo $spiContentInfo
259
     *
260
     * @return \eZ\Publish\API\Repository\Values\Content\ContentInfo
261
     */
262
    public function buildContentInfoDomainObject(SPIContentInfo $spiContentInfo)
263
    {
264
        // Map SPI statuses to API
265
        switch ($spiContentInfo->status) {
266
            case SPIContentInfo::STATUS_TRASHED:
267
                $status = ContentInfo::STATUS_TRASHED;
268
                break;
269
270
            case SPIContentInfo::STATUS_PUBLISHED:
271
                $status = ContentInfo::STATUS_PUBLISHED;
272
                break;
273
274
            case SPIContentInfo::STATUS_DRAFT:
275
            default:
276
                $status = ContentInfo::STATUS_DRAFT;
277
        }
278
279
        return new ContentInfo(
280
            array(
281
                'id' => $spiContentInfo->id,
282
                'contentTypeId' => $spiContentInfo->contentTypeId,
283
                'name' => $spiContentInfo->name,
284
                'sectionId' => $spiContentInfo->sectionId,
285
                'currentVersionNo' => $spiContentInfo->currentVersionNo,
286
                'published' => $spiContentInfo->isPublished,
0 ignored issues
show
Deprecated Code introduced by
The property eZ\Publish\SPI\Persisten...ntentInfo::$isPublished has been deprecated with message: Use SPI\ContentInfo::$status (with value ContentInfo::STATUS_PUBLISHED) Flag indicating if content is currently published.

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
287
                'ownerId' => $spiContentInfo->ownerId,
288
                'modificationDate' => $spiContentInfo->modificationDate == 0 ?
289
                    null :
290
                    $this->getDateTime($spiContentInfo->modificationDate),
291
                'publishedDate' => $spiContentInfo->publicationDate == 0 ?
292
                    null :
293
                    $this->getDateTime($spiContentInfo->publicationDate),
294
                'alwaysAvailable' => $spiContentInfo->alwaysAvailable,
295
                'remoteId' => $spiContentInfo->remoteId,
296
                'mainLanguageCode' => $spiContentInfo->mainLanguageCode,
297
                'mainLocationId' => $spiContentInfo->mainLocationId,
298
                'status' => $status,
299
            )
300
        );
301
    }
302
303
    /**
304
     * Builds API Relation object from provided SPI Relation object.
305
     *
306
     * @param \eZ\Publish\SPI\Persistence\Content\Relation $spiRelation
307
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $sourceContentInfo
308
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $destinationContentInfo
309
     *
310
     * @return \eZ\Publish\API\Repository\Values\Content\Relation
311
     */
312
    public function buildRelationDomainObject(
313
        SPIRelation $spiRelation,
314
        ContentInfo $sourceContentInfo,
315
        ContentInfo $destinationContentInfo
316
    ) {
317
        $sourceFieldDefinitionIdentifier = null;
318
        if ($spiRelation->sourceFieldDefinitionId !== null) {
319
            $contentType = $this->contentTypeHandler->load($sourceContentInfo->contentTypeId);
320
            foreach ($contentType->fieldDefinitions as $fieldDefinition) {
321
                if ($fieldDefinition->id !== $spiRelation->sourceFieldDefinitionId) {
322
                    continue;
323
                }
324
325
                $sourceFieldDefinitionIdentifier = $fieldDefinition->identifier;
326
                break;
327
            }
328
        }
329
330
        return new Relation(
331
            array(
332
                'id' => $spiRelation->id,
333
                'sourceFieldDefinitionIdentifier' => $sourceFieldDefinitionIdentifier,
334
                'type' => $spiRelation->type,
335
                'sourceContentInfo' => $sourceContentInfo,
336
                'destinationContentInfo' => $destinationContentInfo,
337
            )
338
        );
339
    }
340
341
    /**
342
     * Builds domain location object from provided persistence location.
343
     *
344
     * @param \eZ\Publish\SPI\Persistence\Content\Location $spiLocation
345
     * @param \eZ\Publish\SPI\Persistence\Content\ContentInfo $spiContentInfo pre-loaded Content Info
346
     *
347
     * @return \eZ\Publish\API\Repository\Values\Content\Location
348
     *
349
     * @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException In case if the given Content does not belong to the given Location
350
     */
351
    public function buildLocationDomainObject(SPILocation $spiLocation, SPIContentInfo $spiContentInfo = null)
352
    {
353
        // TODO: this is hardcoded workaround for missing ContentInfo on root location
354
        if ($spiLocation->id == 1) {
355
            $legacyDateTime = $this->getDateTime(1030968000); //  first known commit of eZ Publish 3.x
356
            $contentInfo = new ContentInfo(
357
                array(
358
                    'id' => 0,
359
                    'name' => 'Top Level Nodes',
360
                    'sectionId' => 1,
361
                    'mainLocationId' => 1,
362
                    'contentTypeId' => 1,
363
                    'currentVersionNo' => 1,
364
                    'published' => 1,
365
                    'ownerId' => 14, // admin user
366
                    'modificationDate' => $legacyDateTime,
367
                    'publishedDate' => $legacyDateTime,
368
                    'alwaysAvailable' => 1,
369
                    'remoteId' => null,
370
                    'mainLanguageCode' => 'eng-GB',
371
                )
372
            );
373
        } elseif (null !== $spiContentInfo) {
374
            if ($spiLocation->contentId !== $spiContentInfo->id) {
375
                throw new InvalidArgumentException(
376
                    '$spiContentInfo',
377
                    sprintf(
378
                        'Content Id %d does not belong to the Location %d',
379
                        $spiContentInfo->id,
380
                        $spiLocation->id
381
                    )
382
                );
383
            }
384
385
            $contentInfo = $this->buildContentInfoDomainObject($spiContentInfo);
386
        } else {
387
            $contentInfo = $this->buildContentInfoDomainObject(
388
                $this->contentHandler->loadContentInfo($spiLocation->contentId)
389
            );
390
        }
391
392
        return new Location(
393
            array(
394
                'contentInfo' => $contentInfo,
395
                'id' => $spiLocation->id,
396
                'priority' => $spiLocation->priority,
397
                'hidden' => $spiLocation->hidden,
398
                'invisible' => $spiLocation->invisible,
399
                'remoteId' => $spiLocation->remoteId,
400
                'parentLocationId' => $spiLocation->parentId,
401
                'pathString' => $spiLocation->pathString,
402
                'depth' => $spiLocation->depth,
403
                'sortField' => $spiLocation->sortField,
404
                'sortOrder' => $spiLocation->sortOrder,
405
            )
406
        );
407
    }
408
409
    /**
410
     * Creates an array of SPI location create structs from given array of API location create structs.
411
     *
412
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
413
     *
414
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct $locationCreateStruct
415
     * @param \eZ\Publish\API\Repository\Values\Content\Location $parentLocation
416
     * @param mixed $mainLocation
417
     * @param mixed $contentId
418
     * @param mixed $contentVersionNo
419
     *
420
     * @return \eZ\Publish\SPI\Persistence\Content\Location\CreateStruct
421
     */
422
    public function buildSPILocationCreateStruct(
423
        $locationCreateStruct,
424
        APILocation $parentLocation,
425
        $mainLocation,
426
        $contentId,
427
        $contentVersionNo
428
    ) {
429
        if ($locationCreateStruct->priority !== null && !is_int($locationCreateStruct->priority)) {
430
            throw new InvalidArgumentValue('priority', $locationCreateStruct->priority, 'LocationCreateStruct');
431
        }
432
433
        if (!is_bool($locationCreateStruct->hidden)) {
434
            throw new InvalidArgumentValue('hidden', $locationCreateStruct->hidden, 'LocationCreateStruct');
435
        }
436
437
        if ($locationCreateStruct->remoteId !== null && (!is_string($locationCreateStruct->remoteId) || empty($locationCreateStruct->remoteId))) {
438
            throw new InvalidArgumentValue('remoteId', $locationCreateStruct->remoteId, 'LocationCreateStruct');
439
        }
440
441
        if ($locationCreateStruct->sortField !== null && !$this->isValidLocationSortField($locationCreateStruct->sortField)) {
442
            throw new InvalidArgumentValue('sortField', $locationCreateStruct->sortField, 'LocationCreateStruct');
443
        }
444
445
        if ($locationCreateStruct->sortOrder !== null && !$this->isValidLocationSortOrder($locationCreateStruct->sortOrder)) {
446
            throw new InvalidArgumentValue('sortOrder', $locationCreateStruct->sortOrder, 'LocationCreateStruct');
447
        }
448
449
        $remoteId = $locationCreateStruct->remoteId;
450
        if (null === $remoteId) {
451
            $remoteId = $this->getUniqueHash($locationCreateStruct);
452
        } else {
453
            try {
454
                $this->locationHandler->loadByRemoteId($remoteId);
455
                throw new InvalidArgumentException(
456
                    '$locationCreateStructs',
457
                    "Another Location with remoteId '{$remoteId}' exists"
458
                );
459
            } catch (NotFoundException $e) {
460
                // Do nothing
461
            }
462
        }
463
464
        return new SPILocationCreateStruct(
465
            array(
466
                'priority' => $locationCreateStruct->priority,
467
                'hidden' => $locationCreateStruct->hidden,
468
                // If we declare the new Location as hidden, it is automatically invisible
469
                // Otherwise it picks up visibility from parent Location
470
                // Note: There is no need to check for hidden status of parent, as hidden Location
471
                // is always invisible as well
472
                'invisible' => ($locationCreateStruct->hidden === true || $parentLocation->invisible),
473
                'remoteId' => $remoteId,
474
                'contentId' => $contentId,
475
                'contentVersion' => $contentVersionNo,
476
                // pathIdentificationString will be set in storage
477
                'pathIdentificationString' => null,
478
                'mainLocationId' => $mainLocation,
479
                'sortField' => $locationCreateStruct->sortField !== null ? $locationCreateStruct->sortField : Location::SORT_FIELD_NAME,
480
                'sortOrder' => $locationCreateStruct->sortOrder !== null ? $locationCreateStruct->sortOrder : Location::SORT_ORDER_ASC,
481
                'parentId' => $locationCreateStruct->parentLocationId,
482
            )
483
        );
484
    }
485
486
    /**
487
     * Checks if given $sortField value is one of the defined sort field constants.
488
     *
489
     * @param mixed $sortField
490
     *
491
     * @return bool
492
     */
493
    public function isValidLocationSortField($sortField)
494
    {
495
        switch ($sortField) {
496
            case APILocation::SORT_FIELD_PATH:
497
            case APILocation::SORT_FIELD_PUBLISHED:
498
            case APILocation::SORT_FIELD_MODIFIED:
499
            case APILocation::SORT_FIELD_SECTION:
500
            case APILocation::SORT_FIELD_DEPTH:
501
            case APILocation::SORT_FIELD_CLASS_IDENTIFIER:
502
            case APILocation::SORT_FIELD_CLASS_NAME:
503
            case APILocation::SORT_FIELD_PRIORITY:
504
            case APILocation::SORT_FIELD_NAME:
505
            case APILocation::SORT_FIELD_MODIFIED_SUBNODE:
0 ignored issues
show
Deprecated Code introduced by
The constant eZ\Publish\API\Repositor..._FIELD_MODIFIED_SUBNODE has been deprecated.

This class constant has been deprecated.

Loading history...
506
            case APILocation::SORT_FIELD_NODE_ID:
507
            case APILocation::SORT_FIELD_CONTENTOBJECT_ID:
508
                return true;
509
        }
510
511
        return false;
512
    }
513
514
    /**
515
     * Checks if given $sortOrder value is one of the defined sort order constants.
516
     *
517
     * @param mixed $sortOrder
518
     *
519
     * @return bool
520
     */
521
    public function isValidLocationSortOrder($sortOrder)
522
    {
523
        switch ($sortOrder) {
524
            case APILocation::SORT_ORDER_DESC:
525
            case APILocation::SORT_ORDER_ASC:
526
                return true;
527
        }
528
529
        return false;
530
    }
531
532
    /**
533
     * Validates given translated list $list, which should be an array of strings with language codes as keys.
534
     *
535
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
536
     *
537
     * @param mixed $list
538
     * @param string $argumentName
539
     */
540
    public function validateTranslatedList($list, $argumentName)
541
    {
542
        if (!is_array($list)) {
543
            throw new InvalidArgumentType($argumentName, 'array', $list);
544
        }
545
546
        foreach ($list as $languageCode => $translation) {
547
            $this->contentLanguageHandler->loadByLanguageCode($languageCode);
548
549
            if (!is_string($translation)) {
550
                throw new InvalidArgumentType($argumentName . "['$languageCode']", 'string', $translation);
551
            }
552
        }
553
    }
554
555
    /**
556
     * Returns \DateTime object from given $timestamp in environment timezone.
557
     *
558
     * This method is needed because constructing \DateTime with $timestamp will
559
     * return the object in UTC timezone.
560
     *
561
     * @param int $timestamp
562
     *
563
     * @return \DateTime
564
     */
565
    public function getDateTime($timestamp)
566
    {
567
        $dateTime = new DateTime();
568
        $dateTime->setTimestamp($timestamp);
569
570
        return $dateTime;
571
    }
572
573
    /**
574
     * Creates unique hash string for given $object.
575
     *
576
     * Used for remoteId.
577
     *
578
     * @param object $object
579
     *
580
     * @return string
581
     */
582
    public function getUniqueHash($object)
583
    {
584
        return md5(uniqid(get_class($object), true));
585
    }
586
}
587