Completed
Push — 6.7 ( 8d5066...b23530 )
by André
14:06
created

LocationService::loadLocations()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 4
nop 2
dl 0
loc 21
rs 8.7624
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the eZ\Publish\Core\Repository\LocationService 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;
10
11
use eZ\Publish\API\Repository\Values\Content\LocationUpdateStruct;
12
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
13
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
14
use eZ\Publish\API\Repository\Values\Content\Location as APILocation;
15
use eZ\Publish\API\Repository\Values\Content\LocationList;
16
use eZ\Publish\SPI\Persistence\Content\Location\UpdateStruct;
17
use eZ\Publish\API\Repository\LocationService as LocationServiceInterface;
18
use eZ\Publish\API\Repository\Repository as RepositoryInterface;
19
use eZ\Publish\SPI\Persistence\Handler;
20
use eZ\Publish\API\Repository\Values\Content\Query;
21
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
22
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
23
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\LogicalAnd as CriterionLogicalAnd;
24
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\LogicalNot as CriterionLogicalNot;
25
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\Subtree as CriterionSubtree;
26
use eZ\Publish\API\Repository\Exceptions\NotFoundException as APINotFoundException;
27
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentValue;
28
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;
29
use eZ\Publish\Core\Base\Exceptions\BadStateException;
30
use eZ\Publish\Core\Base\Exceptions\UnauthorizedException;
31
use Exception;
32
33
/**
34
 * Location service, used for complex subtree operations.
35
 *
36
 * @example Examples/location.php
37
 */
