Completed
Push — master ( 97e40f...89ec5c )
by André
40:26 queued 12:35
created

DomainMapper::buildContentDomainObject()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 17
nc 16
nop 4
dl 0
loc 28
rs 8.439
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
                    'fieldTypeIdentifier' => $spiField->type,
194
                )
195
            );
196
        }
197
198
        return $fields;
199
    }
200
201
    /**
202
     * Builds a VersionInfo domain object from value object returned from persistence.
203
     *
204
     * @param \eZ\Publish\SPI\Persistence\Content\VersionInfo $spiVersionInfo
205
     * @param array $prioritizedLanguages
206
     *
207
     * @return \eZ\Publish\Core\Repository\Values\Content\VersionInfo
208
     */
209
    public function buildVersionInfoDomainObject(SPIVersionInfo $spiVersionInfo, array $prioritizedLanguages = [])
210
    {
211
        // Map SPI statuses to API
212
        switch ($spiVersionInfo->status) {
213
            case SPIVersionInfo::STATUS_ARCHIVED:
214
                $status = APIVersionInfo::STATUS_ARCHIVED;
215
                break;
216
217
            case SPIVersionInfo::STATUS_PUBLISHED:
218
                $status = APIVersionInfo::STATUS_PUBLISHED;
219
                break;
220
221
            case SPIVersionInfo::STATUS_DRAFT:
222
            default:
223
                $status = APIVersionInfo::STATUS_DRAFT;
224
        }
225
226
        // Find prioritised language among names
227
        $prioritizedNameLanguageCode = null;
228
        foreach ($prioritizedLanguages as $prioritizedLanguage) {
229
            if (isset($spiVersionInfo->names[$prioritizedLanguage])) {
230
                $prioritizedNameLanguageCode = $prioritizedLanguage;
231
                break;
232
            }
233
        }
234
235
        return new VersionInfo(
236
            array(
237
                'id' => $spiVersionInfo->id,
238
                'versionNo' => $spiVersionInfo->versionNo,
239
                'modificationDate' => $this->getDateTime($spiVersionInfo->modificationDate),
240
                'creatorId' => $spiVersionInfo->creatorId,
241
                'creationDate' => $this->getDateTime($spiVersionInfo->creationDate),
242
                'status' => $status,
243
                'initialLanguageCode' => $spiVersionInfo->initialLanguageCode,
244
                'languageCodes' => $spiVersionInfo->languageCodes,
245
                'names' => $spiVersionInfo->names,
246
                'contentInfo' => $this->buildContentInfoDomainObject($spiVersionInfo->contentInfo),
247
                'prioritizedNameLanguageCode' => $prioritizedNameLanguageCode,
248
            )
249
        );
250
    }
251
252
    /**
253
     * Builds a ContentInfo domain object from value object returned from persistence.
254
     *
255
     * @param \eZ\Publish\SPI\Persistence\Content\ContentInfo $spiContentInfo
256
     *
257
     * @return \eZ\Publish\API\Repository\Values\Content\ContentInfo
258
     */
259
    public function buildContentInfoDomainObject(SPIContentInfo $spiContentInfo)
260
    {
261
        return new ContentInfo(
262
            array(
263
                'id' => $spiContentInfo->id,
264
                'contentTypeId' => $spiContentInfo->contentTypeId,
265
                'name' => $spiContentInfo->name,
266
                'sectionId' => $spiContentInfo->sectionId,
267
                'currentVersionNo' => $spiContentInfo->currentVersionNo,
268
                'published' => $spiContentInfo->isPublished,
269
                'ownerId' => $spiContentInfo->ownerId,
270
                'modificationDate' => $spiContentInfo->modificationDate == 0 ?
271
                    null :
272
                    $this->getDateTime($spiContentInfo->modificationDate),
273
                'publishedDate' => $spiContentInfo->publicationDate == 0 ?
274
                    null :
275
                    $this->getDateTime($spiContentInfo->publicationDate),
276
                'alwaysAvailable' => $spiContentInfo->alwaysAvailable,
277
                'remoteId' => $spiContentInfo->remoteId,
278
                'mainLanguageCode' => $spiContentInfo->mainLanguageCode,
279
                'mainLocationId' => $spiContentInfo->mainLocationId,
280
            )
281
        );
282
    }
283
284
    /**
285
     * Builds API Relation object from provided SPI Relation object.
286
     *
287
     * @param \eZ\Publish\SPI\Persistence\Content\Relation $spiRelation
288
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $sourceContentInfo
289
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $destinationContentInfo
290
     *
291
     * @return \eZ\Publish\API\Repository\Values\Content\Relation
292
     */
