Completed
Push — ezp-24830_REST_for_role_drafts ( ac0f60...ff5f81 )
by
unknown
27:12
created

Role::createRoleDraft()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 18
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 18
rs 8.8571
cc 5
eloc 13
nc 5
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\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
     * Loads the policies for the role.
305
     *
306
     * @param $roleId
307
     *
308
     * @return \eZ\Publish\Core\REST\Server\Values\PolicyList
309
     */
310
    public function loadPolicies($roleId, Request $request)
311
    {
312
        $loadedRole = $this->roleService->loadRole($roleId);
313
314
        return new Values\PolicyList($loadedRole->getPolicies(), $request->getPathInfo());
315
    }
316
317
    /**
318
     * Deletes all policies from a role.
319
     *
320
     * @param $roleId
321
     *
322
     * @return \eZ\Publish\Core\REST\Server\Values\NoContent
323
     */
324
    public function deletePolicies($roleId)
325
    {
326
        $loadedRole = $this->roleService->loadRole($roleId);
327
328
        foreach ($loadedRole->getPolicies() as $policy) {
329
            $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...
330
        }
331
332
        return new Values\NoContent();
333
    }
334
335
    /**
336
     * Loads a policy.
337
     *
338
     * @param $roleId
339
     * @param $policyId
340
     *
341
     * @throws \eZ\Publish\Core\REST\Common\Exceptions\NotFoundException
342
     *
343
     * @return \eZ\Publish\API\Repository\Values\User\Policy
344
     */
345
    public function loadPolicy($roleId, $policyId, Request $request)
346
    {
347
        $loadedRole = $this->roleService->loadRole($roleId);
348
        foreach ($loadedRole->getPolicies() as $policy) {
349
            if ($policy->id == $policyId) {
350
                return $policy;
351
            }
352
        }
353
354
        throw new Exceptions\NotFoundException("Policy not found: '{$request->getPathInfo()}'.");
355
    }
356
357
    /**
358
     * Adds a policy to role.
359
     *
360
     * @param $roleId
361
     *
362
     * @return \eZ\Publish\Core\REST\Server\Values\CreatedPolicy
363
     */
364
    public function addPolicy($roleId, Request $request)
365
    {
366
        $createStruct = $this->inputDispatcher->parse(
367
            new Message(
368
                array('Content-Type' => $request->headers->get('Content-Type')),
369
                $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...
370
            )
371
        );
372
373
        try {
374
            $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...
375
                $this->roleService->loadRole($roleId),
376
                $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...
377
            );
378
        } catch (LimitationValidationException $e) {
379
            throw new BadRequestException($e->getMessage());
380
        }
381
382
        $policies = $role->getPolicies();
383
384
        $policyToReturn = $policies[0];
385
        for ($i = 1, $count = count($policies); $i < $count; ++$i) {
386
            if ($policies[$i]->id > $policyToReturn->id) {
387
                $policyToReturn = $policies[$i];
388
            }
389
        }
390
391
        return new Values\CreatedPolicy(
392
            array(
393
                'policy' => $policyToReturn,
394
            )
395
        );
396
    }
397
398
    /**
399
     * Updates a policy.
400
     *
401
     * @param $roleId
402
     * @param $policyId
403
     *
404
     * @throws \eZ\Publish\Core\REST\Common\Exceptions\NotFoundException
405
     *
406
     * @return \eZ\Publish\API\Repository\Values\User\Policy
407
     */
408
    public function updatePolicy($roleId, $policyId, Request $request)
409
    {
410
        $updateStruct = $this->inputDispatcher->parse(
411
            new Message(
412
                array('Content-Type' => $request->headers->get('Content-Type')),
413
                $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...
414
            )
415
        );
416
417
        $role = $this->roleService->loadRole($roleId);
418
        foreach ($role->getPolicies() as $policy) {
419
            if ($policy->id == $policyId) {
420
                try {
421
                    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...
422
                        $policy,
423
                        $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...
424
                    );
425
                } catch (LimitationValidationException $e) {
426
                    throw new BadRequestException($e->getMessage());
427
                }
428
            }
429
        }
430
431
        throw new Exceptions\NotFoundException("Policy not found: '{$request->getPathInfo()}'.");
432
    }
433
434
    /**
435
     * Delete a policy from role.
436
     *
437
     * @param $roleId
438
     * @param $policyId
439
     *
440
     * @throws \eZ\Publish\Core\REST\Common\Exceptions\NotFoundException
441
     *
442
     * @return \eZ\Publish\Core\REST\Server\Values\NoContent
443
     */