38
class LocationService implements LocationServiceInterface
39
{
40
    /**
41
     * @var \eZ\Publish\Core\Repository\Repository
42
     */
43
    protected $repository;
44
45
    /**
46
     * @var \eZ\Publish\SPI\Persistence\Handler
47
     */
48
    protected $persistenceHandler;
49
50
    /**
51
     * @var array
52
     */
53
    protected $settings;
54
55
    /**
56
     * @var \eZ\Publish\Core\Repository\Helper\DomainMapper
57
     */
58
    protected $domainMapper;
59
60
    /**
61
     * @var \eZ\Publish\Core\Repository\Helper\NameSchemaService
62
     */
63
    protected $nameSchemaService;
64
65
    /**
66
     * @var \eZ\Publish\Core\Repository\PermissionsCriterionHandler
67
     */
68
    protected $permissionsCriterionHandler;
69
70
    /**
71
     * Setups service with reference to repository object that created it & corresponding handler.
72
     *
73
     * @param \eZ\Publish\API\Repository\Repository $repository
74
     * @param \eZ\Publish\SPI\Persistence\Handler $handler
75
     * @param \eZ\Publish\Core\Repository\Helper\DomainMapper $domainMapper
76
     * @param \eZ\Publish\Core\Repository\Helper\NameSchemaService $nameSchemaService
77
     * @param \eZ\Publish\Core\Repository\PermissionsCriterionHandler $permissionsCriterionHandler
78
     * @param array $settings
79
     */
80 View Code Duplication
    public function __construct(
81
        RepositoryInterface $repository,
82
        Handler $handler,
83
        Helper\DomainMapper $domainMapper,
84
        Helper\NameSchemaService $nameSchemaService,
85
        PermissionsCriterionHandler $permissionsCriterionHandler,
86
        array $settings = array()
87
    ) {
88
        $this->repository = $repository;
0 ignored issues
show
Documentation Bug introduced by
$repository is of type object<eZ\Publish\API\Repository\Repository>, but the property $repository was declared to be of type object<eZ\Publish\Core\Repository\Repository>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
89
        $this->persistenceHandler = $handler;
90
        $this->domainMapper = $domainMapper;
91
        $this->nameSchemaService = $nameSchemaService;
92
        // Union makes sure default settings are ignored if provided in argument
93
        $this->settings = $settings + array(
94
            //'defaultSetting' => array(),
95
        );
96
        $this->permissionsCriterionHandler = $permissionsCriterionHandler;
97
    }
98
99
    /**
100
     * Copies the subtree starting from $subtree as a new subtree of $targetLocation.
101
     *
102
     * Only the items on which the user has read access are copied.
103
     *
104
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed copy the subtree to the given parent location
105
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user does not have read access to the whole source subtree
106
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if the target location is a sub location of the given location
107
     *
108
     * @param \eZ\Publish\API\Repository\Values\Content\Location $subtree - the subtree denoted by the location to copy
109
     * @param \eZ\Publish\API\Repository\Values\Content\Location $targetParentLocation - the target parent location for the copy operation
110
     *
111
     * @return \eZ\Publish\API\Repository\Values\Content\Location The newly created location of the copied subtree
112
     */
113
    public function copySubtree(APILocation $subtree, APILocation $targetParentLocation)
114
    {
115
        $loadedSubtree = $this->loadLocation($subtree->id);
116
        $loadedTargetLocation = $this->loadLocation($targetParentLocation->id);
117
118
        if (stripos($loadedTargetLocation->pathString, $loadedSubtree->pathString) !== false) {
0 ignored issues
show
Documentation introduced by
The property $pathString is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
119
            throw new InvalidArgumentException('targetParentLocation', 'target parent location is a sub location of the given subtree');
120
        }
121
122
        // check create permission on target
123
        if (!$this->repository->canUser('content', 'create', $loadedSubtree->getContentInfo(), $loadedTargetLocation)) {
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\Core\Repository\Repository::canUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::canUser() instead. Check if user has access to a given action on a given value object. Indicates if the current user is allowed to perform an action given by the function on the given
objects.

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...
124
            throw new UnauthorizedException('content', 'create');
125
        }
126
127
        /** Check read access to whole source subtree
128
         * @var bool|\eZ\Publish\API\Repository\Values\Content\Query\Criterion
129
         */
130
        $contentReadCriterion = $this->permissionsCriterionHandler->getPermissionsCriterion();
131 View Code Duplication
        if ($contentReadCriterion === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
132
            throw new UnauthorizedException('content', 'read');
133
        } elseif ($contentReadCriterion !== true) {
134
            // Query if there are any content in subtree current user don't have access to
135
            $query = new Query(
136
                array(
137
                    'limit' => 0,
138
                    'filter' => new CriterionLogicalAnd(
139
                        array(
140
                            new CriterionSubtree($loadedSubtree->pathString),
0 ignored issues
show
Documentation introduced by
The property $pathString is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
141
                            new CriterionLogicalNot($contentReadCriterion),
0 ignored issues
show
Bug introduced by
It seems like $contentReadCriterion defined by $this->permissionsCriter...tPermissionsCriterion() on line 130 can also be of type boolean; however, eZ\Publish\API\Repositor...gicalNot::__construct() does only seem to accept object<eZ\Publish\API\Re...ontent\Query\Criterion>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
142
                        )
143
                    ),
144
                )
145
            );
146
            $result = $this->repository->getSearchService()->findContent($query, array(), false);
147
            if ($result->totalCount > 0) {
148
                throw new UnauthorizedException('content', 'read');
149
            }
150
        }
151
152
        $this->repository->beginTransaction();
153
        try {
154
            $newLocation = $this->persistenceHandler->locationHandler()->copySubtree(
155
                $loadedSubtree->id,
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
156
                $loadedTargetLocation->id
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
157
            );
158
159
            $content = $this->repository->getContentService()->loadContent($newLocation->contentId);
160
            $urlAliasNames = $this->nameSchemaService->resolveUrlAliasSchema($content);
161 View Code Duplication
            foreach ($urlAliasNames as $languageCode => $name) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
162
                $this->persistenceHandler->urlAliasHandler()->publishUrlAliasForLocation(
163
                    $newLocation->id,
164
                    $loadedTargetLocation->id,
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
165
                    $name,
166
                    $languageCode,
167
                    $content->contentInfo->alwaysAvailable
168
                );
169
            }
170
171
            $this->persistenceHandler->urlAliasHandler()->locationCopied(
172
                $loadedSubtree->id,
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
173
                $newLocation->id,
174
                $loadedTargetLocation->id
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
175
            );
176
177
            $this->repository->commit();
178
        } catch (Exception $e) {
179
            $this->repository->rollback();
180
            throw $e;
181
        }
182
183
        return $this->domainMapper->buildLocationDomainObject($newLocation);
184
    }
