Completed
Push — 7.5 ( 5ae6a9...706a7c )
by Łukasz
18:26
created

Handler::setContentStates()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
5
 * @license For full copyright and license information view LICENSE file distributed with this source code.
6
 */
7
namespace eZ\Publish\Core\Persistence\Legacy\Content\Location;
8
9
use eZ\Publish\SPI\Persistence\Content;
10
use eZ\Publish\SPI\Persistence\Content\Location;
11
use eZ\Publish\SPI\Persistence\Content\Location\CreateStruct;
12
use eZ\Publish\SPI\Persistence\Content\Location\UpdateStruct;
13
use eZ\Publish\SPI\Persistence\Content\Location\Handler as BaseLocationHandler;
14
use eZ\Publish\Core\Persistence\Legacy\Content\Handler as ContentHandler;
15
use eZ\Publish\Core\Persistence\Legacy\Content\TreeHandler;
16
use eZ\Publish\Core\Persistence\Legacy\Content\ObjectState\Handler as ObjectStateHandler;
17
use eZ\Publish\Core\Persistence\Legacy\Content\Location\Gateway as LocationGateway;
18
use eZ\Publish\Core\Persistence\Legacy\Content\Location\Mapper as LocationMapper;
19
use eZ\Publish\SPI\Persistence\Content\MetadataUpdateStruct;
20
use eZ\Publish\SPI\Persistence\Content\Location\Trashed;
21
22
/**
23
 * The Location Handler interface defines operations on Location elements in the storage engine.
24
 */
