Completed
Push — master ( 8107b6...19db21 )
by
unknown
20:08
created

LocationService::getAllLocationsCount()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the LocationUpdateStruct 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\REST\Client;
10
11
use eZ\Publish\API\Repository\LocationService as APILocationService;
12
use eZ\Publish\API\Repository\Values\Content\LocationUpdateStruct;
13
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
14
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
15
use eZ\Publish\API\Repository\Values\Content\Location;
16
use eZ\Publish\API\Repository\Values\Content\VersionInfo;
17
use eZ\Publish\Core\REST\Common\RequestParser;
18
use eZ\Publish\Core\REST\Common\Input\Dispatcher;
19
use eZ\Publish\Core\REST\Common\Output\Visitor;
20
use eZ\Publish\Core\REST\Common\Message;
21
use eZ\Publish\API\Repository\Values\ContentType\ContentType;
22
23
/**
24
 * Location service, used for complex subtree operations.
25
 *
26
 * @example Examples/location.php
27
 */
28
class LocationService implements APILocationService, Sessionable
29
{
30
    /**
31
     * @var \eZ\Publish\Core\REST\Client\HttpClient
32
     */
33
    private $client;
34
35
    /**
36
     * @var \eZ\Publish\Core\REST\Common\Input\Dispatcher
37
     */
38
    private $inputDispatcher;
39
40
    /**
41
     * @var \eZ\Publish\Core\REST\Common\Output\Visitor
42
     */
43
    private $outputVisitor;
44
45
    /**
46
     * @var \eZ\Publish\Core\REST\Common\RequestParser
47
     */
48
    private $requestParser;
49
50
    /**
51
     * @param \eZ\Publish\Core\REST\Client\HttpClient $client
52
     * @param \eZ\Publish\Core\REST\Common\Input\Dispatcher $inputDispatcher
53
     * @param \eZ\Publish\Core\REST\Common\Output\Visitor $outputVisitor
54
     * @param \eZ\Publish\Core\REST\Common\RequestParser $requestParser
55
     */
56 View Code Duplication
    public function __construct(HttpClient $client, Dispatcher $inputDispatcher, Visitor $outputVisitor, RequestParser $requestParser)
57
    {
58
        $this->client = $client;
59
        $this->inputDispatcher = $inputDispatcher;
60
        $this->outputVisitor = $outputVisitor;
61
        $this->requestParser = $requestParser;
62
    }
63
64
    /**
65
     * Set session ID.
66
     *
67
     * Only for testing
68
     *
69
     * @param mixed $id
70
     *
71
     * @private
72
     */
73
    public function setSession($id)
74
    {
75
        if ($this->outputVisitor instanceof Sessionable) {
76
            $this->outputVisitor->setSession($id);
77
        }
78
    }
79
80
    /**
81
     * Instantiates a new location create class.
82
     *
83
     * @param mixed $parentLocationId the parent under which the new location should be created
84
     * @param \eZ\Publish\API\Repository\Values\ContentType\ContentType|null $contentType
85
     *
86
     * @return \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct
87
     */
88 View Code Duplication
    public function newLocationCreateStruct($parentLocationId, ContentType $contentType = null)
89
    {
90
        $properties = [
91
            'parentLocationId' => $parentLocationId,
92
        ];
93
        if ($contentType) {
94
            $properties['sortField'] = $contentType->defaultSortField;
95
            $properties['sortOrder'] = $contentType->defaultSortOrder;
96
        }
97
98
        return new LocationCreateStruct($properties);
99
    }
100
101
    /**
102
     * Creates the new $location in the content repository for the given content.
103
     *
104
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to create this location
105
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException  if the content is already below the specified parent
106
     *                                        or the parent is a sub location of the location the content
107
     *                                        or if set the remoteId exists already
108
     *
109
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
110
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct $locationCreateStruct
111
     *
112
     * @return \eZ\Publish\API\Repository\Values\Content\Location the newly created Location
113
     */
114
    public function createLocation(ContentInfo $contentInfo, LocationCreateStruct $locationCreateStruct)
115
    {
116
        $inputMessage = $this->outputVisitor->visit($locationCreateStruct);
117
        $inputMessage->headers['Accept'] = $this->outputVisitor->getMediaType('Location');
118
119
        $values = $this->requestParser->parse('object', $contentInfo->id);
120
        $result = $this->client->request(
121
            'POST',
122
            $this->requestParser->generate('objectLocations', array('object' => $values['object'])),
123
            $inputMessage
124
        );
125
126
        return $this->inputDispatcher->parse($result);
127
    }
128
129
    /**
130
     * Loads a location object from its $locationId.
131
     *
132
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to read this location
133
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If the specified location is not found
134
     *
135
     * @param mixed $locationId
136
     * @param string[]|null $prioritizedLanguages Used as prioritized language code on translated properties of returned object.
137
     *
138
     * @return \eZ\Publish\API\Repository\Values\Content\Location
139
     */
140 View Code Duplication
    public function loadLocation($locationId, array $prioritizedLanguages = null)
141
    {
142
        $response = $this->client->request(
143
            'GET',
144
            $locationId,
145
            new Message(
146
                array('Accept' => $this->outputVisitor->getMediaType('Location'))
147
            )
148
        );
149
150
        return $this->inputDispatcher->parse($response);
151
    }
152
153
    /**
154
     * Loads a location object from its $remoteId.
155
     *
156
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to read this location
157
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If the specified location is not found
158
     *
159
     * @param string $remoteId
160
     * @param string[]|null $prioritizedLanguages Used as prioritized language code on translated properties of returned object.
161
     *
162
     * @return \eZ\Publish\API\Repository\Values\Content\Location
163
     */
164
    public function loadLocationByRemoteId($remoteId, array $prioritizedLanguages = null)
165
    {
166
        $response = $this->client->request(
167
            'GET',
168
            $this->requestParser->generate('locationByRemote', array('location' => $remoteId)),
169
            new Message(
170
                array('Accept' => $this->outputVisitor->getMediaType('LocationList'))
171
            )
172
        );
173
174
        return reset($this->inputDispatcher->parse($response));
0 ignored issues
show
Bug introduced by
$this->inputDispatcher->parse($response) cannot be passed to reset() as the parameter $array expects a reference.
Loading history...
175
    }
176
177
    /**
178
     * Instantiates a new location update class.
179
     *
180
     * @return \eZ\Publish\API\Repository\Values\Content\LocationUpdateStruct
181
     */
182
    public function newLocationUpdateStruct()
183
    {
184
        return new LocationUpdateStruct();
185
    }
186
187
    /**
188
     * Updates $location in the content repository.
189
     *
190
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to update this location
191
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException   if if set the remoteId exists already
192
     *
193
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
194
     * @param \eZ\Publish\API\Repository\Values\Content\LocationUpdateStruct $locationUpdateStruct
195
     *
196
     * @return \eZ\Publish\API\Repository\Values\Content\Location the updated Location
197
     */
198
    public function updateLocation(Location $location, LocationUpdateStruct $locationUpdateStruct)
199
    {
200
        $inputMessage = $this->outputVisitor->visit($locationUpdateStruct);
201
        $inputMessage->headers['Accept'] = $this->outputVisitor->getMediaType('Location');
202
        $inputMessage->headers['X-HTTP-Method-Override'] = 'PATCH';
203
204
        $result = $this->client->request(
205
            'POST',
206
            $location->id,
207
            $inputMessage
208
        );
209
210
        return $this->inputDispatcher->parse($result);
211
    }
212
213
    /**
214
     * Loads the locations for the given content object.
215
     *
216
     * If a $rootLocation is given, only locations that belong to this location are returned.
217
     * The location list is also filtered by permissions on reading locations.
218
     *
219
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if there is no published version yet
220
     *
221
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
222
     * @param \eZ\Publish\API\Repository\Values\Content\Location $rootLocation
223
     * @param string[]|null $prioritizedLanguages Used as prioritized language code on translated properties of returned object.
224
     *
225
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
226
     */
227 View Code Duplication
    public function loadLocations(ContentInfo $contentInfo, Location $rootLocation = null, array $prioritizedLanguages = null)
228
    {
229
        $values = $this->requestParser->parse('object', $contentInfo->id);
230
        $response = $this->client->request(
231
            'GET',
232
            $this->requestParser->generate('objectLocations', array('object' => $values['object'])),
233
            new Message(
234
                array('Accept' => $this->outputVisitor->getMediaType('LocationList'))
235
            )
236
        );
237
238
        return $this->inputDispatcher->parse($response);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->inputDispatcher->parse($response); (eZ\Publish\API\Repository\Values\ValueObject) is incompatible with the return type declared by the interface eZ\Publish\API\Repositor...nService::loadLocations of type eZ\Publish\API\Repositor...lues\Content\Location[].

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

Let’s take a look at an example:

class Author {
    private $name;

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

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

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

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

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

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

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

Loading history...
239
    }
240
241
    /**
242
     * Loads children which are readable by the current user of a location object sorted by sortField and sortOrder.
243
     *
244
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
245
     * @param int $offset the start offset for paging
246
     * @param int $limit the number of locations returned
247
     * @param string[]|null $prioritizedLanguages Used as prioritized language code on translated properties of returned object.
248
     *
249
     * @return \eZ\Publish\API\Repository\Values\Content\LocationList
250
     */
251 View Code Duplication
    public function loadLocationChildren(Location $location, $offset = 0, $limit = 25, array $prioritizedLanguages = null)
252
    {
253
        $values = $this->requestParser->parse('location', $location->id);
254
        $response = $this->client->request(
255
            'GET',
256
            $this->requestParser->generate('locationChildren', array('location' => $values['location'])),
257
            new Message(
258
                array('Accept' => $this->outputVisitor->getMediaType('LocationList'))
259
            )
260
        );
261
262
        return $this->inputDispatcher->parse($response);
263
    }
264
265
    /**
266
     * Load parent Locations for Content Draft.
267
     *
268
     * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo
269
     * @param string[]|null $prioritizedLanguages Used as prioritized language code on translated properties of returned object.
270
     *
271
     * @return \eZ\Publish\API\Repository\Values\Content\Location[] List of parent Locations
272
     */
273
    public function loadParentLocationsForDraftContent(VersionInfo $versionInfo, array $prioritizedLanguages = null)
274
    {
275
        throw new \Exception('@todo: Implement.');
276
    }
277
278
    /**
279
     * Returns the number of children which are readable by the current user of a location object.
280
     *
281
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
282
     *
283
     * @return int
284
     */
285
    public function getLocationChildCount(Location $location)
286
    {
287
        throw new \Exception('@todo: Implement.');
288
    }
289
290
    /**
291
     * Swaps the contents hold by the $location1 and $location2.
292
     *
293
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to swap content
294
     *
295
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location1
296
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location2
297
     */
298
    public function swapLocation(Location $location1, Location $location2)
299
    {
300
        throw new \Exception('@todo: Implement.');
301
    }
302
303
    /**
304
     * Hides the $location and marks invisible all descendants of $location.
305
     *
306
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to hide this location
307
     *
308
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
309
     *
310
     * @return \eZ\Publish\API\Repository\Values\Content\Location $location, with updated hidden value
311
     */
312
    public function hideLocation(Location $location)
313
    {
314
        throw new \Exception('@todo: Implement.');
315
    }
316
317
    /**
318
     * Unhides the $location.
319
     *
320
     * This method and marks visible all descendants of $locations
321
     * until a hidden location is found.
322
     *
323
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to unhide this location
324
     *
325
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
326
     *
327
     * @return \eZ\Publish\API\Repository\Values\Content\Location $location, with updated hidden value
328
     */
329
    public function unhideLocation(Location $location)
330
    {
331
        throw new \Exception('@todo: Implement.');
332
    }
333
334
    /**
335
     * Deletes $location and all its descendants.
336
     *
337
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user is not allowed to delete this location or a descendant
338
     *
339
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
340
     */
341
    public function deleteLocation(Location $location)
342
    {
343
        throw new \Exception('@todo: Implement.');
344
    }
345
346
    /**
347
     * Copies the subtree starting from $subtree as a new subtree of $targetLocation.
348
     *
349
     * Only the items on which the user has read access are copied.
350
     *
351
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed copy the subtree to the given parent location
352
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException  if the target location is a sub location of the given location
353
     *
354
     * @param \eZ\Publish\API\Repository\Values\Content\Location $subtree - the subtree denoted by the location to copy
355
     * @param \eZ\Publish\API\Repository\Values\Content\Location $targetParentLocation - the target parent location for the copy operation
356
     *
357
     * @return \eZ\Publish\API\Repository\Values\Content\Location The newly created location of the copied subtree
358
     *
359
     * @todo enhancement - this method should return a result structure containing the new location and a list
360
     *       of locations which are not copied due to permission denials.
361
     */
362
    public function copySubtree(Location $subtree, Location $targetParentLocation)
363
    {
364
        throw new \Exception('@todo: Implement.');
365
    }
366
367
    /**
368
     * Moves the subtree to $newParentLocation.
369
     *
370
     * If a user has the permission to move the location to a target location
371
     * he can do it regardless of an existing descendant on which the user has no permission.
372
     *
373
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to move this location to the target
374
     *
375
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
376
     * @param \eZ\Publish\API\Repository\Values\Content\Location $newParentLocation
377
     */
378
    public function moveSubtree(Location $location, Location $newParentLocation)
379
    {
380
        throw new \Exception('@todo: Implement.');
381
    }
382
383
    public function getAllLocationsCount(): int
384
    {
385
        throw new \Exception('@todo: Implement.');
386
    }
387
388
    /**
389
     * @param int $limit
390
     * @param int $offset
391
     *
392
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
393
     *
394
     * @throws \Exception
395
     */
396
    public function loadAllLocations(int $offset = 0, int $limit = 25): array
397
    {
398
        throw new \Exception('@todo: Implement.');
399
    }
400
}
401