185
186
    /**
187
     * Loads a location object from its $locationId.
188
     *
189
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to read this location
190
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If the specified location is not found
191
     *
192
     * @param mixed $locationId
193
     *
194
     * @return \eZ\Publish\API\Repository\Values\Content\Location
195
     */
196
    public function loadLocation($locationId)
197
    {
198
        $spiLocation = $this->persistenceHandler->locationHandler()->load($locationId);
199
        $location = $this->domainMapper->buildLocationDomainObject($spiLocation);
200
        if (!$this->repository->canUser('content', 'read', $location->getContentInfo(), $location)) {
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\Core\Repository\Repository::canUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::canUser() instead. Check if user has access to a given action on a given value object. Indicates if the current user is allowed to perform an action given by the function on the given
objects.

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...
201
            throw new UnauthorizedException('content', 'read');
202
        }
203
204
        return $location;
205
    }
206
207
    /**
208
     * Loads a location object from its $remoteId.
209
     *
210
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to read this location
211
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException If more than one location with same remote ID was found
212
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If the specified location is not found
213
     *
214
     * @param string $remoteId
215
     *
216
     * @return \eZ\Publish\API\Repository\Values\Content\Location
217
     */
218
    public function loadLocationByRemoteId($remoteId)
219
    {
220
        if (!is_string($remoteId)) {
221
            throw new InvalidArgumentValue('remoteId', $remoteId);
222
        }
223
224
        $spiLocation = $this->persistenceHandler->locationHandler()->loadByRemoteId($remoteId);
225
        $location = $this->domainMapper->buildLocationDomainObject($spiLocation);
226
        if (!$this->repository->canUser('content', 'read', $location->getContentInfo(), $location)) {
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\Core\Repository\Repository::canUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::canUser() instead. Check if user has access to a given action on a given value object. Indicates if the current user is allowed to perform an action given by the function on the given
objects.

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...
227
            throw new UnauthorizedException('content', 'read');
228
        }
229
230
        return $location;
231
    }
232
233
    /**
234
     * {@inheritdoc}
235
     */
236
    public function loadLocations(ContentInfo $contentInfo, APILocation $rootLocation = null)
237
    {
238
        if (!$contentInfo->published) {
239
            throw new BadStateException('$contentInfo', 'ContentInfo has no published versions');
240
        }
241
242
        $spiLocations = $this->persistenceHandler->locationHandler()->loadLocationsByContent(
243
            $contentInfo->id,
244
            $rootLocation !== null ? $rootLocation->id : null
245
        );
246
247
        $locations = [];
248
        foreach ($spiLocations as $spiLocation) {
249
            $location = $this->domainMapper->buildLocationDomainObject($spiLocation);
250
            if ($this->repository->canUser('content', 'read', $location->getContentInfo(), $location)) {
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\Core\Repository\Repository::canUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::canUser() instead. Check if user has access to a given action on a given value object. Indicates if the current user is allowed to perform an action given by the function on the given
objects.

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...
251
                $locations[] = $location;
252
            }
253
        }
254
255
        return $locations;
256
    }
257
258
    /**
259
     * Loads children which are readable by the current user of a location object sorted by sortField and sortOrder.
260
     *
261
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
262
     * @param int $offset the start offset for paging
263
     * @param int $limit the number of locations returned
264
     *
265
     * @return \eZ\Publish\API\Repository\Values\Content\LocationList
266
     */
267
    public function loadLocationChildren(APILocation $location, $offset = 0, $limit = 25)