444 View Code Duplication
    public function deletePolicy($roleId, $policyId, Request $request)
445
    {
446
        $role = $this->roleService->loadRole($roleId);
447
448
        $policy = null;
449
        foreach ($role->getPolicies() as $rolePolicy) {
450
            if ($rolePolicy->id == $policyId) {
451
                $policy = $rolePolicy;
452
                break;
453
            }
454
        }
455
456
        if ($policy !== null) {
457
            $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...
458
459
            return new Values\NoContent();
460
        }
461
462
        throw new Exceptions\NotFoundException("Policy not found: '{$request->getPathInfo()}'.");
463
    }
464
465
    /**
466
     * Assigns role to user.
467
     *
468
     * @param $userId
469
     *
470
     * @return \eZ\Publish\Core\REST\Server\Values\RoleAssignmentList
471
     */
472
    public function assignRoleToUser($userId, Request $request)
473
    {
474
        $roleAssignment = $this->inputDispatcher->parse(
475
            new Message(
476
                array('Content-Type' => $request->headers->get('Content-Type')),
477
                $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...
478
            )
479
        );
480
481
        $user = $this->userService->loadUser($userId);
482
        $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...
483
484
        try {
485
            $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...
486
        } catch (LimitationValidationException $e) {
487
            throw new BadRequestException($e->getMessage());
488
        }
489
490
        $roleAssignments = $this->roleService->getRoleAssignmentsForUser($user);
491
492
        return new Values\RoleAssignmentList($roleAssignments, $user->id);
493
    }
494
495
    /**
496
     * Assigns role to user group.
497
     *
498
     * @param $groupPath
499
     *
500
     * @return \eZ\Publish\Core\REST\Server\Values\RoleAssignmentList
501
     */
502
    public function assignRoleToUserGroup($groupPath, Request $request)
503
    {
504
        $roleAssignment = $this->inputDispatcher->parse(
505
            new Message(
506
                array('Content-Type' => $request->headers->get('Content-Type')),
507
                $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...
508
            )
509
        );
510
511
        $groupLocationParts = explode('/', $groupPath);
512
        $groupLocation = $this->locationService->loadLocation(array_pop($groupLocationParts));
513
        $userGroup = $this->userService->loadUserGroup($groupLocation->contentId);
514
515
        $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...
516
517
        try {
518
            $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...
519
        } catch (LimitationValidationException $e) {
520
            throw new BadRequestException($e->getMessage());
521
        }
522
523
        $roleAssignments = $this->roleService->getRoleAssignmentsForUserGroup($userGroup);
524
525
        return new Values\RoleAssignmentList($roleAssignments, $groupPath, true);
526
    }
527
528
    /**
529
     * Un-assigns role from user.
530
     *
531
     * @param $userId
532
     * @param $roleId
533
     *
534
     * @return \eZ\Publish\Core\REST\Server\Values\RoleAssignmentList
535
     */
536
    public function unassignRoleFromUser($userId, $roleId)
537
    {
538
        $user = $this->userService->loadUser($userId);
539
        $role = $this->roleService->loadRole($roleId);
540
541
        $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...
542
543
        $roleAssignments = $this->roleService->getRoleAssignmentsForUser($user);
544
545
        return new Values\RoleAssignmentList($roleAssignments, $user->id);
546
    }
547
548
    /**
549
     * Un-assigns role from user group.
550
     *
551
     * @param $groupPath
552
     * @param $roleId
553
     *
554
     * @return \eZ\Publish\Core\REST\Server\Values\RoleAssignmentList
555
     */
556
    public function unassignRoleFromUserGroup($groupPath, $roleId)
557
    {
558
        $groupLocationParts = explode('/', $groupPath);
559
        $groupLocation = $this->locationService->loadLocation(array_pop($groupLocationParts));
560
        $userGroup = $this->userService->loadUserGroup($groupLocation->contentId);
561
562
        $role = $this->roleService->loadRole($roleId);
563
        $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...
564
565
        $roleAssignments = $this->roleService->getRoleAssignmentsForUserGroup($userGroup);
566
567
        return new Values\RoleAssignmentList($roleAssignments, $groupPath, true);
568
    }
569
570
    /**
571
     * Loads role assignments for user.
572
     *
573
     * @param $userId
574
     *
575
     * @return \eZ\Publish\Core\REST\Server\Values\RoleAssignmentList
576
     */
