Completed
Push — master ( a6387c...f7252d )
by André
23:52 queued 09:38
created

LocationService::unhideLocation()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 17
Code Lines 11

Duplication

Lines 17
Ratio 100 %

Importance

Changes 0
Metric Value
cc 3
eloc 11
nc 4
nop 1
dl 17
loc 17
rs 9.4285
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
     * Loads the locations for the given content object.
235
     *
236
     * If a $rootLocation is given, only locations that belong to this location are returned.
237
     * The location list is also filtered by permissions on reading locations.
238
     *
239
     * @todo permissions check is missing
240
     *
241
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if there is no published version yet
242
     *
243
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
244
     * @param \eZ\Publish\API\Repository\Values\Content\Location $rootLocation
245
     *
246
     * @return \eZ\Publish\API\Repository\Values\Content\Location[] An array of {@link Location}
247
     */
248
    public function loadLocations(ContentInfo $contentInfo, APILocation $rootLocation = null)
249
    {
250
        if (!$contentInfo->published) {
251
            throw new BadStateException('$contentInfo', 'ContentInfo has no published versions');
252
        }
253
254
        $spiLocations = $this->persistenceHandler->locationHandler()->loadLocationsByContent(
255
            $contentInfo->id,
256
            $rootLocation !== null ? $rootLocation->id : null
257
        );
258
259
        $locations = array();
260
        foreach ($spiLocations as $spiLocation) {
261
            $locations[] = $this->domainMapper->buildLocationDomainObject($spiLocation);
262
        }
263
264
        return $locations;
265
    }
266
267
    /**
268
     * Loads children which are readable by the current user of a location object sorted by sortField and sortOrder.
269
     *
270
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
271
     * @param int $offset the start offset for paging
272
     * @param int $limit the number of locations returned
273
     *
274
     * @return \eZ\Publish\API\Repository\Values\Content\LocationList
275
     */
276
    public function loadLocationChildren(APILocation $location, $offset = 0, $limit = 25)
277
    {
278
        if (!$this->domainMapper->isValidLocationSortField($location->sortField)) {
279
            throw new InvalidArgumentValue('sortField', $location->sortField, 'Location');
280
        }
281
282
        if (!$this->domainMapper->isValidLocationSortOrder($location->sortOrder)) {
283
            throw new InvalidArgumentValue('sortOrder', $location->sortOrder, 'Location');
284
        }
285
286
        if (!is_int($offset)) {
287
            throw new InvalidArgumentValue('offset', $offset);
288
        }
289
290
        if (!is_int($limit)) {
291
            throw new InvalidArgumentValue('limit', $limit);
292
        }
293
294
        $childLocations = array();
295
        $searchResult = $this->searchChildrenLocations($location, $offset, $limit);
296
        foreach ($searchResult->searchHits as $searchHit) {
297
            $childLocations[] = $searchHit->valueObject;
298
        }
299
300
        return new LocationList(
301
            array(
302
                'locations' => $childLocations,
303
                'totalCount' => $searchResult->totalCount,
304
            )
305
        );
306
    }
307
308
    /**
309
     * Returns the number of children which are readable by the current user of a location object.
310
     *
311
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
312
     *
313
     * @return int
314
     */
315
    public function getLocationChildCount(APILocation $location)
316
    {
317
        $searchResult = $this->searchChildrenLocations($location, 0, 0);
318
319
        return $searchResult->totalCount;
320
    }
321
322
    /**
323
     * Searches children locations of the provided parent location id.
324
     *
325
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
326
     * @param int $offset
327
     * @param int $limit
328
     *
329
     * @return \eZ\Publish\API\Repository\Values\Content\Search\SearchResult
330
     */
331
    protected function searchChildrenLocations(APILocation $location, $offset = 0, $limit = -1)
332
    {
333
        $query = new LocationQuery([
334
            'filter' => new Criterion\ParentLocationId($location->id),
335
            'offset' => $offset >= 0 ? (int)$offset : 0,
336
            'limit' => $limit >= 0 ? (int)$limit : null,
337
            'sortClauses' => $location->getSortClauses(),
338
        ]);
339
340
        return $this->repository->getSearchService()->findLocations($query);
341
    }
342
343
    /**
344
     * Creates the new $location in the content repository for the given content.
345
     *
346
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to create this location
347
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if the content is already below the specified parent
348
     *                                        or the parent is a sub location of the location of the content
349
     *                                        or if set the remoteId exists already
350
     *
351
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
352
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct $locationCreateStruct
353
     *
354
     * @return \eZ\Publish\API\Repository\Values\Content\Location the newly created Location
355
     */