268
    {
269
        if (!$this->domainMapper->isValidLocationSortField($location->sortField)) {
270
            throw new InvalidArgumentValue('sortField', $location->sortField, 'Location');
271
        }
272
273
        if (!$this->domainMapper->isValidLocationSortOrder($location->sortOrder)) {
274
            throw new InvalidArgumentValue('sortOrder', $location->sortOrder, 'Location');
275
        }
276
277
        if (!is_int($offset)) {
278
            throw new InvalidArgumentValue('offset', $offset);
279
        }
280
281
        if (!is_int($limit)) {
282
            throw new InvalidArgumentValue('limit', $limit);
283
        }
284
285
        $childLocations = array();
286
        $searchResult = $this->searchChildrenLocations($location, $offset, $limit);
287
        foreach ($searchResult->searchHits as $searchHit) {
288
            $childLocations[] = $searchHit->valueObject;
289
        }
290
291
        return new LocationList(
292
            array(
293
                'locations' => $childLocations,
294
                'totalCount' => $searchResult->totalCount,
295
            )
296
        );
297
    }
298
299
    /**
300
     * Returns the number of children which are readable by the current user of a location object.
301
     *
302
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
303
     *
304
     * @return int
305
     */
306
    public function getLocationChildCount(APILocation $location)
307
    {
308
        $searchResult = $this->searchChildrenLocations($location, 0, 0);
309
310
        return $searchResult->totalCount;
311
    }
312
313
    /**
314
     * Searches children locations of the provided parent location id.
315
     *
316
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
317
     * @param int $offset
318
     * @param int $limit
319
     *
320
     * @return \eZ\Publish\API\Repository\Values\Content\Search\SearchResult
321
     */
322
    protected function searchChildrenLocations(APILocation $location, $offset = 0, $limit = -1)
323
    {
324
        $query = new LocationQuery([
325
            'filter' => new Criterion\ParentLocationId($location->id),
326
            'offset' => $offset >= 0 ? (int)$offset : 0,
327
            'limit' => $limit >= 0 ? (int)$limit : null,
328
            'sortClauses' => $location->getSortClauses(),
329
        ]);
330
331
        return $this->repository->getSearchService()->findLocations($query);
332
    }
333
334
    /**
335
     * Creates the new $location in the content repository for the given content.
336
     *
337
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to create this location
338
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if the content is already below the specified parent
339
     *                                        or the parent is a sub location of the location of the content
340
     *                                        or if set the remoteId exists already
341
     *
342
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
343
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct $locationCreateStruct
344
     *
345
     * @return \eZ\Publish\API\Repository\Values\Content\Location the newly created Location
346
     */
347
    public function createLocation(ContentInfo $contentInfo, LocationCreateStruct $locationCreateStruct)
348
    {
349
        $content = $this->repository->getContentService()->loadContent($contentInfo->id);
350
        $parentLocation = $this->loadLocation($locationCreateStruct->parentLocationId);
351
352
        if (!$this->repository->canUser('content', 'create', $content->contentInfo, $parentLocation)) {
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\Core\Repository\Repository::canUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::canUser() instead. Check if user has access to a given action on a given value object. Indicates if the current user is allowed to perform an action given by the function on the given
objects.

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...
353
            throw new UnauthorizedException('content', 'create');
354
        }
355
356
        // Check if the parent is a sub location of one of the existing content locations (this also solves the
357
        // situation where parent location actually one of the content locations),
358
        // or if the content already has location below given location create struct parent
359
        $existingContentLocations = $this->loadLocations($content->contentInfo);
360
        if (!empty($existingContentLocations)) {
361
            foreach ($existingContentLocations as $existingContentLocation) {
362
                if (stripos($parentLocation->pathString, $existingContentLocation->pathString) !== false) {
0 ignored issues
show
Documentation introduced by
The property $pathString is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
363
                    throw new InvalidArgumentException(
364
                        '$locationCreateStruct',
365
                        'Specified parent is a sub location of one of the existing content locations.'
366
                    );
367
                }
368
                if ($parentLocation->id == $existingContentLocation->parentLocationId) {
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
369
                    throw new InvalidArgumentException(
370
                        '$locationCreateStruct',
371
                        'Content is already below the specified parent.'
372
                    );
373
                }
374
            }
375
        }
376
377
        $spiLocationCreateStruct = $this->domainMapper->buildSPILocationCreateStruct(
378
            $locationCreateStruct,
379
            $parentLocation,
380
            $content->contentInfo->mainLocationId !== null ? $content->contentInfo->mainLocationId : true,
381
            $content->contentInfo->id,
382
            $content->contentInfo->currentVersionNo
383
        );
384
385
        $this->repository->beginTransaction();
386
        try {
387
            $newLocation = $this->persistenceHandler->locationHandler()->create($spiLocationCreateStruct);
388
389
            $urlAliasNames = $this->nameSchemaService->resolveUrlAliasSchema($content);
390 View Code Duplication
            foreach ($urlAliasNames as $languageCode => $name) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
391
                $this->persistenceHandler->urlAliasHandler()->publishUrlAliasForLocation(
392
                    $newLocation->id,
393
                    $newLocation->parentId,
394
                    $name,
395
                    $languageCode,
396
                    $content->contentInfo->alwaysAvailable,
397
                    // @todo: this is legacy storage specific for updating ezcontentobject_tree.path_identification_string, to be removed
398
                    $languageCode === $content->contentInfo->mainLanguageCode
399
                );
400
            }
401
402
            $this->repository->commit();
403
        } catch (Exception $e) {
404
            $this->repository->rollback();
405
            throw $e;
406
        }