577
    public function loadRoleAssignmentsForUser($userId)
578
    {
579
        $user = $this->userService->loadUser($userId);
580
581
        $roleAssignments = $this->roleService->getRoleAssignmentsForUser($user);
582
583
        return new Values\RoleAssignmentList($roleAssignments, $user->id);
584
    }
585
586
    /**
587
     * Loads role assignments for user group.
588
     *
589
     * @param $groupPath
590
     *
591
     * @return \eZ\Publish\Core\REST\Server\Values\RoleAssignmentList
592
     */
593
    public function loadRoleAssignmentsForUserGroup($groupPath)
594
    {
595
        $groupLocationParts = explode('/', $groupPath);
596
        $groupLocation = $this->locationService->loadLocation(array_pop($groupLocationParts));
597
        $userGroup = $this->userService->loadUserGroup($groupLocation->contentId);
598
599
        $roleAssignments = $this->roleService->getRoleAssignmentsForUserGroup($userGroup);
600
601
        return new Values\RoleAssignmentList($roleAssignments, $groupPath, true);
602
    }
603
604
    /**
605
     * Returns a role assignment to the given user.
606
     *
607
     * @param $userId
608
     * @param $roleId
609
     *
610
     * @throws \eZ\Publish\Core\REST\Common\Exceptions\NotFoundException
611
     *
612
     * @return \eZ\Publish\Core\REST\Server\Values\RestUserRoleAssignment
613
     */
614
    public function loadRoleAssignmentForUser($userId, $roleId, Request $request)
615
    {
616
        $user = $this->userService->loadUser($userId);
617
        $roleAssignments = $this->roleService->getRoleAssignmentsForUser($user);
618
619
        foreach ($roleAssignments as $roleAssignment) {
620
            if ($roleAssignment->getRole()->id == $roleId) {
621
                return new Values\RestUserRoleAssignment($roleAssignment, $userId);
0 ignored issues
show
Bug introduced by
It seems like $roleAssignment defined by $roleAssignment on line 619 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...
622
            }
623
        }
624
625
        throw new Exceptions\NotFoundException("Role assignment not found: '{$request->getPathInfo()}'.");
626
    }
627
628
    /**
629
     * Returns a role assignment to the given user group.
630
     *
631
     * @param $groupPath
632
     * @param $roleId
633
     *
634
     * @throws \eZ\Publish\Core\REST\Common\Exceptions\NotFoundException
635
     *
636
     * @return \eZ\Publish\Core\REST\Server\Values\RestUserGroupRoleAssignment
637
     */
638
    public function loadRoleAssignmentForUserGroup($groupPath, $roleId, Request $request)
639
    {
640
        $groupLocationParts = explode('/', $groupPath);
641
        $groupLocation = $this->locationService->loadLocation(array_pop($groupLocationParts));
642
        $userGroup = $this->userService->loadUserGroup($groupLocation->contentId);
643
644
        $roleAssignments = $this->roleService->getRoleAssignmentsForUserGroup($userGroup);
645
        foreach ($roleAssignments as $roleAssignment) {
646
            if ($roleAssignment->getRole()->id == $roleId) {
647
                return new Values\RestUserGroupRoleAssignment($roleAssignment, $groupPath);
648
            }
649
        }
650
651
        throw new Exceptions\NotFoundException("Role assignment not found: '{$request->getPathInfo()}'.");
652
    }
653
654
    /**
655
     * Search all policies which are applied to a given user.
656
     *
657
     * @return \eZ\Publish\Core\REST\Server\Values\PolicyList
658
     */
659
    public function listPoliciesForUser(Request $request)
660
    {
661
        return new Values\PolicyList(
662
            $this->roleService->loadPoliciesByUserId(
663
                $request->query->get('userId')
664
            ),
665
            $request->getPathInfo()
666
        );
667
    }
668
669
    /**
670
     * Maps a RoleCreateStruct to a RoleUpdateStruct.
671
     *
672
     * Needed since both structs are encoded into the same media type on input.
673
     *
674
     * @param \eZ\Publish\API\Repository\Values\User\RoleCreateStruct $createStruct
675
     *
676
     * @return \eZ\Publish\API\Repository\Values\User\RoleUpdateStruct
677
     */
678
    protected function mapToUpdateStruct(RoleCreateStruct $createStruct)
679
    {
680
        return new RoleUpdateStruct(
681
            array(
682
                'identifier' => $createStruct->identifier,
683
            )
684
        );
685
    }
686
}
687