Completed
Push — 7.0 ( e06b0d...07af66 )
by André
31:05 queued 19:36
created

DomainMapper   F

Complexity

Total Complexity 79

Size/Duplication

Total Lines 536
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 28

Importance

Changes 0
Metric Value
dl 0
loc 536
rs 1.3043
c 0
b 0
f 0
wmc 79
lcom 3
cbo 28

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 1
B buildContentDomainObject() 0 28 6
C buildDomainFields() 0 54 15
B buildVersionInfoDomainObject() 0 42 6
B buildContentInfoDomainObject() 0 24 3
B buildRelationDomainObject() 0 28 4
B buildLocationDomainObject() 0 44 3
A buildLocationDomainObjectsOnSearchResult() 0 17 3
C buildSPILocationCreateStruct() 0 63 16
B isValidLocationSortField() 0 20 13
A isValidLocationSortOrder() 0 10 3
A validateTranslatedList() 0 14 4
A getDateTime() 0 7 1
A getUniqueHash() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like DomainMapper often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DomainMapper, and based on these observations, apply Extract Interface, too.

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\API\Repository\Values\Content\Search\SearchResult;
12
use eZ\Publish\SPI\Persistence\Content\Handler as ContentHandler;
13
use eZ\Publish\SPI\Persistence\Content\Location\Handler as LocationHandler;
14
use eZ\Publish\SPI\Persistence\Content\Language\Handler as LanguageHandler;
15
use eZ\Publish\SPI\Persistence\Content\Type\Handler as TypeHandler;
16
use eZ\Publish\Core\Repository\Values\Content\Content;
17
use eZ\Publish\API\Repository\Values\Content\VersionInfo as APIVersionInfo;
18
use eZ\Publish\Core\Repository\Values\Content\VersionInfo;
19
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
20
use eZ\Publish\API\Repository\Values\ContentType\ContentType;
21
use eZ\Publish\API\Repository\Values\Content\Field;
22
use eZ\Publish\Core\Repository\Values\Content\Relation;
23
use eZ\Publish\API\Repository\Values\Content\Location as APILocation;
24
use eZ\Publish\Core\Repository\Values\Content\Location;
25
use eZ\Publish\SPI\Persistence\Content as SPIContent;
26
use eZ\Publish\SPI\Persistence\Content\Location as SPILocation;
27
use eZ\Publish\SPI\Persistence\Content\VersionInfo as SPIVersionInfo;
28
use eZ\Publish\SPI\Persistence\Content\ContentInfo as SPIContentInfo;
29
use eZ\Publish\SPI\Persistence\Content\Relation as SPIRelation;
30
use eZ\Publish\SPI\Persistence\Content\Type as SPIType;
31
use eZ\Publish\SPI\Persistence\Content\Location\CreateStruct as SPILocationCreateStruct;
32
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
33
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;
34
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentValue;
35
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentType;
36
use DateTime;
37
38
/**
39
 * DomainMapper is an internal service.
40
 *
41
 * @internal Meant for internal use by Repository.
42
 */