407
408
        return $this->domainMapper->buildLocationDomainObject($newLocation);
409
    }
410
411
    /**
412
     * Updates $location in the content repository.
413
     *
414
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to update this location
415
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException   if if set the remoteId exists already
416
     *
417
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
418
     * @param \eZ\Publish\API\Repository\Values\Content\LocationUpdateStruct $locationUpdateStruct
419
     *
420
     * @return \eZ\Publish\API\Repository\Values\Content\Location the updated Location
421
     */
422
    public function updateLocation(APILocation $location, LocationUpdateStruct $locationUpdateStruct)
423
    {
424
        if ($locationUpdateStruct->priority !== null && !is_int($locationUpdateStruct->priority)) {
425
            throw new InvalidArgumentValue('priority', $locationUpdateStruct->priority, 'LocationUpdateStruct');
426
        }
427
428
        if ($locationUpdateStruct->remoteId !== null && (!is_string($locationUpdateStruct->remoteId) || empty($locationUpdateStruct->remoteId))) {
429
            throw new InvalidArgumentValue('remoteId', $locationUpdateStruct->remoteId, 'LocationUpdateStruct');
430
        }
431
432
        if ($locationUpdateStruct->sortField !== null && !$this->domainMapper->isValidLocationSortField($locationUpdateStruct->sortField)) {
433
            throw new InvalidArgumentValue('sortField', $locationUpdateStruct->sortField, 'LocationUpdateStruct');
434
        }
435
436
        if ($locationUpdateStruct->sortOrder !== null && !$this->domainMapper->isValidLocationSortOrder($locationUpdateStruct->sortOrder)) {
437
            throw new InvalidArgumentValue('sortOrder', $locationUpdateStruct->sortOrder, 'LocationUpdateStruct');
438
        }
439
440
        $loadedLocation = $this->loadLocation($location->id);
441
442
        if ($locationUpdateStruct->remoteId !== null) {
443
            try {
444
                $existingLocation = $this->loadLocationByRemoteId($locationUpdateStruct->remoteId);
445
                if ($existingLocation !== null && $existingLocation->id !== $loadedLocation->id) {
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
446
                    throw new InvalidArgumentException('locationUpdateStruct', 'location with provided remote ID already exists');
447
                }
448
            } catch (APINotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
449
            }
450
        }
451
452
        if (!$this->repository->canUser('content', 'edit', $loadedLocation->getContentInfo(), $loadedLocation)) {
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\Core\Repository\Repository::canUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::canUser() instead. Check if user has access to a given action on a given value object. Indicates if the current user is allowed to perform an action given by the function on the given
objects.

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...
453
            throw new UnauthorizedException('content', 'edit');
454
        }
455
456
        $updateStruct = new UpdateStruct();
457
        $updateStruct->priority = $locationUpdateStruct->priority !== null ? $locationUpdateStruct->priority : $loadedLocation->priority;
0 ignored issues
show
Documentation introduced by
The property $priority is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
458
        $updateStruct->remoteId = $locationUpdateStruct->remoteId !== null ? trim($locationUpdateStruct->remoteId) : $loadedLocation->remoteId;
0 ignored issues
show
Documentation introduced by
The property $remoteId is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
459
        $updateStruct->sortField = $locationUpdateStruct->sortField !== null ? $locationUpdateStruct->sortField : $loadedLocation->sortField;
0 ignored issues
show
Documentation introduced by
The property $sortField is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
460
        $updateStruct->sortOrder = $locationUpdateStruct->sortOrder !== null ? $locationUpdateStruct->sortOrder : $loadedLocation->sortOrder;
0 ignored issues
show
Documentation introduced by
The property $sortOrder is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
461
462
        $this->repository->beginTransaction();
463
        try {
464
            $this->persistenceHandler->locationHandler()->update($updateStruct, $loadedLocation->id);
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
465
            $this->repository->commit();
466
        } catch (Exception $e) {
467
            $this->repository->rollback();
468
            throw $e;
469
        }
470
471
        return $this->loadLocation($loadedLocation->id);
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
472
    }