25
class Handler implements BaseLocationHandler
26
{
27
    /**
28
     * Gateway for handling location data.
29
     *
30
     * @var \eZ\Publish\Core\Persistence\Legacy\Content\Location\Gateway
31
     */
32
    protected $locationGateway;
33
34
    /**
35
     * Location locationMapper.
36
     *
37
     * @var \eZ\Publish\Core\Persistence\Legacy\Content\Location\Mapper
38
     */
39
    protected $locationMapper;
40
41
    /**
42
     * Content handler.
43
     *
44
     * @var \eZ\Publish\Core\Persistence\Legacy\Content\Handler
45
     */
46
    protected $contentHandler;
47
48
    /**
49
     * Object state handler.
50
     *
51
     * @var \eZ\Publish\Core\Persistence\Legacy\Content\ObjectState\Handler
52
     */
53
    protected $objectStateHandler;
54
55
    /**
56
     * Tree handler.
57
     *
58
     * @var \eZ\Publish\Core\Persistence\Legacy\Content\TreeHandler
59
     */
60
    protected $treeHandler;
61
62
    /**
63
     * Construct from userGateway.
64
     *
65
     * @param \eZ\Publish\Core\Persistence\Legacy\Content\Location\Gateway $locationGateway
66
     * @param \eZ\Publish\Core\Persistence\Legacy\Content\Location\Mapper $locationMapper
67
     * @param \eZ\Publish\Core\Persistence\Legacy\Content\Handler $contentHandler
68
     * @param \eZ\Publish\Core\Persistence\Legacy\Content\ObjectState\Handler $objectStateHandler
69
     * @param \eZ\Publish\Core\Persistence\Legacy\Content\TreeHandler $treeHandler
70
     *
71
     * @return \eZ\Publish\Core\Persistence\Legacy\Content\Location\Handler
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
72
     */
73
    public function __construct(
74
        LocationGateway $locationGateway,
75
        LocationMapper $locationMapper,
76
        ContentHandler $contentHandler,
77
        ObjectStateHandler $objectStateHandler,
78
        TreeHandler $treeHandler
79
    ) {
80
        $this->locationGateway = $locationGateway;
81
        $this->locationMapper = $locationMapper;
82
        $this->contentHandler = $contentHandler;
83
        $this->objectStateHandler = $objectStateHandler;
84
        $this->treeHandler = $treeHandler;
85
    }
86
87
    /**
88
     * Returns parent path string for a path string.
89
     *
90
     * @param string $pathString
91
     *
92
     * @return string
93
     */
94
    protected function getParentPathString($pathString)
95
    {
96
        return implode('/', array_slice(explode('/', $pathString), 0, -2)) . '/';
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102
    public function load($locationId, array $translations = null, bool $useAlwaysAvailable = true)
103
    {
104
        return $this->treeHandler->loadLocation($locationId, $translations, $useAlwaysAvailable);
0 ignored issues
show
Bug introduced by
It seems like $translations defined by parameter $translations on line 102 can also be of type array; however, eZ\Publish\Core\Persiste...Handler::loadLocation() does only seem to accept null|array<integer,string>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110
    public function loadList(array $locationIds, array $translations = null, bool $useAlwaysAvailable = true): iterable
111
    {
112
        $list = $this->locationGateway->getNodeDataList($locationIds, $translations, $useAlwaysAvailable);
0 ignored issues
show
Bug introduced by
It seems like $translations defined by parameter $translations on line 110 can also be of type array; however, eZ\Publish\Core\Persiste...eway::getNodeDataList() does only seem to accept null|array<integer,string>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
113
114
        $locations = [];
115
        foreach ($list as $row) {
116
            $id = (int)$row['node_id'];
117
            if (!isset($locations[$id])) {
118
                $locations[$id] = $this->locationMapper->createLocationFromRow($row);
119
            }
120
        }
121
122
        return $locations;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $locations; (array) is incompatible with the return type declared by the interface eZ\Publish\SPI\Persisten...ation\Handler::loadList of type eZ\Publish\SPI\Persisten...ntent\Location\iterable.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
123
    }
124
125
    /**
126
     * Loads the subtree ids of the location identified by $locationId.
127
     *
128
     * @param int $locationId
129
     *
130
     * @return array Location ids are in the index, Content ids in the value.
131
     */
132
    public function loadSubtreeIds($locationId)
133
    {
134
        return $this->locationGateway->getSubtreeContent($locationId, true);
135
    }
136
137
    /**
138
     * {@inheritdoc}
139
     */
140
    public function loadByRemoteId($remoteId, array $translations = null, bool $useAlwaysAvailable = true)
141
    {
142
        $data = $this->locationGateway->getBasicNodeDataByRemoteId($remoteId, $translations, $useAlwaysAvailable);
0 ignored issues
show
Bug introduced by
It seems like $translations defined by parameter $translations on line 140 can also be of type array; however, eZ\Publish\Core\Persiste...sicNodeDataByRemoteId() does only seem to accept null|array<integer,string>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
143
144
        return $this->locationMapper->createLocationFromRow($data);
145
    }
146
147
    /**
148
     * Loads all locations for $contentId, optionally limited to a sub tree
149
     * identified by $rootLocationId.
150
     *
151
     * @param int $contentId
152
     * @param int $rootLocationId
153
     *
154
     * @return \eZ\Publish\SPI\Persistence\Content\Location[]
155
     */
156
    public function loadLocationsByContent($contentId, $rootLocationId = null)
157
    {
158
        $rows = $this->locationGateway->loadLocationDataByContent($contentId, $rootLocationId);
159
160
        return $this->locationMapper->createLocationsFromRows($rows);
161
    }
162
163
    /**
164
     * {@inheritdoc}
165
     */
166
    public function loadLocationsByTrashContent(int $contentId, ?int $rootLocationId = null): array
167
    {
168
        $rows = $this->locationGateway->loadLocationDataByTrashContent($contentId, $rootLocationId);
169
170
        return $this->locationMapper->createLocationsFromRows($rows, '', new Trashed());
171
    }
172
173
    /**
174
     * @see \eZ\Publish\SPI\Persistence\Content\Location\Handler::loadParentLocationsForDraftContent
175
     */
176
    public function loadParentLocationsForDraftContent($contentId)
177
    {
178
        $rows = $this->locationGateway->loadParentLocationsDataForDraftContent($contentId);
179
180
        return $this->locationMapper->createLocationsFromRows($rows);
181
    }
182
183
    /**
184
     * Returns an array of default content states with content state group id as key.
185
     *
186
     * @return \eZ\Publish\SPI\Persistence\Content\ObjectState[]
187
     */
188
    protected function getDefaultContentStates()
189
    {
190
        $defaultObjectStatesMap = [];
191
192
        foreach ($this->objectStateHandler->loadAllGroups() as $objectStateGroup) {
193
            foreach ($this->objectStateHandler->loadObjectStates($objectStateGroup->id) as $objectState) {
194
                // Only register the first object state which is the default one.
195
                $defaultObjectStatesMap[$objectStateGroup->id] = $objectState;
196
                break;
197
            }
198
        }
199
200
        return $defaultObjectStatesMap;
201
    }
202
203
    /**
204
     * @param Content $content
205
     * @param \eZ\Publish\SPI\Persistence\Content\ObjectState[] $contentStates
206
     */
207
    protected function setContentStates(Content $content, array $contentStates)
208
    {
209
        foreach ($contentStates as $contentStateGroupId => $contentState) {
210
            $this->objectStateHandler->setContentState(
211
                $content->versionInfo->contentInfo->id,
212
                $contentStateGroupId,
213
                $contentState->id
214
            );
215
        }
216
    }
217
218
    /**
219
     * Copy location object identified by $sourceId, into destination identified by $destinationParentId.
220
     *
221
     * Performs a deep copy of the location identified by $sourceId and all of
222
     * its child locations, copying the most recent published content object
223
     * for each location to a new content object without any additional version
224
     * information. Relations are not copied. URLs are not touched at all.
225
     *
226
     * @todo Either move to async/batch or find ways toward optimizing away operations per object.
227
     * @todo Optionally retain dates and set creator
228
     *
229
     * @param mixed $sourceId
230
     * @param mixed $destinationParentId
231
     * @param int|null $newOwnerId
232
     *
233
     * @return Location the newly created Location.
234
     *
235
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
236
     */
237
    public function copySubtree($sourceId, $destinationParentId, $newOwnerId = null)
238
    {
239
        $children = $this->locationGateway->getSubtreeContent($sourceId);
240
        $destinationParentData = $this->locationGateway->getBasicNodeData($destinationParentId);
241
        $defaultObjectStates = $this->getDefaultContentStates();
242
        $contentMap = [];
243
        $locationMap = [
244
            $children[0]['parent_node_id'] => [
245
                'id' => $destinationParentId,
246
                'hidden' => (bool)$destinationParentData['is_hidden'],
247
                'invisible' => (bool)$destinationParentData['is_invisible'],
248
                'path_identification_string' => $destinationParentData['path_identification_string'],
249
            ],
250
        ];
251
252
        $locations = [];
253
        foreach ($children as $child) {
254
            $locations[$child['contentobject_id']][$child['node_id']] = true;
255
        }
256
257
        $time = time();
258
        $mainLocations = [];
259
        $mainLocationsUpdate = [];
260
        foreach ($children as $index => $child) {
261
            // Copy content
262
            if (!isset($contentMap[$child['contentobject_id']])) {
263
                $content = $this->contentHandler->copy(
264
                    (int)$child['contentobject_id'],
265
                    (int)$child['contentobject_version'],
266
                    $newOwnerId
267
                );
268
269
                $this->setContentStates($content, $defaultObjectStates);
270
271
                $content = $this->contentHandler->publish(
272
                    $content->versionInfo->contentInfo->id,
273
                    $content->versionInfo->contentInfo->currentVersionNo,
274
                    new MetadataUpdateStruct(
275
                        [
276
                            'publicationDate' => $time,
277
                            'modificationDate' => $time,
278
                        ]
279
                    )
280
                );
281
282
                $contentMap[$child['contentobject_id']] = $content->versionInfo->contentInfo->id;
283
            }
284
285
            $createStruct = $this->locationMapper->getLocationCreateStruct($child);
286
            $createStruct->contentId = $contentMap[$child['contentobject_id']];
287
            $parentData = $locationMap[$child['parent_node_id']];
288
            $createStruct->parentId = $parentData['id'];
289
            $createStruct->invisible = $createStruct->hidden || $parentData['hidden'] || $parentData['invisible'];
290
            $pathString = explode('/', $child['path_identification_string']);
291
            $pathString = end($pathString);
292
            $createStruct->pathIdentificationString = strlen($pathString) > 0
293
                ? $parentData['path_identification_string'] . '/' . $pathString
294
                : null;
295
296
            // Use content main location if already set, otherwise create location as main
297
            if (isset($mainLocations[$child['contentobject_id']])) {
298
                $createStruct->mainLocationId = $locationMap[$mainLocations[$child['contentobject_id']]]['id'];
299
            } else {
300
                $createStruct->mainLocationId = true;
301
                $mainLocations[$child['contentobject_id']] = $child['node_id'];
302
303
                // If needed mark for update
304
                if (
305
                    isset($locations[$child['contentobject_id']][$child['main_node_id']]) &&
306
                    count($locations[$child['contentobject_id']]) > 1 &&
307
                    $child['node_id'] !== $child['main_node_id']
308
                ) {
309
                    $mainLocationsUpdate[$child['contentobject_id']] = $child['main_node_id'];
310
                }
311
            }
312
313
            $newLocation = $this->create($createStruct);
314
315
            $locationMap[$child['node_id']] = [
316
                'id' => $newLocation->id,
317
                'hidden' => $newLocation->hidden,
318
                'invisible' => $newLocation->invisible,
319
                'path_identification_string' => $newLocation->pathIdentificationString,
320
            ];
321
            if ($index === 0) {
322
                $copiedSubtreeRootLocation = $newLocation;
323
            }
324
        }
325
326
        // Update main locations
327
        foreach ($mainLocationsUpdate as $contentId => $mainLocationId) {
328
            $this->changeMainLocation(
329
                $contentMap[$contentId],
330
                $locationMap[$mainLocationId]['id']
331
            );
332
        }
333
334
        $destinationParentSectionId = $this->getSectionId($destinationParentId);
335
        $this->updateSubtreeSectionIfNecessary($copiedSubtreeRootLocation, $destinationParentSectionId);
0 ignored issues
show
Bug introduced by
The variable $copiedSubtreeRootLocation does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
336
337
        return $copiedSubtreeRootLocation;
338
    }
339
340
    /**
341
     * Retrieves section ID of the location's content.
342
     *
343
     * @param int $locationId
344
     *
345
     * @return int
346
     */
347
    private function getSectionId($locationId)
348
    {
349
        $location = $this->load($locationId);
350
        $locationContentInfo = $this->contentHandler->loadContentInfo($location->contentId);
351
352
        return $locationContentInfo->sectionId;
353
    }
354
355
    /**
356
     * If the location is the main location for its content, updates subtree section.
357
     *
358
     * @param Location $location
359
     * @param int $sectionId
360
     */
361
    private function updateSubtreeSectionIfNecessary(Location $location, $sectionId)
362
    {
363
        if ($this->isMainLocation($location)) {
364
            $this->setSectionForSubtree($location->id, $sectionId);
365
        }
366
    }
367
368
    /**
369
     * Checks if the location is the main location for its content.
370
     *
371
     * @param Location $location
372
     *
373
     * @return bool
374
     */
375
    private function isMainLocation(Location $location)
376
    {
377
        $locationContentInfo = $this->contentHandler->loadContentInfo($location->contentId);
378
379
        return $locationContentInfo->mainLocationId === $location->id;
380
    }
381
382
    /**
383
     * Moves location identified by $sourceId into new parent identified by $destinationParentId.
384
     *
385
     * Performs a full move of the location identified by $sourceId to a new
386
     * destination, identified by $destinationParentId. Relations do not need
387
     * to be updated, since they refer to Content. URLs are not touched.
388
     *
389
     * @param mixed $sourceId
390
     * @param mixed $destinationParentId
391
     *
392
     * @return bool
393
     */
394
    public function move($sourceId, $destinationParentId)
395
    {
396
        $sourceNodeData = $this->locationGateway->getBasicNodeData($sourceId);
397
        $destinationNodeData = $this->locationGateway->getBasicNodeData($destinationParentId);
398
399
        $this->locationGateway->moveSubtreeNodes(
400
            $sourceNodeData,
401
            $destinationNodeData
402
        );
403
404
        $this->locationGateway->updateNodeAssignment(
405
            $sourceNodeData['contentobject_id'],
406
            $sourceNodeData['parent_node_id'],
407
            $destinationParentId,
408
            Gateway::NODE_ASSIGNMENT_OP_CODE_MOVE
409
        );
410
411
        $sourceLocation = $this->load($sourceId);
412
        $destinationParentSectionId = $this->getSectionId($destinationParentId);
413
        $this->updateSubtreeSectionIfNecessary($sourceLocation, $destinationParentSectionId);
414
    }
415
416
    /**
417
     * Marks the given nodes and all ancestors as modified.
418
     *
419
     * Optionally a time stamp with the modification date may be specified,
420
     * otherwise the current time is used.
421
     *
422
     * @param int|string $locationId
423
     * @param int $timestamp
424
     */
425
    public function markSubtreeModified($locationId, $timestamp = null)
426
    {
427
        $nodeData = $this->locationGateway->getBasicNodeData($locationId);
428
        $timestamp = $timestamp ?: time();
429
        $this->locationGateway->updateSubtreeModificationTime($nodeData['path_string'], $timestamp);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\Core\Persiste...btreeModificationTime() has been deprecated with message: Not supposed to be in use anymore.

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

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

Loading history...
430
    }
431
432
    /**
433
     * Sets a location to be hidden, and it self + all children to invisible.
434
     *
435
     * @param mixed $id Location ID
436
     */
437
    public function hide($id)
438
    {
439
        $sourceNodeData = $this->locationGateway->getBasicNodeData($id);
440
441
        $this->locationGateway->hideSubtree($sourceNodeData['path_string']);
442
    }
443
444
    /**
445
     * Sets a location to be unhidden, and self + children to visible unless a parent is hiding the tree.
446
     * If not make sure only children down to first hidden node is marked visible.
447
     *
448
     * @param mixed $id
449
     */
450
    public function unHide($id)
451
    {
452
        $sourceNodeData = $this->locationGateway->getBasicNodeData($id);
453
454
        $this->locationGateway->unhideSubtree($sourceNodeData['path_string']);
455
    }
456
457
    /**
458
     * Sets a location + all children to invisible.
459
     *
460
     * @param int $id Location ID
461
     */
462
    public function setInvisible(int $id): void
463
    {
464
        $sourceNodeData = $this->locationGateway->getBasicNodeData($id);
465
466
        $this->locationGateway->setNodeWithChildrenInvisible($sourceNodeData['path_string']);
467
    }
468
469
    /**
470
     * Sets a location + all children to visible.
471
     *
472
     * @param int $id Location ID
473
     */
474
    public function setVisible(int $id): void
475
    {
476
        $sourceNodeData = $this->locationGateway->getBasicNodeData($id);
477
478
        $this->locationGateway->setNodeWithChildrenVisible($sourceNodeData['path_string']);
479
    }
480
481
    /**
482
     * Swaps the content object being pointed to by a location object.
483
     *
484
     * Make the location identified by $locationId1 refer to the Content
485
     * referred to by $locationId2 and vice versa.
486
     *
487
     * @param mixed $locationId1
488
     * @param mixed $locationId2
489
     *
490
     * @return bool
491
     */
492
    public function swap($locationId1, $locationId2)
493
    {
494
        $this->locationGateway->swap($locationId1, $locationId2);
495
    }
496
497
    /**
498
     * Updates an existing location.
499
     *
500
     * @param \eZ\Publish\SPI\Persistence\Content\Location\UpdateStruct $location
501
     * @param int $locationId
502
     */
503
    public function update(UpdateStruct $location, $locationId)
504
    {
505
        $this->locationGateway->update($location, $locationId);
506
    }
507
508
    /**
509
     * Creates a new location rooted at $location->parentId.
510
     *
511
     * @param \eZ\Publish\SPI\Persistence\Content\Location\CreateStruct $createStruct
512
     *
513
     * @return \eZ\Publish\SPI\Persistence\Content\Location
514
     */
515
    public function create(CreateStruct $createStruct)
516
    {
517
        $parentNodeData = $this->locationGateway->getBasicNodeData($createStruct->parentId);
518
        $locationStruct = $this->locationGateway->create($createStruct, $parentNodeData);
519
        $this->locationGateway->createNodeAssignment(
520
            $createStruct,
521
            $parentNodeData['node_id'],
522
            LocationGateway::NODE_ASSIGNMENT_OP_CODE_CREATE_NOP
523
        );
524
525
        return $locationStruct;
526
    }
527
528
    /**
529
     * Removes all Locations under and including $locationId.
530
     *
531
     * Performs a recursive delete on the location identified by $locationId,
532
     * including all of its child locations. Content which is not referred to
533
     * by any other location is automatically removed. Content which looses its
534
     * main Location will get the first of its other Locations assigned as the
535
     * new main Location.
536
     *
537
     * @param mixed $locationId
538
     *
539
     * @return bool
540
     */
541
    public function removeSubtree($locationId)
542
    {
543
        $this->treeHandler->removeSubtree($locationId);
544
    }
545
546
    /**
547
     * Set section on all content objects in the subtree.
548
     *
549
     * @param mixed $locationId
550
     * @param mixed $sectionId
551
     */
552
    public function setSectionForSubtree($locationId, $sectionId)
553
    {
554
        $this->treeHandler->setSectionForSubtree($locationId, $sectionId);
555
    }
556
557
    /**
558
     * Changes main location of content identified by given $contentId to location identified by given $locationId.
559
     *
560
     * Updates ezcontentobject_tree and eznode_assignment tables (eznode_assignment for content current version number).
561
     *
562
     * @param mixed $contentId
563
     * @param mixed $locationId
564
     */
565
    public function changeMainLocation($contentId, $locationId)
566
    {
567
        $this->treeHandler->changeMainLocation($contentId, $locationId);
568
    }
569
570
    /**
571
     * Get the total number of all existing Locations. Can be combined with loadAllLocations.
572
     *
573
     * @return int
574
     */
575
    public function countAllLocations()
576
    {
577
        return $this->locationGateway->countAllLocations();
578
    }
579
580
    /**
581
     * Bulk-load all existing Locations, constrained by $limit and $offset to paginate results.
582
     *
583
     * @param int $offset
584
     * @param int $limit
585
     *
586
     * @return \eZ\Publish\SPI\Persistence\Content\Location[]
587
     */
588
    public function loadAllLocations($offset, $limit)
589
    {
590
        $rows = $this->locationGateway->loadAllLocationsData($offset, $limit);
591
592
        return $this->locationMapper->createLocationsFromRows($rows);
593
    }
594
}
595