356
    public function createLocation(ContentInfo $contentInfo, LocationCreateStruct $locationCreateStruct)
357
    {
358
        $content = $this->repository->getContentService()->loadContent($contentInfo->id);
359
        $parentLocation = $this->loadLocation($locationCreateStruct->parentLocationId);
360
361
        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...
362
            throw new UnauthorizedException('content', 'create');
363
        }
364
365
        // Check if the parent is a sub location of one of the existing content locations (this also solves the
366
        // situation where parent location actually one of the content locations),
367
        // or if the content already has location below given location create struct parent
368
        $existingContentLocations = $this->loadLocations($content->contentInfo);
369
        if (!empty($existingContentLocations)) {
370
            foreach ($existingContentLocations as $existingContentLocation) {
371
                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...
372
                    throw new InvalidArgumentException(
373
                        '$locationCreateStruct',
374
                        'Specified parent is a sub location of one of the existing content locations.'
375
                    );
376
                }
377
                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...
378
                    throw new InvalidArgumentException(
379
                        '$locationCreateStruct',
380
                        'Content is already below the specified parent.'
381
                    );
382
                }
383
            }
384
        }
385
386
        $spiLocationCreateStruct = $this->domainMapper->buildSPILocationCreateStruct(
387
            $locationCreateStruct,
388
            $parentLocation,
389
            $content->contentInfo->mainLocationId !== null ? $content->contentInfo->mainLocationId : true,
390
            $content->contentInfo->id,
391
            $content->contentInfo->currentVersionNo
392
        );
393
394
        $this->repository->beginTransaction();
395
        try {
396
            $newLocation = $this->persistenceHandler->locationHandler()->create($spiLocationCreateStruct);
397
398
            $urlAliasNames = $this->nameSchemaService->resolveUrlAliasSchema($content);
399 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...
400
                $this->persistenceHandler->urlAliasHandler()->publishUrlAliasForLocation(
401
                    $newLocation->id,
402
                    $newLocation->parentId,
403
                    $name,
404
                    $languageCode,
405
                    $content->contentInfo->alwaysAvailable,
406
                    // @todo: this is legacy storage specific for updating ezcontentobject_tree.path_identification_string, to be removed
407
                    $languageCode === $content->contentInfo->mainLanguageCode
408
                );
409
            }
410
411
            $this->repository->commit();
412
        } catch (Exception $e) {
413
            $this->repository->rollback();
414
            throw $e;
415
        }
416
417
        return $this->domainMapper->buildLocationDomainObject($newLocation);
418
    }
419
420
    /**
421
     * Updates $location in the content repository.
422
     *
423
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to update this location
424
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException   if if set the remoteId exists already
425
     *
426
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
427
     * @param \eZ\Publish\API\Repository\Values\Content\LocationUpdateStruct $locationUpdateStruct
428
     *
429
     * @return \eZ\Publish\API\Repository\Values\Content\Location the updated Location
430
     */
431
    public function updateLocation(APILocation $location, LocationUpdateStruct $locationUpdateStruct)
432
    {
433
        if ($locationUpdateStruct->priority !== null && !is_int($locationUpdateStruct->priority)) {
434
            throw new InvalidArgumentValue('priority', $locationUpdateStruct->priority, 'LocationUpdateStruct');
435
        }
436
437
        if ($locationUpdateStruct->remoteId !== null && (!is_string($locationUpdateStruct->remoteId) || empty($locationUpdateStruct->remoteId))) {
438
            throw new InvalidArgumentValue('remoteId', $locationUpdateStruct->remoteId, 'LocationUpdateStruct');
439
        }
440
441
        if ($locationUpdateStruct->sortField !== null && !$this->domainMapper->isValidLocationSortField($locationUpdateStruct->sortField)) {
442
            throw new InvalidArgumentValue('sortField', $locationUpdateStruct->sortField, 'LocationUpdateStruct');
443
        }
444
445
        if ($locationUpdateStruct->sortOrder !== null && !$this->domainMapper->isValidLocationSortOrder($locationUpdateStruct->sortOrder)) {
446
            throw new InvalidArgumentValue('sortOrder', $locationUpdateStruct->sortOrder, 'LocationUpdateStruct');
447
        }
448
449
        $loadedLocation = $this->loadLocation($location->id);
450
451
        if ($locationUpdateStruct->remoteId !== null) {
452
            try {
453
                $existingLocation = $this->loadLocationByRemoteId($locationUpdateStruct->remoteId);
454
                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...
455
                    throw new InvalidArgumentException('locationUpdateStruct', 'location with provided remote ID already exists');
456
                }
457
            } catch (APINotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
458
            }
459
        }