473
474
    /**
475
     * Swaps the contents held by $location1 and $location2.
476
     *
477
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to swap content
478
     *
479
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location1
480
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location2
481
     */
482
    public function swapLocation(APILocation $location1, APILocation $location2)
483
    {
484
        $loadedLocation1 = $this->loadLocation($location1->id);
485
        $loadedLocation2 = $this->loadLocation($location2->id);
486
487
        if (!$this->repository->canUser('content', 'edit', $loadedLocation1->getContentInfo(), $loadedLocation1)) {
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\Core\Repository\Repository::canUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::canUser() instead. Check if user has access to a given action on a given value object. Indicates if the current user is allowed to perform an action given by the function on the given
objects.

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...
488
            throw new UnauthorizedException('content', 'edit');
489
        }
490
        if (!$this->repository->canUser('content', 'edit', $loadedLocation2->getContentInfo(), $loadedLocation2)) {
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\Core\Repository\Repository::canUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::canUser() instead. Check if user has access to a given action on a given value object. Indicates if the current user is allowed to perform an action given by the function on the given
objects.

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...
491
            throw new UnauthorizedException('content', 'edit');
492
        }
493
494
        $this->repository->beginTransaction();
495
        try {
496
            $this->persistenceHandler->locationHandler()->swap($loadedLocation1->id, $loadedLocation2->id);
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
497
            $this->persistenceHandler->urlAliasHandler()->locationSwapped(
498
                $location1->id,
499
                $location1->parentLocationId,
500
                $location2->id,
501
                $location2->parentLocationId
502
            );
503
            $this->repository->commit();
504
        } catch (Exception $e) {
505
            $this->repository->rollback();
506
            throw $e;
507
        }
508
    }
509
510
    /**
511
     * Hides the $location and marks invisible all descendants of $location.
512
     *
513
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to hide this location
514
     *
515
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
516
     *
517
     * @return \eZ\Publish\API\Repository\Values\Content\Location $location, with updated hidden value
518
     */
519 View Code Duplication
    public function hideLocation(APILocation $location)
520
    {
521
        if (!$this->repository->canUser('content', 'hide', $location->getContentInfo(), $location)) {
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\Core\Repository\Repository::canUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::canUser() instead. Check if user has access to a given action on a given value object. Indicates if the current user is allowed to perform an action given by the function on the given
objects.

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...
522
            throw new UnauthorizedException('content', 'hide');
523
        }
524
525
        $this->repository->beginTransaction();
526
        try {
527
            $this->persistenceHandler->locationHandler()->hide($location->id);
528
            $this->repository->commit();
529
        } catch (Exception $e) {
530
            $this->repository->rollback();
531
            throw $e;
532
        }
533
534
        return $this->loadLocation($location->id);
535
    }
536
537
    /**
538
     * Unhides the $location.
539
     *
540
     * This method and marks visible all descendants of $locations
541
     * until a hidden location is found.
542
     *
543
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to unhide this location
544
     *
545
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
546
     *
547
     * @return \eZ\Publish\API\Repository\Values\Content\Location $location, with updated hidden value
548
     */
549 View Code Duplication
    public function unhideLocation(APILocation $location)
