Completed
Push — 7.0_deprecation_removal ( e8d685 )
by André
23:55
created

buildLocationDomainObjectsOnSearchResult()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

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