460
461
        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...
462
            throw new UnauthorizedException('content', 'edit');
463
        }
464
465
        $updateStruct = new UpdateStruct();
466
        $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...
467
        $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...
468
        $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...
469
        $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...
470
471
        $this->repository->beginTransaction();
472
        try {
473
            $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...
474
            $this->repository->commit();
475
        } catch (Exception $e) {
476
            $this->repository->rollback();
477
            throw $e;
478
        }
479
480
        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...
481
    }
482
483
    /**
484
     * Swaps the contents held by $location1 and $location2.
485
     *
486
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to swap content
487
     *
488
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location1
489
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location2
490
     */
491
    public function swapLocation(APILocation $location1, APILocation $location2)
492
    {
493
        $loadedLocation1 = $this->loadLocation($location1->id);
494
        $loadedLocation2 = $this->loadLocation($location2->id);
495
496
        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...
497
            throw new UnauthorizedException('content', 'edit');
498
        }
499
        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...
500
            throw new UnauthorizedException('content', 'edit');
501
        }
502
503
        $this->repository->beginTransaction();
504
        try {
505
            $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...
506
            $this->persistenceHandler->urlAliasHandler()->locationSwapped(
507
                $location1->id,
508
                $location1->parentLocationId,
509
                $location2->id,
510
                $location2->parentLocationId
511
            );
512
            $this->repository->commit();
513
        } catch (Exception $e) {
514
            $this->repository->rollback();
515
            throw $e;
516
        }
517
    }
518
519
    /**
520
     * Hides the $location and marks invisible all descendants of $location.
521
     *
522
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to hide this location
523
     *
524
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
525
     *
526
     * @return \eZ\Publish\API\Repository\Values\Content\Location $location, with updated hidden value
527
     */
528 View Code Duplication
    public function hideLocation(APILocation $location)
529
    {
530
        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...
531
            throw new UnauthorizedException('content', 'hide');
532
        }
533
534
        $this->repository->beginTransaction();
535
        try {
536
            $this->persistenceHandler->locationHandler()->hide($location->id);
537
            $this->repository->commit();
538
        } catch (Exception $e) {
539
            $this->repository->rollback();
540
            throw $e;
541
        }
542
543
        return $this->loadLocation($location->id);
544
    }
545
546
    /**
547
     * Unhides the $location.
548
     *
549
     * This method and marks visible all descendants of $locations
550
     * until a hidden location is found.
551
     *
552
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to unhide this location
553
     *
554
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
555
     *
556
     * @return \eZ\Publish\API\Repository\Values\Content\Location $location, with updated hidden value
557
     */
558 View Code Duplication
    public function unhideLocation(APILocation $location)
559
    {
560
        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...
561
            throw new UnauthorizedException('content', 'hide');
562
        }
563
564
        $this->repository->beginTransaction();
565
        try {
566
            $this->persistenceHandler->locationHandler()->unHide($location->id);
567
            $this->repository->commit();
568
        } catch (Exception $e) {
569
            $this->repository->rollback();
570
            throw $e;
571
        }
572
573
        return $this->loadLocation($location->id);
574
    }
575
576
    /**
577
     * Moves the subtree to $newParentLocation.
578
     *
579
     * If a user has the permission to move the location to a target location
580
     * he can do it regardless of an existing descendant on which the user has no permission.
581
     *
582
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to move this location to the target
583
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user does not have read access to the whole source subtree
584
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If the new parent is in a subtree of the location
585
     *
586
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
587
     * @param \eZ\Publish\API\Repository\Values\Content\Location $newParentLocation
588
     */
589
    public function moveSubtree(APILocation $location, APILocation $newParentLocation)
590
    {
591
        $location = $this->loadLocation($location->id);
592
        $newParentLocation = $this->loadLocation($newParentLocation->id);
593
594
        // check create permission on target location
595
        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...
596
            throw new UnauthorizedException('content', 'create');
597
        }
598
599
        /** Check read access to whole source subtree
600
         * @var bool|\eZ\Publish\API\Repository\Values\Content\Query\Criterion
601
         */