550
    {
551
        if (!$this->repository->canUser('content', 'hide', $location->getContentInfo(), $location)) {
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\Core\Repository\Repository::canUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::canUser() instead. Check if user has access to a given action on a given value object. Indicates if the current user is allowed to perform an action given by the function on the given
objects.

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...
552
            throw new UnauthorizedException('content', 'hide');
553
        }
554
555
        $this->repository->beginTransaction();
556
        try {
557
            $this->persistenceHandler->locationHandler()->unHide($location->id);
558
            $this->repository->commit();
559
        } catch (Exception $e) {
560
            $this->repository->rollback();
561
            throw $e;
562
        }
563
564
        return $this->loadLocation($location->id);
565
    }
566
567
    /**
568
     * Moves the subtree to $newParentLocation.
569
     *
570
     * If a user has the permission to move the location to a target location
571
     * he can do it regardless of an existing descendant on which the user has no permission.
572
     *
573
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to move this location to the target
574
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user does not have read access to the whole source subtree
575
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If the new parent is in a subtree of the location
576
     *
577
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
578
     * @param \eZ\Publish\API\Repository\Values\Content\Location $newParentLocation
579
     */
580
    public function moveSubtree(APILocation $location, APILocation $newParentLocation)
581
    {
582
        $location = $this->loadLocation($location->id);
583
        $newParentLocation = $this->loadLocation($newParentLocation->id);
584
585
        // check create permission on target location
586
        if (!$this->repository->canUser('content', 'create', $location->getContentInfo(), $newParentLocation)) {
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\Core\Repository\Repository::canUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::canUser() instead. Check if user has access to a given action on a given value object. Indicates if the current user is allowed to perform an action given by the function on the given
objects.

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...
587
            throw new UnauthorizedException('content', 'create');
588
        }
589
590
        /** Check read access to whole source subtree
591
         * @var bool|\eZ\Publish\API\Repository\Values\Content\Query\Criterion
592
         */
593
        $contentReadCriterion = $this->permissionsCriterionHandler->getPermissionsCriterion();
594 View Code Duplication
        if ($contentReadCriterion === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
595
            throw new UnauthorizedException('content', 'read');
596
        } elseif ($contentReadCriterion !== true) {
597
            // Query if there are any content in subtree current user don't have access to
598
            $query = new Query(
599
                array(
600
                    'limit' => 0,
601
                    'filter' => new CriterionLogicalAnd(
602
                        array(
603
                            new CriterionSubtree($location->pathString),
0 ignored issues
show
Documentation introduced by
The property $pathString is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
604
                            new CriterionLogicalNot($contentReadCriterion),
0 ignored issues
show
Bug introduced by
It seems like $contentReadCriterion defined by $this->permissionsCriter...tPermissionsCriterion() on line 593 can also be of type boolean; however, eZ\Publish\API\Repositor...gicalNot::__construct() does only seem to accept object<eZ\Publish\API\Re...ontent\Query\Criterion>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
605
                        )
606
                    ),
607
                )
608
            );
609
            $result = $this->repository->getSearchService()->findContent($query, array(), false);
610
            if ($result->totalCount > 0) {
611
                throw new UnauthorizedException('content', 'read');
612
            }
613
        }
614
615
        if (strpos($newParentLocation->pathString, $location->pathString) === 0) {
0 ignored issues
show
Documentation introduced by
The property $pathString is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
616
            throw new InvalidArgumentException(
617
                '$newParentLocation',
618
                'new parent location is in a subtree of the given $location'
619
            );
620
        }
621
622
        $this->repository->beginTransaction();
623
        try {
624
            $this->persistenceHandler->locationHandler()->move($location->id, $newParentLocation->id);
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
625
626
            $content = $this->repository->getContentService()->loadContent($location->contentId);
627
            $urlAliasNames = $this->nameSchemaService->resolveUrlAliasSchema($content);
628 View Code Duplication
            foreach ($urlAliasNames as $languageCode => $name) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
629
                $this->persistenceHandler->urlAliasHandler()->publishUrlAliasForLocation(
630
                    $location->id,
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
631
                    $newParentLocation->id,
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
632
                    $name,
633
                    $languageCode,
634
                    $content->contentInfo->alwaysAvailable
635
                );
636
            }
637
638
            $this->persistenceHandler->urlAliasHandler()->locationMoved(
639
                $location->id,
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
640
                $location->parentLocationId,
0 ignored issues
show
Documentation introduced by
The property $parentLocationId is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
641
                $newParentLocation->id
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
642
            );
643
644
            $this->repository->commit();
645
        } catch (Exception $e) {
646
            $this->repository->rollback();
647
            throw $e;
648
        }
