Completed
Push — ezp-24830_REST_for_role_drafts ( a61586...6f0e8c )
by
unknown
30:00
created

Role::addPolicyByRoleDraft()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 33
Code Lines 19

Duplication

Lines 33
Ratio 100 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 33
loc 33
rs 8.5806
cc 4
eloc 19
nc 4
nop 2
1
<?php
2
3
/**
4
 * File containing the Role controller 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
 * @version //autogentag//
10
 */
11
namespace eZ\Publish\Core\REST\Server\Controller;
12
13
use eZ\Publish\API\Repository\Exceptions\LimitationValidationException;
14
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
15
use eZ\Publish\Core\Base\Exceptions\ForbiddenException;
16
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;
17
use eZ\Publish\Core\Base\Exceptions\UnauthorizedException;
18
use eZ\Publish\Core\REST\Common\Message;
19
use eZ\Publish\Core\REST\Common\Exceptions;
20
use eZ\Publish\Core\REST\Server\Exceptions\BadRequestException;
21
use eZ\Publish\Core\REST\Server\Values;
22
use eZ\Publish\Core\REST\Server\Controller as RestController;
23
use eZ\Publish\API\Repository\RoleService;
24
use eZ\Publish\API\Repository\UserService;
25
use eZ\Publish\API\Repository\LocationService;
26
use eZ\Publish\API\Repository\Values\User\RoleCreateStruct;
27
use eZ\Publish\API\Repository\Values\User\RoleUpdateStruct;
28
use eZ\Publish\API\Repository\Exceptions\NotFoundException as APINotFoundException;
29
use Symfony\Component\HttpFoundation\Request;
30
31
/**
32
 * Role controller.
33
 */
34
class Role extends RestController
35
{
36
    /**
37
     * Role service.
38
     *
39
     * @var \eZ\Publish\API\Repository\RoleService
40
     */
41
    protected $roleService;
42
43
    /**
44
     * User service.
45
     *
46
     * @var \eZ\Publish\API\Repository\UserService
47
     */
48
    protected $userService;
49
50
    /**
51
     * Location service.
52
     *
53
     * @var \eZ\Publish\API\Repository\LocationService
54
     */
55
    protected $locationService;
56
57
    /**
58
     * Construct controller.
59
     *
60
     * @param \eZ\Publish\API\Repository\RoleService $roleService
61
     * @param \eZ\Publish\API\Repository\UserService $userService
62
     * @param \eZ\Publish\API\Repository\LocationService $locationService
63
     */
64
    public function __construct(
65
        RoleService $roleService,
66
        UserService $userService,
67
        LocationService $locationService
68
    ) {
69
        $this->roleService = $roleService;
70
        $this->userService = $userService;
71
        $this->locationService = $locationService;
72
    }
73
74
    /**
75
     * Create new role.
76
     *
77
     * Defaults to publishing the role, but you can create a draft instead by setting the POST parameter publish=false
78
     *
79
     * @return \eZ\Publish\Core\REST\Server\Values\CreatedRole
80
     */
81
    public function createRole(Request $request)
82
    {
83
        $publish = (
84
            !$request->query->has('publish') ||
85
            ($request->query->has('publish') && $request->query->get('publish') === 'true')
86
        );
87
88
        try {
89
            $roleDraft = $this->roleService->createRole(
90
                $this->inputDispatcher->parse(
0 ignored issues
show
Compatibility introduced by
$this->inputDispatcher->...request->getContent())) of type object<eZ\Publish\API\Re...ory\Values\ValueObject> is not a sub-type of object<eZ\Publish\API\Re...\User\RoleCreateStruct>. It seems like you assume a child class of the class eZ\Publish\API\Repository\Values\ValueObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
91
                    new Message(
92
                        [
93
                            'Content-Type' => $request->headers->get('Content-Type'),
94
                            // @todo Needs refactoring! Temporary solution so parser has access to get parameters
95
                            '__publish' => $publish,
96
                        ],
97
                        $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, eZ\Publish\Core\REST\Common\Message::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

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

An additional type check may prevent trouble.

Loading history...
98
                    )
99
                )
100
            );
101
        } catch (InvalidArgumentException $e) {
102
            throw new ForbiddenException($e->getMessage());
103
        } catch (UnauthorizedException $e) {
104
            throw new ForbiddenException($e->getMessage());
105
        } catch (LimitationValidationException $e) {
106
            throw new BadRequestException($e->getMessage());
107
        } catch (Exceptions\Parser $e) {
108
            throw new BadRequestException($e->getMessage());
109
        }