293
    public function buildRelationDomainObject(
294
        SPIRelation $spiRelation,
295
        ContentInfo $sourceContentInfo,
296
        ContentInfo $destinationContentInfo
297
    ) {
298
        $sourceFieldDefinitionIdentifier = null;
299
        if ($spiRelation->sourceFieldDefinitionId !== null) {
300
            $contentType = $this->contentTypeHandler->load($sourceContentInfo->contentTypeId);
301
            foreach ($contentType->fieldDefinitions as $fieldDefinition) {
302
                if ($fieldDefinition->id !== $spiRelation->sourceFieldDefinitionId) {
303
                    continue;
304
                }
305
306
                $sourceFieldDefinitionIdentifier = $fieldDefinition->identifier;
307
                break;
308
            }
309
        }
310
311
        return new Relation(
312
            array(
313
                'id' => $spiRelation->id,
314
                'sourceFieldDefinitionIdentifier' => $sourceFieldDefinitionIdentifier,
315
                'type' => $spiRelation->type,
316
                'sourceContentInfo' => $sourceContentInfo,
317
                'destinationContentInfo' => $destinationContentInfo,
318
            )
319
        );
320
    }
321
322
    /**
323
     * Builds domain location object from provided persistence location.
324
     *
325
     * @param \eZ\Publish\SPI\Persistence\Content\Location $spiLocation
326
     * @param \eZ\Publish\SPI\Persistence\Content\ContentInfo|null $contentInfo
327
     *
328
     * @return \eZ\Publish\API\Repository\Values\Content\Location
329
     */
330
    public function buildLocationDomainObject(SPILocation $spiLocation, SPIContentInfo $contentInfo = null)
331
    {
332
        // TODO: this is hardcoded workaround for missing ContentInfo on root location
333
        if ($spiLocation->id == 1) {
334
            $legacyDateTime = $this->getDateTime(1030968000); //  first known commit of eZ Publish 3.x
335
            $contentInfo = new ContentInfo(
336
                array(
337
                    'id' => 0,
338
                    'name' => 'Top Level Nodes',
339
                    'sectionId' => 1,
340
                    'mainLocationId' => 1,
341
                    'contentTypeId' => 1,
342
                    'currentVersionNo' => 1,
343
                    'published' => 1,
344
                    'ownerId' => 14, // admin user
345
                    'modificationDate' => $legacyDateTime,
346
                    'publishedDate' => $legacyDateTime,
347
                    'alwaysAvailable' => 1,
348
                    'remoteId' => null,
349
                    'mainLanguageCode' => 'eng-GB',
350
                )
351
            );
352
        } else {
353
            $contentInfo = $this->buildContentInfoDomainObject(
354
                $contentInfo ?: $this->contentHandler->loadContentInfo($spiLocation->contentId)
355
            );
356
        }
357
358
        return new Location(
359
            array(
360
                'contentInfo' => $contentInfo,
361
                'id' => $spiLocation->id,
362
                'priority' => $spiLocation->priority,
363
                'hidden' => $spiLocation->hidden,
364
                'invisible' => $spiLocation->invisible,
365
                'remoteId' => $spiLocation->remoteId,
366
                'parentLocationId' => $spiLocation->parentId,
367
                'pathString' => $spiLocation->pathString,
368
                'depth' => $spiLocation->depth,
369
                'sortField' => $spiLocation->sortField,
370
                'sortOrder' => $spiLocation->sortOrder,
371
            )
372
        );
373
    }
374
375
    /**
376
     * Build API Location and corresponding ContentInfo domain objects and apply to LocationSearchResult.
377
     *
378
     * Loading of ContentInfo objects are done in one operation.
379
     *
380
     * @param \eZ\Publish\API\Repository\Values\Content\Search\SearchResult $result SPI search result with SPI Location items as hits
381
     *
382
     * @return \eZ\Publish\SPI\Persistence\Content\Location[] Locations we did not find content info for is retunred as an array.
383
     */
384
    public function buildLocationDomainObjectsOnSearchResult(SearchResult $result)
385
    {
386
        $contentIds = [];
387
        foreach ($result->searchHits as $hit) {
388
            $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...
389
        }
390
391
        $missingLocations = [];
392
        $contentInfoList = $this->contentHandler->loadContentInfoList($contentIds);
393
        foreach ($result->searchHits as $key => $hit) {
394
            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...
395
                $hit->valueObject = $this->buildLocationDomainObject(
396
                    $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...
397
                    $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...
398
                );
399
            } else {
400
                $missingLocations[] = $hit->valueObject;
401
                unset($result->searchHits[$key]);
402
                --$result->totalCount;
403
            }
404
        }
405
406
        return $missingLocations;
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