602
        $contentReadCriterion = $this->permissionsCriterionHandler->getPermissionsCriterion();
603 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...
604
            throw new UnauthorizedException('content', 'read');
605
        } elseif ($contentReadCriterion !== true) {
606
            // Query if there are any content in subtree current user don't have access to
607
            $query = new Query(
608
                array(
609
                    'limit' => 0,
610
                    'filter' => new CriterionLogicalAnd(
611
                        array(
612
                            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...
613
                            new CriterionLogicalNot($contentReadCriterion),
0 ignored issues
show
Bug introduced by
It seems like $contentReadCriterion defined by $this->permissionsCriter...tPermissionsCriterion() on line 602 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...
614
                        )
615
                    ),
616
                )
617
            );
618
            $result = $this->repository->getSearchService()->findContent($query, array(), false);
619
            if ($result->totalCount > 0) {
620
                throw new UnauthorizedException('content', 'read');
621
            }
622
        }
623
624
        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...
625
            throw new InvalidArgumentException(
626
                '$newParentLocation',
627
                'new parent location is in a subtree of the given $location'
628
            );
629
        }
630
631
        $this->repository->beginTransaction();
632
        try {
633
            $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...
634
635
            $content = $this->repository->getContentService()->loadContent($location->contentId);
636
            $urlAliasNames = $this->nameSchemaService->resolveUrlAliasSchema($content);
637 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...
638
                $this->persistenceHandler->urlAliasHandler()->publishUrlAliasForLocation(
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
                    $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...
641
                    $name,
642
                    $languageCode,
643
                    $content->contentInfo->alwaysAvailable
644
                );
645
            }
646
647
            $this->persistenceHandler->urlAliasHandler()->locationMoved(
648
                $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...
649
                $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...
650
                $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...
651
            );
652
653
            $this->repository->commit();
654
        } catch (Exception $e) {
655
            $this->repository->rollback();
656
            throw $e;
657
        }
658
    }
659
660
    /**
661
     * Deletes $location and all its descendants.
662
     *
663
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user is not allowed to delete this location or a descendant
664
     *
665
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
666
     */
667
    public function deleteLocation(APILocation $location)
668
    {
669
        $location = $this->loadLocation($location->id);
670
671
        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...
672
            throw new UnauthorizedException('content', 'manage_locations');
673
        }
674
        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...
675
            throw new UnauthorizedException('content', 'remove');
676
        }
677
678
        /** Check remove access to descendants
679
         * @var bool|\eZ\Publish\API\Repository\Values\Content\Query\Criterion
680
         */
681
        $contentReadCriterion = $this->permissionsCriterionHandler->getPermissionsCriterion('content', 'remove');
682 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...
683
            throw new UnauthorizedException('content', 'remove');
684
        } elseif ($contentReadCriterion !== true) {
685
            // Query if there are any content in subtree current user don't have access to
686
            $query = new Query(
687
                array(
688
                    'limit' => 0,
689
                    'filter' => new CriterionLogicalAnd(
690
                        array(
691
                            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...
692
                            new CriterionLogicalNot($contentReadCriterion),
0 ignored issues
show
Bug introduced by
It seems like $contentReadCriterion defined by $this->permissionsCriter...on('content', 'remove') on line 681 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...
693
                        )
694
                    ),
695
                )
696
            );
697
            $result = $this->repository->getSearchService()->findContent($query, array(), false);
698
            if ($result->totalCount > 0) {
699
                throw new UnauthorizedException('content', 'remove');
700
            }
701
        }
702
703
        $this->repository->beginTransaction();
704
        try {
705
            $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...
706
            $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...
707
            $this->repository->commit();
708
        } catch (Exception $e) {
709
            $this->repository->rollback();
710
            throw $e;
711
        }
712
    }
713
714
    /**
715
     * Instantiates a new location create class.
716
     *
717
     * @param mixed $parentLocationId the parent under which the new location should be created
718
     *
719
     * @return \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct
720
     */
721
    public function newLocationCreateStruct($parentLocationId)
722
    {
723
        return new LocationCreateStruct(
724
            array(
725
                'parentLocationId' => $parentLocationId,
726
            )
727
        );
728
    }
729
730
    /**
731
     * Instantiates a new location update class.
732
     *
733
     * @return \eZ\Publish\API\Repository\Values\Content\LocationUpdateStruct
734
     */
735
    public function newLocationUpdateStruct()
736
    {
737
        return new LocationUpdateStruct();
738
    }
739
}
740