43
class DomainMapper
44
{
45
    /**
46
     * @var \eZ\Publish\SPI\Persistence\Content\Handler
47
     */
48
    protected $contentHandler;
49
50
    /**
51
     * @var \eZ\Publish\SPI\Persistence\Content\Location\Handler
52
     */
53
    protected $locationHandler;
54
55
    /**
56
     * @var \eZ\Publish\SPI\Persistence\Content\Type\Handler
57
     */
58
    protected $contentTypeHandler;
59
60
    /**
61
     * @var \eZ\Publish\SPI\Persistence\Content\Language\Handler
62
     */
63
    protected $contentLanguageHandler;
64
65
    /**
66
     * @var FieldTypeRegistry
67
     */
68
    protected $fieldTypeRegistry;
69
70
    /**
71
     * Setups service with reference to repository.
72
     *
73
     * @param \eZ\Publish\SPI\Persistence\Content\Handler $contentHandler
74
     * @param \eZ\Publish\SPI\Persistence\Content\Location\Handler $locationHandler
75
     * @param \eZ\Publish\SPI\Persistence\Content\Type\Handler $contentTypeHandler
76
     * @param \eZ\Publish\SPI\Persistence\Content\Language\Handler $contentLanguageHandler
77
     * @param FieldTypeRegistry $fieldTypeRegistry
78
     */
79
    public function __construct(
80
        ContentHandler $contentHandler,
81
        LocationHandler $locationHandler,
82
        TypeHandler $contentTypeHandler,
83
        LanguageHandler $contentLanguageHandler,
84
        FieldTypeRegistry $fieldTypeRegistry
85
    ) {
86
        $this->contentHandler = $contentHandler;
87
        $this->locationHandler = $locationHandler;
88
        $this->contentTypeHandler = $contentTypeHandler;
89
        $this->contentLanguageHandler = $contentLanguageHandler;
90
        $this->fieldTypeRegistry = $fieldTypeRegistry;
91
    }
92
93
    /**
94
     * Builds a Content domain object from value object returned from persistence.
95
     *
96
     * @param \eZ\Publish\SPI\Persistence\Content $spiContent
97
     * @param ContentType|SPIType $contentType
98
     * @param array|null $fieldLanguages Language codes to filter fields on
99
     * @param string|null $fieldAlwaysAvailableLanguage Language code fallback if a given field is not found in $fieldLanguages
100
     *
101
     * @return \eZ\Publish\Core\Repository\Values\Content\Content
102
     */
103
    public function buildContentDomainObject(SPIContent $spiContent, $contentType = null, array $fieldLanguages = null, $fieldAlwaysAvailableLanguage = null)
104
    {
105
        if ($contentType === null) {
106
            $contentType = $this->contentTypeHandler->load(
107
                $spiContent->versionInfo->contentInfo->contentTypeId
108
            );
109
        }
110
111
        $prioritizedFieldLanguageCode = null;
112
        $prioritizedLanguages = $fieldLanguages ?: [];
113
        if (!empty($prioritizedLanguages)) {
114
            $availableFieldLanguageMap = array_fill_keys($spiContent->versionInfo->languageCodes, true);
115
            foreach ($prioritizedLanguages as $prioritizedLanguage) {
116
                if (isset($availableFieldLanguageMap[$prioritizedLanguage])) {
117
                    $prioritizedFieldLanguageCode = $prioritizedLanguage;
118
                    break;
119
                }
120
            }
121
        }
122
123
        return new Content(
124
            array(
125
                'internalFields' => $this->buildDomainFields($spiContent->fields, $contentType, $fieldLanguages, $fieldAlwaysAvailableLanguage),
126
                'versionInfo' => $this->buildVersionInfoDomainObject($spiContent->versionInfo, $prioritizedLanguages),
127
                'prioritizedFieldLanguageCode' => $prioritizedFieldLanguageCode,
128
            )
129
        );
130
    }
131
132
    /**
133
     * Returns an array of domain fields created from given array of SPI fields.
134
     *
135
     * @throws InvalidArgumentType On invalid $contentType
136
     *
137
     * @param \eZ\Publish\SPI\Persistence\Content\Field[] $spiFields
138
     * @param ContentType|SPIType $contentType
139
     * @param array $languages A language priority, filters returned fields and is used as prioritized language code on
140
     *                         returned value object. If not given all languages are returned.
141
     * @param string|null $alwaysAvailableLanguage Language code fallback if a given field is not found in $languages
142
     *
143
     * @return array
144
     */
145
    public function buildDomainFields(array $spiFields, $contentType, array $languages = null, $alwaysAvailableLanguage = null)
146
    {
147
        if (!$contentType instanceof SPIType && !$contentType instanceof ContentType) {
148
            throw new InvalidArgumentType('$contentType', 'SPI ContentType | API ContentType');
149
        }
150
151
        $fieldIdentifierMap = array();
152
        foreach ($contentType->fieldDefinitions as $fieldDefinitions) {
153
            $fieldIdentifierMap[$fieldDefinitions->id] = $fieldDefinitions->identifier;
154
        }
155
156
        $fieldInFilterLanguagesMap = array();
157
        if ($languages !== null && $alwaysAvailableLanguage !== null) {
158
            foreach ($spiFields as $spiField) {
159
                if (in_array($spiField->languageCode, $languages)) {
160
                    $fieldInFilterLanguagesMap[$spiField->fieldDefinitionId] = true;
161
                }
162
            }
163
        }
164
165
        $fields = array();
166
        foreach ($spiFields as $spiField) {
167
            // We ignore fields in content not part of the content type
168
            if (!isset($fieldIdentifierMap[$spiField->fieldDefinitionId])) {
169
                continue;
170
            }
171
172
            if ($languages !== null && !in_array($spiField->languageCode, $languages)) {
173
                // If filtering is enabled we ignore fields in other languages then $fieldLanguages, if:
174
                if ($alwaysAvailableLanguage === null) {
175
                    // Ignore field if we don't have $alwaysAvailableLanguageCode fallback
176
                    continue;
177
                } elseif (!empty($fieldInFilterLanguagesMap[$spiField->fieldDefinitionId])) {
178
                    // Ignore field if it exists in one of the filtered languages
179
                    continue;
180
                } elseif ($spiField->languageCode !== $alwaysAvailableLanguage) {
181
                    // Also ignore if field is not in $alwaysAvailableLanguageCode
182
                    continue;
183
                }
184
            }
185
186
            $fields[] = new Field(
187
                array(
188
                    'id' => $spiField->id,
189
                    'value' => $this->fieldTypeRegistry->getFieldType($spiField->type)
190
                        ->fromPersistenceValue($spiField->value),
191
                    'languageCode' => $spiField->languageCode,
192
                    'fieldDefIdentifier' => $fieldIdentifierMap[$spiField->fieldDefinitionId],
193
                )
194
            );
195
        }
196
197
        return $fields;
198
    }
199
200
    /**
201
     * Builds a VersionInfo domain object from value object returned from persistence.
202
     *
203
     * @param \eZ\Publish\SPI\Persistence\Content\VersionInfo $spiVersionInfo
204
     * @param array $prioritizedLanguages
205
     *
206
     * @return \eZ\Publish\Core\Repository\Values\Content\VersionInfo
207
     */
208
    public function buildVersionInfoDomainObject(SPIVersionInfo $spiVersionInfo, array $prioritizedLanguages = [])
209
    {
210
        // Map SPI statuses to API
211
        switch ($spiVersionInfo->status) {
212
            case SPIVersionInfo::STATUS_ARCHIVED:
213
                $status = APIVersionInfo::STATUS_ARCHIVED;
214
                break;
215
216
            case SPIVersionInfo::STATUS_PUBLISHED:
217
                $status = APIVersionInfo::STATUS_PUBLISHED;
218
                break;
219
220
            case SPIVersionInfo::STATUS_DRAFT:
221
            default:
222
                $status = APIVersionInfo::STATUS_DRAFT;
223
        }
224
225
        // Find prioritised language among names
226
        $prioritizedNameLanguageCode = null;
227
        foreach ($prioritizedLanguages as $prioritizedLanguage) {
228
            if (isset($spiVersionInfo->names[$prioritizedLanguage])) {
229
                $prioritizedNameLanguageCode = $prioritizedLanguage;
230
                break;
231
            }
232
        }
233
234
        return new VersionInfo(
235
            array(
236
                'id' => $spiVersionInfo->id,
237
                'versionNo' => $spiVersionInfo->versionNo,
238
                'modificationDate' => $this->getDateTime($spiVersionInfo->modificationDate),
239
                'creatorId' => $spiVersionInfo->creatorId,
240
                'creationDate' => $this->getDateTime($spiVersionInfo->creationDate),
241
                'status' => $status,
242
                'initialLanguageCode' => $spiVersionInfo->initialLanguageCode,
243
                'languageCodes' => $spiVersionInfo->languageCodes,
244
                'names' => $spiVersionInfo->names,
245
                'contentInfo' => $this->buildContentInfoDomainObject($spiVersionInfo->contentInfo),
246
                'prioritizedNameLanguageCode' => $prioritizedNameLanguageCode,
247
            )
248
        );
249
    }
250
251
    /**
252
     * Builds a ContentInfo domain object from value object returned from persistence.
253
     *
254
     * @param \eZ\Publish\SPI\Persistence\Content\ContentInfo $spiContentInfo
255
     *
256
     * @return \eZ\Publish\API\Repository\Values\Content\ContentInfo
257
     */
258
    public function buildContentInfoDomainObject(SPIContentInfo $spiContentInfo)
259
    {
260
        return new ContentInfo(
261
            array(
262
                'id' => $spiContentInfo->id,
263
                'contentTypeId' => $spiContentInfo->contentTypeId,
264
                'name' => $spiContentInfo->name,
265
                'sectionId' => $spiContentInfo->sectionId,
266
                'currentVersionNo' => $spiContentInfo->currentVersionNo,
267
                'published' => $spiContentInfo->isPublished,
268
                'ownerId' => $spiContentInfo->ownerId,
269
                'modificationDate' => $spiContentInfo->modificationDate == 0 ?
270
                    null :
271
                    $this->getDateTime($spiContentInfo->modificationDate),
272
                'publishedDate' => $spiContentInfo->publicationDate == 0 ?
273
                    null :
274
                    $this->getDateTime($spiContentInfo->publicationDate),
275
                'alwaysAvailable' => $spiContentInfo->alwaysAvailable,
276
                'remoteId' => $spiContentInfo->remoteId,
277
                'mainLanguageCode' => $spiContentInfo->mainLanguageCode,
278
                'mainLocationId' => $spiContentInfo->mainLocationId,
279
            )
280
        );
281
    }
282
283
    /**
284
     * Builds API Relation object from provided SPI Relation object.
285
     *
286
     * @param \eZ\Publish\SPI\Persistence\Content\Relation $spiRelation
287
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $sourceContentInfo
288
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $destinationContentInfo
289
     *
290
     * @return \eZ\Publish\API\Repository\Values\Content\Relation
291
     */
292
    public function buildRelationDomainObject(
293
        SPIRelation $spiRelation,
294
        ContentInfo $sourceContentInfo,
295
        ContentInfo $destinationContentInfo
296
    ) {
297
        $sourceFieldDefinitionIdentifier = null;
298
        if ($spiRelation->sourceFieldDefinitionId !== null) {
299
            $contentType = $this->contentTypeHandler->load($sourceContentInfo->contentTypeId);
300
            foreach ($contentType->fieldDefinitions as $fieldDefinition) {
301
                if ($fieldDefinition->id !== $spiRelation->sourceFieldDefinitionId) {
302
                    continue;
303
                }
304
305
                $sourceFieldDefinitionIdentifier = $fieldDefinition->identifier;
306
                break;
307
            }
308
        }
309
310
        return new Relation(
311
            array(
312
                'id' => $spiRelation->id,
313
                'sourceFieldDefinitionIdentifier' => $sourceFieldDefinitionIdentifier,
314
                'type' => $spiRelation->type,
315
                'sourceContentInfo' => $sourceContentInfo,
316
                'destinationContentInfo' => $destinationContentInfo,
317
            )
318
        );
319
    }
320
321
    /**
322
     * Builds domain location object from provided persistence location.
323
     *
324
     * @param \eZ\Publish\SPI\Persistence\Content\Location $spiLocation
325
     * @param \eZ\Publish\SPI\Persistence\Content\ContentInfo|null $contentInfo
326
     *
327
     * @return \eZ\Publish\API\Repository\Values\Content\Location
328
     */
329
    public function buildLocationDomainObject(SPILocation $spiLocation, SPIContentInfo $contentInfo = null)
330
    {
331
        // TODO: this is hardcoded workaround for missing ContentInfo on root location
332
        if ($spiLocation->id == 1) {
333
            $legacyDateTime = $this->getDateTime(1030968000); //  first known commit of eZ Publish 3.x
334
            $contentInfo = new ContentInfo(
335
                array(
336
                    'id' => 0,
337
                    'name' => 'Top Level Nodes',
338
                    'sectionId' => 1,
339
                    'mainLocationId' => 1,
340
                    'contentTypeId' => 1,
341
                    'currentVersionNo' => 1,
342
                    'published' => 1,
343
                    'ownerId' => 14, // admin user
344
                    'modificationDate' => $legacyDateTime,
345
                    'publishedDate' => $legacyDateTime,
346
                    'alwaysAvailable' => 1,
347
                    'remoteId' => null,
348
                    'mainLanguageCode' => 'eng-GB',
349
                )
350
            );
351
        } else {
352
            $contentInfo = $this->buildContentInfoDomainObject(
353
                $contentInfo ?: $this->contentHandler->loadContentInfo($spiLocation->contentId)
354
            );
355
        }
356
357
        return new Location(
358
            array(
359
                'contentInfo' => $contentInfo,
360
                'id' => $spiLocation->id,
361
                'priority' => $spiLocation->priority,
362
                'hidden' => $spiLocation->hidden,
363
                'invisible' => $spiLocation->invisible,
364
                'remoteId' => $spiLocation->remoteId,
365
                'parentLocationId' => $spiLocation->parentId,
366
                'pathString' => $spiLocation->pathString,
367
                'depth' => $spiLocation->depth,
368
                'sortField' => $spiLocation->sortField,
369
                'sortOrder' => $spiLocation->sortOrder,
370
            )
371
        );
372
    }
373
374
    /**
375
     * Build API Location and corresponding ContentInfo domain objects and apply to LocationSearchResult.
376
     *
377
     * Loading of ContentInfo objects are done in one operation.
378
     *
379
     * @param \eZ\Publish\API\Repository\Values\Content\Search\SearchResult $result SPI search result with SPI Location items as hits
380
     *
381
     * @return \eZ\Publish\API\Repository\Values\Content\Search\SearchResult Ready built API search result object.
382
     */
383
    public function buildLocationDomainObjectsOnSearchResult(SearchResult $result)
384
    {
385
        $contentIds = [];
386
        foreach ($result->searchHits as $hit) {
387
            $contentIds[] = $hit->valueObject->contentId;
0 ignored issues
show
Documentation introduced by
The property contentId does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
388
        }
389
390
        $contentInfoList = $this->contentHandler->loadContentInfoList($contentIds);
391
        foreach ($result->searchHits as $key => $hit) {
392
            $hit->valueObject = $this->buildLocationDomainObject(
393
                $hit->valueObject,
0 ignored issues
show
Compatibility introduced by
$hit->valueObject of type object<eZ\Publish\API\Re...ory\Values\ValueObject> is not a sub-type of object<eZ\Publish\SPI\Pe...tence\Content\Location>. It seems like you assume a child class of the class eZ\Publish\API\Repository\Values\ValueObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
394
                $contentInfoList[$hit->valueObject->contentId]
0 ignored issues
show
Documentation introduced by
The property contentId does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
395
            );
396
        }
397
398
        return $result;
399
    }
400
401
    /**
402
     * Creates an array of SPI location create structs from given array of API location create structs.
403
     *
404
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
405
     *
406
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct $locationCreateStruct
407
     * @param \eZ\Publish\API\Repository\Values\Content\Location $parentLocation
408
     * @param mixed $mainLocation
409
     * @param mixed $contentId
410
     * @param mixed $contentVersionNo
411
     *
412
     * @return \eZ\Publish\SPI\Persistence\Content\Location\CreateStruct
413
     */
414
    public function buildSPILocationCreateStruct(
415
        $locationCreateStruct,
416
        APILocation $parentLocation,
417
        $mainLocation,
418
        $contentId,
419
        $contentVersionNo
420
    ) {
421
        if ($locationCreateStruct->priority !== null && !is_int($locationCreateStruct->priority)) {
422
            throw new InvalidArgumentValue('priority', $locationCreateStruct->priority, 'LocationCreateStruct');
423
        }
424
425
        if (!is_bool($locationCreateStruct->hidden)) {
426
            throw new InvalidArgumentValue('hidden', $locationCreateStruct->hidden, 'LocationCreateStruct');
427
        }
428
429
        if ($locationCreateStruct->remoteId !== null && (!is_string($locationCreateStruct->remoteId) || empty($locationCreateStruct->remoteId))) {
430
            throw new InvalidArgumentValue('remoteId', $locationCreateStruct->remoteId, 'LocationCreateStruct');
431
        }
432
433
        if ($locationCreateStruct->sortField !== null && !$this->isValidLocationSortField($locationCreateStruct->sortField)) {
434
            throw new InvalidArgumentValue('sortField', $locationCreateStruct->sortField, 'LocationCreateStruct');
435
        }
436
437
        if ($locationCreateStruct->sortOrder !== null && !$this->isValidLocationSortOrder($locationCreateStruct->sortOrder)) {
438
            throw new InvalidArgumentValue('sortOrder', $locationCreateStruct->sortOrder, 'LocationCreateStruct');
439
        }
440
441
        $remoteId = $locationCreateStruct->remoteId;
442
        if (null === $remoteId) {
443
            $remoteId = $this->getUniqueHash($locationCreateStruct);
444
        } else {
445
            try {
446
                $this->locationHandler->loadByRemoteId($remoteId);
447
                throw new InvalidArgumentException(
448
                    '$locationCreateStructs',
449
                    "Another Location with remoteId '{$remoteId}' exists"
450
                );
451
            } catch (NotFoundException $e) {
452
                // Do nothing
453
            }
454
        }
455
456
        return new SPILocationCreateStruct(
457
            array(
458
                'priority' => $locationCreateStruct->priority,
459
                'hidden' => $locationCreateStruct->hidden,
460
                // If we declare the new Location as hidden, it is automatically invisible
461
                // Otherwise it picks up visibility from parent Location
462
                // Note: There is no need to check for hidden status of parent, as hidden Location
463
                // is always invisible as well
464
                'invisible' => ($locationCreateStruct->hidden === true || $parentLocation->invisible),
465
                'remoteId' => $remoteId,
466
                'contentId' => $contentId,
467
                'contentVersion' => $contentVersionNo,
468
                // pathIdentificationString will be set in storage
469
                'pathIdentificationString' => null,
470
                'mainLocationId' => $mainLocation,
471
                'sortField' => $locationCreateStruct->sortField !== null ? $locationCreateStruct->sortField : Location::SORT_FIELD_NAME,
472
                'sortOrder' => $locationCreateStruct->sortOrder !== null ? $locationCreateStruct->sortOrder : Location::SORT_ORDER_ASC,
473
                'parentId' => $locationCreateStruct->parentLocationId,
474
            )
475
        );
476
    }
477
478
    /**
479
     * Checks if given $sortField value is one of the defined sort field constants.
480
     *
481
     * @param mixed $sortField
482
     *
483
     * @return bool
484
     */
485
    public function isValidLocationSortField($sortField)
486
    {
487
        switch ($sortField) {
488
            case APILocation::SORT_FIELD_PATH:
489
            case APILocation::SORT_FIELD_PUBLISHED:
490
            case APILocation::SORT_FIELD_MODIFIED:
491
            case APILocation::SORT_FIELD_SECTION:
492
            case APILocation::SORT_FIELD_DEPTH:
493
            case APILocation::SORT_FIELD_CLASS_IDENTIFIER:
494
            case APILocation::SORT_FIELD_CLASS_NAME:
495
            case APILocation::SORT_FIELD_PRIORITY:
496
            case APILocation::SORT_FIELD_NAME:
497
            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...
498
            case APILocation::SORT_FIELD_NODE_ID:
499
            case APILocation::SORT_FIELD_CONTENTOBJECT_ID:
500
                return true;
501
        }
502
503
        return false;
504
    }
505
506
    /**
507
     * Checks if given $sortOrder value is one of the defined sort order constants.
508
     *
509
     * @param mixed $sortOrder
510
     *
511
     * @return bool
512
     */
513
    public function isValidLocationSortOrder($sortOrder)
514
    {
515
        switch ($sortOrder) {
516
            case APILocation::SORT_ORDER_DESC:
517
            case APILocation::SORT_ORDER_ASC:
518
                return true;
519
        }
520
521
        return false;
522
    }
523
524
    /**
525
     * Validates given translated list $list, which should be an array of strings with language codes as keys.
526
     *
527
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
528
     *
529
     * @param mixed $list
530
     * @param string $argumentName
531
     */
532
    public function validateTranslatedList($list, $argumentName)
533
    {
534
        if (!is_array($list)) {
535
            throw new InvalidArgumentType($argumentName, 'array', $list);
536
        }
537
538
        foreach ($list as $languageCode => $translation) {
539
            $this->contentLanguageHandler->loadByLanguageCode($languageCode);
540
541
            if (!is_string($translation)) {
542
                throw new InvalidArgumentType($argumentName . "['$languageCode']", 'string', $translation);
543
            }
544
        }
545
    }
546
547
    /**
548
     * Returns \DateTime object from given $timestamp in environment timezone.
549
     *
550
     * This method is needed because constructing \DateTime with $timestamp will
551
     * return the object in UTC timezone.
552
     *
553
     * @param int $timestamp
554
     *
555
     * @return \DateTime
556
     */
557
    public function getDateTime($timestamp)
558
    {
559
        $dateTime = new DateTime();
560
        $dateTime->setTimestamp($timestamp);
561
562
        return $dateTime;
563
    }
564
565
    /**
566
     * Creates unique hash string for given $object.
567
     *
568
     * Used for remoteId.
569
     *
570
     * @param object $object
571
     *
572
     * @return string
573
     */
574
    public function getUniqueHash($object)
575
    {
576
        return md5(uniqid(get_class($object), true));
577
    }
578
}
579