649
    }
650
651
    /**
652
     * Deletes $location and all its descendants.
653
     *
654
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user is not allowed to delete this location or a descendant
655
     *
656
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
657
     */
658
    public function deleteLocation(APILocation $location)
659
    {
660
        $location = $this->loadLocation($location->id);
661
662
        if (!$this->repository->canUser('content', 'manage_locations', $location->getContentInfo())) {
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\Core\Repository\Repository::canUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::canUser() instead. Check if user has access to a given action on a given value object. Indicates if the current user is allowed to perform an action given by the function on the given
objects.

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...
663
            throw new UnauthorizedException('content', 'manage_locations');
664
        }
665
        if (!$this->repository->canUser('content', 'remove', $location->getContentInfo(), $location)) {
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\Core\Repository\Repository::canUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::canUser() instead. Check if user has access to a given action on a given value object. Indicates if the current user is allowed to perform an action given by the function on the given
objects.

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...
666
            throw new UnauthorizedException('content', 'remove');
667
        }
668
669
        /** Check remove access to descendants
670
         * @var bool|\eZ\Publish\API\Repository\Values\Content\Query\Criterion
671
         */
672
        $contentReadCriterion = $this->permissionsCriterionHandler->getPermissionsCriterion('content', 'remove');
673 View Code Duplication
        if ($contentReadCriterion === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
674
            throw new UnauthorizedException('content', 'remove');
675
        } elseif ($contentReadCriterion !== true) {
676
            // Query if there are any content in subtree current user don't have access to
677
            $query = new Query(
678
                array(
679
                    'limit' => 0,
680
                    'filter' => new CriterionLogicalAnd(
681
                        array(
682
                            new CriterionSubtree($location->pathString),
0 ignored issues
show
Documentation introduced by
The property $pathString is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
683
                            new CriterionLogicalNot($contentReadCriterion),
0 ignored issues
show
Bug introduced by
It seems like $contentReadCriterion defined by $this->permissionsCriter...on('content', 'remove') on line 672 can also be of type boolean; however, eZ\Publish\API\Repositor...gicalNot::__construct() does only seem to accept object<eZ\Publish\API\Re...ontent\Query\Criterion>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
684
                        )
685
                    ),
686
                )
687
            );
688
            $result = $this->repository->getSearchService()->findContent($query, array(), false);
689
            if ($result->totalCount > 0) {
690
                throw new UnauthorizedException('content', 'remove');
691
            }
692
        }
693
694
        $this->repository->beginTransaction();
695
        try {
696
            $this->persistenceHandler->locationHandler()->removeSubtree($location->id);
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
697
            $this->persistenceHandler->urlAliasHandler()->locationDeleted($location->id);
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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...
698
            $this->repository->commit();
699
        } catch (Exception $e) {
700
            $this->repository->rollback();
701
            throw $e;
702
        }
703
    }
704
705
    /**
706
     * Instantiates a new location create class.
707
     *
708
     * @param mixed $parentLocationId the parent under which the new location should be created
709
     *
710
     * @return \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct
711
     */
712
    public function newLocationCreateStruct($parentLocationId)
713
    {
714
        return new LocationCreateStruct(
715
            array(
716
                'parentLocationId' => $parentLocationId,
717
            )
718
        );
719
    }
720
721
    /**
722
     * Instantiates a new location update class.
723
     *
724
     * @return \eZ\Publish\API\Repository\Values\Content\LocationUpdateStruct
725
     */
726
    public function newLocationUpdateStruct()
727
    {
728
        return new LocationUpdateStruct();
729
    }
730
}
731