110
111
        if ($publish) {
112
            @trigger_error(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
113
                "Create and publish role in the same operation is deprecated, and will be removed in the future.\n" .
114
                'Publish the role draft in a separate action.',
115
                E_USER_DEPRECATED
116
            );
117
118
            $this->roleService->publishRoleDraft($roleDraft);
119
120
            $role = $this->roleService->loadRole($roleDraft->id);
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\User\Role. 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...
121
122
            return new Values\CreatedRole(['role' => new Values\RestRole($role)]);
123
        }
124
125
        return new Values\CreatedRole(['role' => new Values\RestRole($roleDraft)]);
126
    }
127
128
    /**
129
     * Creates a new RoleDraft for an existing Role.
130
     *
131
     * @since 6.1
132
     *
133
     * @return \eZ\Publish\Core\REST\Server\Values\CreatedRole
134
     */
135
    public function createRoleDraft($roleId, Request $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
136
    {
137
        try {
138
            $roleDraft = $this->roleService->createRoleDraft(
139
                $this->roleService->loadRole($roleId)
140
            );
141
        } catch (InvalidArgumentException $e) {
142
            throw new ForbiddenException($e->getMessage());
143
        } catch (UnauthorizedException $e) {
144
            throw new ForbiddenException($e->getMessage());
145
        } catch (LimitationValidationException $e) {
146
            throw new BadRequestException($e->getMessage());
147
        } catch (Exceptions\Parser $e) {
148
            throw new BadRequestException($e->getMessage());
149
        }
150
151
        return new Values\CreatedRole(['role' => new Values\RestRole($roleDraft)]);
152
    }
153
154
    /**
155
     * Loads list of roles.
156
     *
157
     * @return \eZ\Publish\Core\REST\Server\Values\RoleList
158
     */
159
    public function listRoles(Request $request)
160
    {
161
        $roles = array();
162
        if ($request->query->has('identifier')) {
163
            try {
164
                $role = $this->roleService->loadRoleByIdentifier($request->query->get('identifier'));
165
                $roles[] = $role;
166
            } catch (APINotFoundException $e) {
167
                // Do nothing
168
            }
169
        } else {
170
            $offset = $request->query->has('offset') ? (int)$request->query->get('offset') : 0;
171
            $limit = $request->query->has('limit') ? (int)$request->query->get('limit') : -1;
172
173
            $roles = array_slice(
174
                $this->roleService->loadRoles(),
175
                $offset >= 0 ? $offset : 0,
176
                $limit >= 0 ? $limit : null
177
            );
178
        }
179
180
        return new Values\RoleList($roles, $request->getPathInfo());
181
    }
182
183
    /**
184
     * Loads role.
185
     *
186
     * @param $roleId
187
     *
188
     * @return \eZ\Publish\API\Repository\Values\User\Role
189
     */
190
    public function loadRole($roleId)
191
    {
192
        return $this->roleService->loadRole($roleId);
193
    }
194
195
    /**
196
     * Loads a role draft.
197
     *
198
     * @param mixed $roleId Original role ID, or ID of the role draft itself
199
     *
200
     * @return \eZ\Publish\API\Repository\Values\User\RoleDraft
201
     */
202
    public function loadRoleDraft($roleId)
203
    {
204
        try {
205
            // First try to load the draft for given role.
206
            return $this->roleService->loadRoleDraftByRoleId($roleId);
207
        } catch (NotFoundException $e) {
208
            // We might want a newly created role, so try to load it by its ID.
209
            // loadRoleDraft() might throw a NotFoundException (wrong $roleId). If so, let it bubble up.
210
            return $this->roleService->loadRoleDraft($roleId);
211
        }
212
    }
213
214
    /**
215
     * Updates a role.
216
     *
217
     * @param $roleId
218
     *
219
     * @return \eZ\Publish\API\Repository\Values\User\Role
220
     */
221
    public function updateRole($roleId, Request $request)
222
    {
223
        $createStruct = $this->inputDispatcher->parse(
224
            new Message(
225
                array('Content-Type' => $request->headers->get('Content-Type')),
226
                $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, eZ\Publish\Core\REST\Common\Message::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

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

An additional type check may prevent trouble.

Loading history...
227
            )
228
        );
229
230
        return $this->roleService->updateRole(
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...leService::updateRole() has been deprecated with message: since 6.0, use {@see updateRoleDraft}

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...
231
            $this->roleService->loadRole($roleId),
232
            $this->mapToUpdateStruct($createStruct)
0 ignored issues
show
Compatibility introduced by
$createStruct of type object<eZ\Publish\API\Re...ory\Values\ValueObject> is not a sub-type of object<eZ\Publish\API\Re...\User\RoleCreateStruct>. It seems like you assume a child class of the class eZ\Publish\API\Repository\Values\ValueObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
233
        );
234
    }
235
236
    /**
237
     * Updates a role draft.
238
     *
239
     * @param mixed $roleId Original role ID, or ID of the role draft itself
240
     *
241
     * @return \eZ\Publish\API\Repository\Values\User\RoleDraft
242
     */
243
    public function updateRoleDraft($roleId, Request $request)
244
    {
245
        $createStruct = $this->inputDispatcher->parse(
246
            new Message(
247
                array('Content-Type' => $request->headers->get('Content-Type')),
248
                $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, eZ\Publish\Core\REST\Common\Message::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

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

An additional type check may prevent trouble.

Loading history...
249
            )
250
        );
251
252
        try {
253
            // First try to load the draft for given role.
254
            $roleDraft = $this->roleService->loadRoleDraftByRoleId($roleId);
255
        } catch (NotFoundException $e) {
256
            // We might want a newly created role, so try to load it by its ID.
257
            // loadRoleDraft() might throw a NotFoundException (wrong $roleId). If so, let it bubble up.
258
            $roleDraft = $this->roleService->loadRoleDraft($roleId);
259
        }
260
261
        return $this->roleService->updateRoleDraft($roleDraft, $this->mapToUpdateStruct($createStruct));
0 ignored issues
show
Compatibility introduced by
$createStruct of type object<eZ\Publish\API\Re...ory\Values\ValueObject> is not a sub-type of object<eZ\Publish\API\Re...\User\RoleCreateStruct>. It seems like you assume a child class of the class eZ\Publish\API\Repository\Values\ValueObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
262
    }
263
264
    /**
265
     * Publishes a role draft.
266
     *
267
     * @param mixed $roleId Original role ID, or ID of the role draft itself
268
     * @return Values\RestRole
269
     */
270
    public function publishRoleDraft($roleId)
271
    {
272
        try {
273
            // First try to load the draft for given role.
274
            $roleDraft = $this->roleService->loadRoleDraftByRoleId($roleId);
275
        } catch (NotFoundException $e) {
276
            // We might want a newly created role, so try to load it by its ID.
277
            // loadRoleDraft() might throw a NotFoundException (wrong $roleId). If so, let it bubble up.
278
            $roleDraft = $this->roleService->loadRoleDraft($roleId);
279
        }
280
281
        $this->roleService->publishRoleDraft($roleDraft);
282
        $publishedRole = $this->roleService->loadRole($roleDraft->id);
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\User\Role. 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...
283
284
        return new Values\CreatedRole(['role' => new Values\RestRole($publishedRole)]);
285
    }
286
287
    /**
288
     * Delete a role by ID.
289
     *
290
     * @param $roleId
291
     *
292
     * @return \eZ\Publish\Core\REST\Server\Values\NoContent
293
     */
294
    public function deleteRole($roleId)
295
    {
296
        $this->roleService->deleteRole(
297
            $this->roleService->loadRole($roleId)
298
        );
299
300
        return new Values\NoContent();
301
    }
302
303
    /**
304
     * Delete a role draft by ID.
305
     *
306
     * @param $roleId
307
     *
308
     * @return \eZ\Publish\Core\REST\Server\Values\NoContent
309
     */
310
    public function deleteRoleDraft($roleId)
311
    {
312
        $this->roleService->deleteRoleDraft(
313
            $this->roleService->loadRoleDraft($roleId)
314
        );
315
316
        return new Values\NoContent();
317
    }
318
319
    /**
320
     * Loads the policies for the role.
321
     *
322
     * @param $roleId
323
     *
324
     * @return \eZ\Publish\Core\REST\Server\Values\PolicyList
325
     */
326
    public function loadPolicies($roleId, Request $request)
327
    {
328
        $loadedRole = $this->roleService->loadRole($roleId);
329
330
        return new Values\PolicyList($loadedRole->getPolicies(), $request->getPathInfo());
331
    }
332
333
    /**
334
     * Deletes all policies from a role.
335
     *
336
     * @param $roleId
337
     *
338
     * @return \eZ\Publish\Core\REST\Server\Values\NoContent
339
     */
340
    public function deletePolicies($roleId)
341
    {
342
        $loadedRole = $this->roleService->loadRole($roleId);
343
344
        foreach ($loadedRole->getPolicies() as $policy) {
345
            $this->roleService->deletePolicy($policy);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...Service::deletePolicy() has been deprecated with message: since 6.0, use {@link removePolicyByRoleDraft()} instead.

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...
346
        }
347
348
        return new Values\NoContent();
349
    }
350
351
    /**
352
     * Loads a policy.
353
     *
354
     * @param $roleId
355
     * @param $policyId
356
     *
357
     * @throws \eZ\Publish\Core\REST\Common\Exceptions\NotFoundException
358
     *
359
     * @return \eZ\Publish\API\Repository\Values\User\Policy
360
     */
361
    public function loadPolicy($roleId, $policyId, Request $request)
362
    {
363
        $loadedRole = $this->roleService->loadRole($roleId);
364
        foreach ($loadedRole->getPolicies() as $policy) {
365
            if ($policy->id == $policyId) {
366
                return $policy;
367
            }
368
        }
369
370
        throw new Exceptions\NotFoundException("Policy not found: '{$request->getPathInfo()}'.");
371
    }
372
373
    /**
374
     * Adds a policy to role.
375
     *
376
     * @param $roleId
377
     *
378
     * @return \eZ\Publish\Core\REST\Server\Values\CreatedPolicy
379
     */
380 View Code Duplication
    public function addPolicy($roleId, Request $request)
381
    {
382
        $createStruct = $this->inputDispatcher->parse(
383
            new Message(
384
                array('Content-Type' => $request->headers->get('Content-Type')),
385
                $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, eZ\Publish\Core\REST\Common\Message::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

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

An additional type check may prevent trouble.

Loading history...
386
            )
387
        );
388
389
        try {
390
            $role = $this->roleService->addPolicy(
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repository\RoleService::addPolicy() has been deprecated with message: since 6.0, use {@see addPolicyByRoleDraft}

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...
391
                $this->roleService->loadRole($roleId),
392
                $createStruct
0 ignored issues
show
Compatibility introduced by
$createStruct of type object<eZ\Publish\API\Re...ory\Values\ValueObject> is not a sub-type of object<eZ\Publish\API\Re...ser\PolicyCreateStruct>. It seems like you assume a child class of the class eZ\Publish\API\Repository\Values\ValueObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
393
            );
394
        } catch (LimitationValidationException $e) {
395
            throw new BadRequestException($e->getMessage());
396
        }
397
398
        $policies = $role->getPolicies();
399
400
        $policyToReturn = $policies[0];
401
        for ($i = 1, $count = count($policies); $i < $count; ++$i) {
402
            if ($policies[$i]->id > $policyToReturn->id) {
403
                $policyToReturn = $policies[$i];
404
            }
405
        }
406
407
        return new Values\CreatedPolicy(
408
            array(
409
                'policy' => $policyToReturn,
410
            )
411
        );
412
    }
413
414
    /**
415
     * Adds a policy to a role draft.
416
     *
417
     * @param $roleId
418
     *
419
     * @return \eZ\Publish\Core\REST\Server\Values\CreatedPolicy
420
     */
421 View Code Duplication
    public function addPolicyByRoleDraft($roleId, Request $request)
422
    {
423
        $createStruct = $this->inputDispatcher->parse(
424
            new Message(
425
                array('Content-Type' => $request->headers->get('Content-Type')),
426
                $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, eZ\Publish\Core\REST\Common\Message::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

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

An additional type check may prevent trouble.

Loading history...
427
            )
428
        );
429
430
        try {
431
            $role = $this->roleService->addPolicyByRoleDraft(
432
                $this->roleService->loadRoleDraft($roleId),
433
                $createStruct
0 ignored issues
show
Compatibility introduced by
$createStruct of type object<eZ\Publish\API\Re...ory\Values\ValueObject> is not a sub-type of object<eZ\Publish\API\Re...ser\PolicyCreateStruct>. It seems like you assume a child class of the class eZ\Publish\API\Repository\Values\ValueObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
434
            );
435
        } catch (LimitationValidationException $e) {
436
            throw new BadRequestException($e->getMessage());
437
        }
438
439
        $policies = $role->getPolicies();
440
441
        $policyToReturn = $policies[0];
442
        for ($i = 1, $count = count($policies); $i < $count; ++$i) {
443
            if ($policies[$i]->id > $policyToReturn->id) {
444
                $policyToReturn = $policies[$i];
445
            }
446
        }
447
448
        return new Values\CreatedPolicy(
449
            array(
450
                'policy' => $policyToReturn,
451
            )
452
        );
453
    }
454
455
    /**
456
     * Updates a policy.
457
     *
458
     * @param $roleId
459
     * @param $policyId
460
     *
461
     * @throws \eZ\Publish\Core\REST\Common\Exceptions\NotFoundException
462
     *
463
     * @return \eZ\Publish\API\Repository\Values\User\Policy
464
     */
465 View Code Duplication
    public function updatePolicy($roleId, $policyId, Request $request)
466
    {
467
        $updateStruct = $this->inputDispatcher->parse(
468
            new Message(
469
                array('Content-Type' => $request->headers->get('Content-Type')),
470
                $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, eZ\Publish\Core\REST\Common\Message::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

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

An additional type check may prevent trouble.

Loading history...
471
            )
472
        );
473
474
        $role = $this->roleService->loadRole($roleId);
475
        foreach ($role->getPolicies() as $policy) {
476
            if ($policy->id == $policyId) {
477
                try {
478
                    return $this->roleService->updatePolicy(
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...Service::updatePolicy() has been deprecated with message: since 6.0, use {@link updatePolicyByRoleDraft()} instead.

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...
479
                        $policy,
480
                        $updateStruct
0 ignored issues
show
Compatibility introduced by
$updateStruct of type object<eZ\Publish\API\Re...ory\Values\ValueObject> is not a sub-type of object<eZ\Publish\API\Re...ser\PolicyUpdateStruct>. It seems like you assume a child class of the class eZ\Publish\API\Repository\Values\ValueObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
481
                    );
482
                } catch (LimitationValidationException $e) {
483
                    throw new BadRequestException($e->getMessage());
484
                }
485
            }
486
        }
487
488
        throw new Exceptions\NotFoundException("Policy not found: '{$request->getPathInfo()}'.");
489
    }
490
491
    /**
492
     * Updates a policy.
493
     *
494
     * @param $roleId
495
     * @param $policyId
496
     *
497
     * @throws \eZ\Publish\Core\REST\Common\Exceptions\NotFoundException
498
     *
499
     * @return \eZ\Publish\API\Repository\Values\User\Policy
500
     */
501 View Code Duplication
    public function updatePolicyByRoleDraft($roleId, $policyId, Request $request)
502
    {
503
        $updateStruct = $this->inputDispatcher->parse(
504
            new Message(
505
                array('Content-Type' => $request->headers->get('Content-Type')),
506
                $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, eZ\Publish\Core\REST\Common\Message::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

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

An additional type check may prevent trouble.

Loading history...
507
            )
508
        );
509
510
        $role = $this->roleService->loadRoleDraft($roleId);
511
        foreach ($role->getPolicies() as $policy) {
512
            if ($policy->id == $policyId) {
513
                try {
514
                    return $this->roleService->updatePolicy(
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...Service::updatePolicy() has been deprecated with message: since 6.0, use {@link updatePolicyByRoleDraft()} instead.

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...
515
                        $policy,
516
                        $updateStruct
0 ignored issues
show
Compatibility introduced by
$updateStruct of type object<eZ\Publish\API\Re...ory\Values\ValueObject> is not a sub-type of object<eZ\Publish\API\Re...ser\PolicyUpdateStruct>. It seems like you assume a child class of the class eZ\Publish\API\Repository\Values\ValueObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
517
                    );
518
                } catch (LimitationValidationException $e) {
519
                    throw new BadRequestException($e->getMessage());
520
                }
521
            }
522
        }
523
524
        throw new Exceptions\NotFoundException("Policy not found: '{$request->getPathInfo()}'.");
525
    }
526
527
    /**
528
     * Delete a policy from role.
529
     *
530
     * @param $roleId
531
     * @param $policyId
532
     *
533
     * @throws \eZ\Publish\Core\REST\Common\Exceptions\NotFoundException
534
     *
535
     * @return \eZ\Publish\Core\REST\Server\Values\NoContent
536
     */
537 View Code Duplication
    public function deletePolicy($roleId, $policyId, Request $request)
538
    {
539
        $role = $this->roleService->loadRole($roleId);
540
541
        $policy = null;
542
        foreach ($role->getPolicies() as $rolePolicy) {
543
            if ($rolePolicy->id == $policyId) {
544
                $policy = $rolePolicy;
545
                break;
546
            }
547
        }
548
549
        if ($policy !== null) {
550
            $this->roleService->deletePolicy($policy);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...Service::deletePolicy() has been deprecated with message: since 6.0, use {@link removePolicyByRoleDraft()} instead.

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...
551
552
            return new Values\NoContent();
553
        }
554
555
        throw new Exceptions\NotFoundException("Policy not found: '{$request->getPathInfo()}'.");
556
    }
557
558
    /**
559
     * Remove a policy from a role draft.
560
     *
561
     * @param $roleId
562
     * @param $policyId
563
     *
564
     * @throws \eZ\Publish\Core\REST\Common\Exceptions\NotFoundException
565
     *
566
     * @return \eZ\Publish\Core\REST\Server\Values\NoContent
567
     */
568 View Code Duplication
    public function removePolicyByRoleDraft($roleId, $policyId, Request $request)
569
    {
570
        $roleDraft = $this->roleService->loadRoleDraft($roleId);
571
572
        $policy = null;
573
        foreach ($roleDraft->getPolicies() as $rolePolicy) {
574
            if ($rolePolicy->id == $policyId) {
575
                $policy = $rolePolicy;
576
                break;
577
            }
578
        }
579
580
        if ($policy !== null) {
581
            $this->roleService->removePolicyByRoleDraft($roleDraft, $policy);
0 ignored issues
show
Compatibility introduced by
$policy of type object<eZ\Publish\API\Re...ory\Values\User\Policy> is not a sub-type of object<eZ\Publish\API\Re...alues\User\PolicyDraft>. It seems like you assume a child class of the class eZ\Publish\API\Repository\Values\User\Policy to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
582
583
            return new Values\NoContent();
584
        }
585
586
        throw new Exceptions\NotFoundException("Policy not found: '{$request->getPathInfo()}'.");
587
    }
588
589
    /**
590
     * Assigns role to user.
591
     *
592
     * @param $userId
593
     *
594
     * @return \eZ\Publish\Core\REST\Server\Values\RoleAssignmentList
595
     */
596
    public function assignRoleToUser($userId, Request $request)
597
    {
598
        $roleAssignment = $this->inputDispatcher->parse(
599
            new Message(
600
                array('Content-Type' => $request->headers->get('Content-Type')),
601
                $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, eZ\Publish\Core\REST\Common\Message::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

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

An additional type check may prevent trouble.

Loading history...
602
            )
603
        );
604
605
        $user = $this->userService->loadUser($userId);
606
        $role = $this->roleService->loadRole($roleAssignment->roleId);
0 ignored issues
show
Documentation introduced by
The property roleId does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
607
608
        try {
609
            $this->roleService->assignRoleToUser($role, $user, $roleAssignment->limitation);
0 ignored issues
show
Documentation introduced by
The property limitation does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
610
        } catch (LimitationValidationException $e) {
611
            throw new BadRequestException($e->getMessage());
612
        }
613
614
        $roleAssignments = $this->roleService->getRoleAssignmentsForUser($user);
615
616
        return new Values\RoleAssignmentList($roleAssignments, $user->id);
617
    }
618
619
    /**
620
     * Assigns role to user group.
621
     *
622
     * @param $groupPath
623
     *
624
     * @return \eZ\Publish\Core\REST\Server\Values\RoleAssignmentList
625
     */
626
    public function assignRoleToUserGroup($groupPath, Request $request)
627
    {
628
        $roleAssignment = $this->inputDispatcher->parse(
629
            new Message(
630
                array('Content-Type' => $request->headers->get('Content-Type')),
631
                $request->getContent()
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, eZ\Publish\Core\REST\Common\Message::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

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

An additional type check may prevent trouble.

Loading history...
632
            )
633
        );
634
635
        $groupLocationParts = explode('/', $groupPath);
636
        $groupLocation = $this->locationService->loadLocation(array_pop($groupLocationParts));
637
        $userGroup = $this->userService->loadUserGroup($groupLocation->contentId);
638
639
        $role = $this->roleService->loadRole($roleAssignment->roleId);
0 ignored issues
show
Documentation introduced by
The property roleId does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
640
641
        try {
642
            $this->roleService->assignRoleToUserGroup($role, $userGroup, $roleAssignment->limitation);
0 ignored issues
show
Documentation introduced by
The property limitation does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
643
        } catch (LimitationValidationException $e) {
644
            throw new BadRequestException($e->getMessage());
645
        }
646
647
        $roleAssignments = $this->roleService->getRoleAssignmentsForUserGroup($userGroup);
648
649
        return new Values\RoleAssignmentList($roleAssignments, $groupPath, true);
650
    }
651
652
    /**
653
     * Un-assigns role from user.
654
     *
655
     * @param $userId
656
     * @param $roleId
657
     *
658
     * @return \eZ\Publish\Core\REST\Server\Values\RoleAssignmentList
659
     */
660
    public function unassignRoleFromUser($userId, $roleId)
661
    {
662
        $user = $this->userService->loadUser($userId);
663
        $role = $this->roleService->loadRole($roleId);
664
665
        $this->roleService->unassignRoleFromUser($role, $user);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...:unassignRoleFromUser() has been deprecated with message: since 6.0, use {@see removeRoleAssignment} instead.

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

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

Loading history...
666
667
        $roleAssignments = $this->roleService->getRoleAssignmentsForUser($user);
668
669
        return new Values\RoleAssignmentList($roleAssignments, $user->id);
670
    }
671
672
    /**
673
     * Un-assigns role from user group.
674
     *
675
     * @param $groupPath
676
     * @param $roleId
677
     *
678
     * @return \eZ\Publish\Core\REST\Server\Values\RoleAssignmentList
679
     */
680
    public function unassignRoleFromUserGroup($groupPath, $roleId)
681
    {
682
        $groupLocationParts = explode('/', $groupPath);
683
        $groupLocation = $this->locationService->loadLocation(array_pop($groupLocationParts));
684
        $userGroup = $this->userService->loadUserGroup($groupLocation->contentId);
685
686
        $role = $this->roleService->loadRole($roleId);
687
        $this->roleService->unassignRoleFromUserGroup($role, $userGroup);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...signRoleFromUserGroup() has been deprecated with message: since 6.0, use {@see removeRoleAssignment} instead.

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...
688
689
        $roleAssignments = $this->roleService->getRoleAssignmentsForUserGroup($userGroup);
690
691
        return new Values\RoleAssignmentList($roleAssignments, $groupPath, true);
692
    }
693
694
    /**
695
     * Loads role assignments for user.
696
     *
697
     * @param $userId
698
     *
699
     * @return \eZ\Publish\Core\REST\Server\Values\RoleAssignmentList
700
     */
701
    public function loadRoleAssignmentsForUser($userId)
702
    {
703
        $user = $this->userService->loadUser($userId);
704
705
        $roleAssignments = $this->roleService->getRoleAssignmentsForUser($user);
706
707
        return new Values\RoleAssignmentList($roleAssignments, $user->id);
708
    }
709
710
    /**
711
     * Loads role assignments for user group.
712
     *
713
     * @param $groupPath
714
     *
715
     * @return \eZ\Publish\Core\REST\Server\Values\RoleAssignmentList
716
     */
717
    public function loadRoleAssignmentsForUserGroup($groupPath)
718
    {
719
        $groupLocationParts = explode('/', $groupPath);
720
        $groupLocation = $this->locationService->loadLocation(array_pop($groupLocationParts));
721
        $userGroup = $this->userService->loadUserGroup($groupLocation->contentId);
722
723
        $roleAssignments = $this->roleService->getRoleAssignmentsForUserGroup($userGroup);
724
725
        return new Values\RoleAssignmentList($roleAssignments, $groupPath, true);
726
    }
727
728
    /**
729
     * Returns a role assignment to the given user.
730
     *
731
     * @param $userId
732
     * @param $roleId
733
     *
734
     * @throws \eZ\Publish\Core\REST\Common\Exceptions\NotFoundException
735
     *
736
     * @return \eZ\Publish\Core\REST\Server\Values\RestUserRoleAssignment
737
     */
738
    public function loadRoleAssignmentForUser($userId, $roleId, Request $request)
739
    {
740
        $user = $this->userService->loadUser($userId);
741
        $roleAssignments = $this->roleService->getRoleAssignmentsForUser($user);
742
743
        foreach ($roleAssignments as $roleAssignment) {
744
            if ($roleAssignment->getRole()->id == $roleId) {
745
                return new Values\RestUserRoleAssignment($roleAssignment, $userId);
0 ignored issues
show
Bug introduced by
It seems like $roleAssignment defined by $roleAssignment on line 743 can also be of type object<eZ\Publish\API\Re...serGroupRoleAssignment>; however, eZ\Publish\Core\REST\Ser...signment::__construct() does only seem to accept object<eZ\Publish\API\Re...ser\UserRoleAssignment>, 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...
746
            }
747
        }
748
749
        throw new Exceptions\NotFoundException("Role assignment not found: '{$request->getPathInfo()}'.");
750
    }
751
752
    /**
753
     * Returns a role assignment to the given user group.
754
     *
755
     * @param $groupPath
756
     * @param $roleId
757
     *
758
     * @throws \eZ\Publish\Core\REST\Common\Exceptions\NotFoundException
759
     *
760
     * @return \eZ\Publish\Core\REST\Server\Values\RestUserGroupRoleAssignment
761
     */
762
    public function loadRoleAssignmentForUserGroup($groupPath, $roleId, Request $request)
763
    {
764
        $groupLocationParts = explode('/', $groupPath);
765
        $groupLocation = $this->locationService->loadLocation(array_pop($groupLocationParts));
766
        $userGroup = $this->userService->loadUserGroup($groupLocation->contentId);
767
768
        $roleAssignments = $this->roleService->getRoleAssignmentsForUserGroup($userGroup);
769
        foreach ($roleAssignments as $roleAssignment) {
770
            if ($roleAssignment->getRole()->id == $roleId) {
771
                return new Values\RestUserGroupRoleAssignment($roleAssignment, $groupPath);
772
            }
773
        }
774
775
        throw new Exceptions\NotFoundException("Role assignment not found: '{$request->getPathInfo()}'.");
776
    }
777
778
    /**
779
     * Search all policies which are applied to a given user.
780
     *
781
     * @return \eZ\Publish\Core\REST\Server\Values\PolicyList
782
     */
783
    public function listPoliciesForUser(Request $request)
784
    {
785
        return new Values\PolicyList(
786
            $this->roleService->loadPoliciesByUserId(
787
                $request->query->get('userId')
788
            ),
789
            $request->getPathInfo()
790
        );
791
    }
792
793
    /**
794
     * Maps a RoleCreateStruct to a RoleUpdateStruct.
795
     *
796
     * Needed since both structs are encoded into the same media type on input.
797
     *
798
     * @param \eZ\Publish\API\Repository\Values\User\RoleCreateStruct $createStruct
799
     *
800
     * @return \eZ\Publish\API\Repository\Values\User\RoleUpdateStruct
801
     */
802
    protected function mapToUpdateStruct(RoleCreateStruct $createStruct)
803
    {
804
        return new RoleUpdateStruct(
805
            array(
806
                'identifier' => $createStruct->identifier,
807
            )
808
        );
809
    }
810
}
811