Completed
Push — ezp24624-query_controller_take... ( f346e1...647162 )
by
unknown
23:39
created

RoleService   F

Complexity

Total Complexity 165

Size/Duplication

Total Lines 1461
Duplicated Lines 28.41 %

Coupling/Cohesion

Components 1
Dependencies 33

Importance

Changes 0
Metric Value
dl 415
loc 1461
rs 0.5217
c 0
b 0
f 0
wmc 165
lcom 1
cbo 33

40 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 40 1
C createRole() 0 40 7
B createRoleDraft() 27 27 4
A loadRoleDraft() 10 10 2
A loadRoleDraftByRoleId() 10 10 2
C updateRoleDraft() 3 50 9
C addPolicyByRoleDraft() 47 47 10
A removePolicyByRoleDraft() 14 14 3
C updatePolicyByRoleDraft() 0 48 7
A deleteRoleDraft() 0 13 2
B publishRoleDraft() 33 33 4
D updateRole() 3 45 9
C addPolicy() 47 47 10
A removePolicy() 14 14 3
A deletePolicy() 0 8 2
A internalDeletePolicy() 0 11 2
B updatePolicy() 0 43 6
A loadRole() 10 10 2
A loadRoleByIdentifier() 14 14 3
A loadRoles() 15 15 3
A loadPoliciesByUserId() 0 15 3
B assignRoleToUserGroup() 36 36 5
B unassignRoleFromUserGroup() 31 31 6
B assignRoleToUser() 36 36 5
B unassignRoleFromUser() 31 31 6
B loadRoleAssignment() 0 35 4
B getRoleAssignments() 0 36 5
B getRoleAssignmentsForUser() 0 28 5
A getRoleAssignmentsForUserGroup() 0 19 3
A newRoleCreateStruct() 0 9 1
A newPolicyCreateStruct() 0 10 1
A newPolicyUpdateStruct() 0 8 1
A newRoleUpdateStruct() 0 4 1
A getLimitationType() 0 4 1
A getLimitationTypesByModuleFunction() 0 21 4
A validateRoleCreateStruct() 0 17 3
C validatePolicy() 0 25 7
C checkAssignmentAndFilterLimitationValues() 0 42 7
A deleteRole() 17 17 3
A removeRoleAssignment() 17 17 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like RoleService often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use RoleService, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * File containing the eZ\Publish\Core\Repository\RoleService 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\Repository;
12
13
use eZ\Publish\API\Repository\Exceptions\NotFoundException as APINotFoundException;
14
use eZ\Publish\API\Repository\Repository as RepositoryInterface;
15
use eZ\Publish\API\Repository\RoleService as RoleServiceInterface;
16
use eZ\Publish\API\Repository\Values\User\Limitation;
17
use eZ\Publish\API\Repository\Values\User\Limitation\RoleLimitation;
18
use eZ\Publish\API\Repository\Values\User\Policy as APIPolicy;
19
use eZ\Publish\API\Repository\Values\User\PolicyCreateStruct as APIPolicyCreateStruct;
20
use eZ\Publish\API\Repository\Values\User\PolicyDraft;
21
use eZ\Publish\API\Repository\Values\User\PolicyUpdateStruct as APIPolicyUpdateStruct;
22
use eZ\Publish\API\Repository\Values\User\Role as APIRole;
23
use eZ\Publish\API\Repository\Values\User\RoleAssignment;
24
use eZ\Publish\API\Repository\Values\User\RoleCreateStruct as APIRoleCreateStruct;
25
use eZ\Publish\API\Repository\Values\User\RoleDraft as APIRoleDraft;
26
use eZ\Publish\API\Repository\Values\User\RoleUpdateStruct;
27
use eZ\Publish\API\Repository\Values\User\User;
28
use eZ\Publish\API\Repository\Values\User\UserGroup;
29
use eZ\Publish\Core\Base\Exceptions\BadStateException;
30
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;
31
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentValue;
32
use eZ\Publish\Core\Base\Exceptions\LimitationValidationException;
33
use eZ\Publish\Core\Base\Exceptions\NotFoundException;
34
use eZ\Publish\Core\Base\Exceptions\NotFound\LimitationNotFoundException;
35
use eZ\Publish\Core\Base\Exceptions\UnauthorizedException;
36
use eZ\Publish\Core\Repository\Values\User\Policy;
37
use eZ\Publish\Core\Repository\Values\User\PolicyCreateStruct;
38
use eZ\Publish\Core\Repository\Values\User\PolicyUpdateStruct;
39
use eZ\Publish\Core\Repository\Values\User\Role;
40
use eZ\Publish\Core\Repository\Values\User\RoleCreateStruct;
41
use eZ\Publish\Core\Repository\Values\User\RoleDraft;
42
use eZ\Publish\SPI\Persistence\User\Handler;
43
use eZ\Publish\SPI\Persistence\User\Role as SPIRole;
44
use eZ\Publish\SPI\Persistence\User\RoleUpdateStruct as SPIRoleUpdateStruct;
45
use Exception;
46
47
/**
48
 * This service provides methods for managing Roles and Policies.
49
 */
50
class RoleService implements RoleServiceInterface
51
{
52
    /**
53
     * @var \eZ\Publish\API\Repository\Repository
54
     */
55
    protected $repository;
56
57
    /**
58
     * @var \eZ\Publish\SPI\Persistence\User\Handler
59
     */
60
    protected $userHandler;
61
62
    /**
63
     * @var \eZ\Publish\Core\Repository\Helper\LimitationService
64
     */
65
    protected $limitationService;
66
67
    /**
68
     * @var \eZ\Publish\Core\Repository\Helper\RoleDomainMapper
69
     */
70
    protected $roleDomainMapper;
71
72
    /**
73
     * @var array
74
     */
75
    protected $settings;
76
77
    /**
78
     * Setups service with reference to repository object that created it & corresponding handler.
79
     *
80
     * @param \eZ\Publish\API\Repository\Repository $repository
81
     * @param \eZ\Publish\SPI\Persistence\User\Handler $userHandler
82
     * @param \eZ\Publish\Core\Repository\Helper\LimitationService $limitationService
83
     * @param \eZ\Publish\Core\Repository\Helper\RoleDomainMapper $roleDomainMapper
84
     * @param array $settings
85
     */
86
    public function __construct(
87
        RepositoryInterface $repository,
88
        Handler $userHandler,
89
        Helper\LimitationService $limitationService,
90
        Helper\RoleDomainMapper $roleDomainMapper,
91
        array $settings = array()
92
    ) {
93
        $this->repository = $repository;
94
        $this->userHandler = $userHandler;
95
        $this->limitationService = $limitationService;
96
        $this->roleDomainMapper = $roleDomainMapper;
97
        // Union makes sure default settings are ignored if provided in argument
98
        $this->settings = $settings + array(
99
            'policyMap' => array(
100
                'content' => array(
101
                    'read' => array('Class' => true, 'Section' => true, 'Owner' => true, 'Group' => true, 'Node' => true, 'Subtree' => true, 'State' => true),
102
                    'diff' => array('Class' => true, 'Section' => true, 'Owner' => true, 'Node' => true, 'Subtree' => true),
103
                    'view_embed' => array('Class' => true, 'Section' => true, 'Owner' => true, 'Node' => true, 'Subtree' => true),
104
                    'create' => array('Class' => true, 'Section' => true, 'ParentOwner' => true, 'ParentGroup' => true, 'ParentClass' => true, 'ParentDepth' => true, 'Node' => true, 'Subtree' => true, 'Language' => true),
105
                    'edit' => array('Class' => true, 'Section' => true, 'Owner' => true, 'Group' => true, 'Node' => true, 'Subtree' => true, 'Language' => true, 'State' => true),
106
                    'manage_locations' => array('Class' => true, 'Section' => true, 'Owner' => true, 'Subtree' => true),
107
                    'hide' => array('Class' => true, 'Section' => true, 'Owner' => true, 'Group' => true, 'Node' => true, 'Subtree' => true, 'Language' => true),
108
                    'translate' => array('Class' => true, 'Section' => true, 'Owner' => true, 'Node' => true, 'Subtree' => true, 'Language' => true),
109
                    'remove' => array('Class' => true, 'Section' => true, 'Owner' => true, 'Node' => true, 'Subtree' => true, 'State' => true),
110
                    'versionread' => array('Class' => true, 'Section' => true, 'Owner' => true, 'Status' => true, 'Node' => true, 'Subtree' => true),
111
                    'versionremove' => array('Class' => true, 'Section' => true, 'Owner' => true, 'Status' => true, 'Node' => true, 'Subtree' => true),
112
                    'pdf' => array('Class' => true, 'Section' => true, 'Owner' => true, 'Node' => true, 'Subtree' => true),
113
                ),
114
                'section' => array(
115
                    'assign' => array('Class' => true, 'Section' => true, 'Owner' => true, 'NewSection' => true),
116
                ),
117
                'state' => array(
118
                    'assign' => array('Class' => true, 'Section' => true, 'Owner' => true, 'Group' => true, 'Node' => true, 'Subtree' => true, 'State' => true, 'NewState' => true),
119
                ),
120
                'user' => array(
121
                    'login' => array('SiteAccess' => true),
122
                ),
123
            ),
124
        );
125
    }
126
127
    /**
128
     * Creates a new RoleDraft.
129
     *
130
     * @since 6.0
131
     *
132
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to create a RoleDraft
133
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
134
     *         if the name of the role already exists or if limitation of the same type
135
     *         is repeated in the policy create struct or if limitation is not allowed on module/function
136
     * @throws \eZ\Publish\API\Repository\Exceptions\LimitationValidationException if a policy limitation in the $roleCreateStruct is not valid
137
     *
138
     * @param \eZ\Publish\API\Repository\Values\User\RoleCreateStruct $roleCreateStruct
139
     *
140
     * @return \eZ\Publish\API\Repository\Values\User\RoleDraft
141
     */
142
    public function createRole(APIRoleCreateStruct $roleCreateStruct)
143
    {
144
        if (!is_string($roleCreateStruct->identifier) || empty($roleCreateStruct->identifier)) {
145
            throw new InvalidArgumentValue('identifier', $roleCreateStruct->identifier, 'RoleCreateStruct');
146
        }
147
148
        if ($this->repository->hasAccess('role', 'create') !== true) {
149
            throw new UnauthorizedException('role', 'create');
150
        }
151
152
        try {
153
            $existingRole = $this->loadRoleByIdentifier($roleCreateStruct->identifier);
154
155
            throw new InvalidArgumentException(
156
                '$roleCreateStruct',
157
                "Role '{$existingRole->id}' with the specified identifier '{$roleCreateStruct->identifier}' " .
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...
158
                'already exists'
159
            );
160
        } catch (APINotFoundException $e) {
161
            // Do nothing
162
        }
163
164
        $limitationValidationErrors = $this->validateRoleCreateStruct($roleCreateStruct);
165
        if (!empty($limitationValidationErrors)) {
166
            throw new LimitationValidationException($limitationValidationErrors);
0 ignored issues
show
Documentation introduced by
$limitationValidationErrors is of type array<integer,array<inte...ype\ValidationError>>>>, but the function expects a array<integer,object<eZ\...dType\ValidationError>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
167
        }
168
169
        $spiRoleCreateStruct = $this->roleDomainMapper->buildPersistenceRoleCreateStruct($roleCreateStruct);
170
171
        $this->repository->beginTransaction();
172
        try {
173
            $spiRole = $this->userHandler->createRole($spiRoleCreateStruct);
174
            $this->repository->commit();
175
        } catch (Exception $e) {
176
            $this->repository->rollback();
177
            throw $e;
178
        }
179
180
        return $this->roleDomainMapper->buildDomainRoleDraftObject($spiRole);
181
    }
182
183
    /**
184
     * Creates a new RoleDraft for an existing Role.
185
     *
186
     * @since 6.0
187
     *
188
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to create a RoleDraft
189
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if the Role already has a RoleDraft that will need to be removed first
190
     *
191
     * @param \eZ\Publish\API\Repository\Values\User\Role $role
192
     *
193
     * @return \eZ\Publish\API\Repository\Values\User\RoleDraft
194
     */
195 View Code Duplication
    public function createRoleDraft(APIRole $role)
196
    {
197
        if ($this->repository->hasAccess('role', 'create') !== true) {
198
            throw new UnauthorizedException('role', 'create');
199
        }
200
201
        try {
202
            $this->userHandler->loadRole($role->id, Role::STATUS_DRAFT);
203
204
            // Throw exception, so platformui et al can do conflict management. Follow-up: EZP-24719
205
            throw new InvalidArgumentException(
206
                '$role',
207
                "Cannot create a draft for role '{$role->identifier}' because another draft exists"
208
            );
209
        } catch (APINotFoundException $e) {
210
            $this->repository->beginTransaction();
211
            try {
212
                $spiRole = $this->userHandler->createRoleDraft($role->id);
213
                $this->repository->commit();
214
            } catch (Exception $e) {
215
                $this->repository->rollback();
216
                throw $e;
217
            }
218
        }
219
220
        return $this->roleDomainMapper->buildDomainRoleDraftObject($spiRole);
221
    }
222
223
    /**
224
     * Loads a RoleDraft for the given id.
225
     *
226
     * @since 6.0
227
     *
228
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to read this RoleDraft
229
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if a RoleDraft with the given id was not found
230
     *
231
     * @param mixed $id
232
     *
233
     * @return \eZ\Publish\API\Repository\Values\User\RoleDraft
234
     */
235 View Code Duplication
    public function loadRoleDraft($id)
236
    {
237
        if ($this->repository->hasAccess('role', 'read') !== true) {
238
            throw new UnauthorizedException('role', 'read');
239
        }
240
241
        $spiRole = $this->userHandler->loadRole($id, Role::STATUS_DRAFT);
242
243
        return $this->roleDomainMapper->buildDomainRoleDraftObject($spiRole);
244
    }
245
246
    /**
247
     * Loads a RoleDraft by the ID of the role it was created from.
248
     *
249
     * @param mixed $roleId ID of the role the draft was created from.
250
     *
251
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to read this role
252
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if a RoleDraft with the given id was not found
253
     *
254
     * @return \eZ\Publish\API\Repository\Values\User\RoleDraft
255
     */
256 View Code Duplication
    public function loadRoleDraftByRoleId($roleId)
257
    {
258
        if ($this->repository->hasAccess('role', 'read') !== true) {
259
            throw new UnauthorizedException('role', 'read');
260
        }
261
262
        $spiRole = $this->userHandler->loadRoleDraftByRoleId($roleId);
263
264
        return $this->roleDomainMapper->buildDomainRoleDraftObject($spiRole);
265
    }
266
267
    /**
268
     * Updates the properties of a RoleDraft.
269
     *
270
     * @since 6.0
271
     *
272
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to update a RoleDraft
273
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if the identifier of the RoleDraft already exists
274
     *
275
     * @param \eZ\Publish\API\Repository\Values\User\RoleDraft $roleDraft
276
     * @param \eZ\Publish\API\Repository\Values\User\RoleUpdateStruct $roleUpdateStruct
277
     *
278
     * @return \eZ\Publish\API\Repository\Values\User\RoleDraft
279
     */
280
    public function updateRoleDraft(APIRoleDraft $roleDraft, RoleUpdateStruct $roleUpdateStruct)
281
    {
282 View Code Duplication
        if ($roleUpdateStruct->identifier !== null && !is_string($roleUpdateStruct->identifier)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
283
            throw new InvalidArgumentValue('identifier', $roleUpdateStruct->identifier, 'RoleUpdateStruct');
284
        }
285
286
        $loadedRoleDraft = $this->loadRoleDraft($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...
287
288
        if ($this->repository->hasAccess('role', 'update') !== true) {
289
            throw new UnauthorizedException('role', 'update');
290
        }
291
292
        if ($roleUpdateStruct->identifier !== null) {
293
            try {
294
                /* Throw exception if:
295
                 * - A published role with the same identifier exists, AND
296
                 * - The ID of the published role does not match the original ID of the draft
297
                */
298
                $existingSPIRole = $this->userHandler->loadRoleByIdentifier($roleUpdateStruct->identifier);
299
                $SPIRoleDraft = $this->userHandler->loadRole($loadedRoleDraft->id, Role::STATUS_DRAFT);
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...
300
                if ($existingSPIRole->id != $SPIRoleDraft->originalId) {
301
                    throw new InvalidArgumentException(
302
                        '$roleUpdateStruct',
303
                        "Role '{$existingSPIRole->id}' with the specified identifier '{$roleUpdateStruct->identifier}' " .
304
                        'already exists'
305
                    );
306
                }
307
            } catch (APINotFoundException $e) {
308
                // Do nothing
309
            }
310
        }
311
312
        $this->repository->beginTransaction();
313
        try {
314
            $this->userHandler->updateRole(
315
                new SPIRoleUpdateStruct(
316
                    array(
317
                        'id' => $loadedRoleDraft->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...
318
                        'identifier' => $roleUpdateStruct->identifier ?: $loadedRoleDraft->identifier,
0 ignored issues
show
Documentation introduced by
The property $identifier 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...
319
                    )
320
                )
321
            );
322
            $this->repository->commit();
323
        } catch (Exception $e) {
324
            $this->repository->rollback();
325
            throw $e;
326
        }
327
328
        return $this->loadRoleDraft($loadedRoleDraft->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...
329
    }
330
331
    /**
332
     * Adds a new policy to the RoleDraft.
333
     *
334
     * @since 6.0
335
     *
336
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to add  a policy
337
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if limitation of the same type is repeated in policy create
338
     *                                                                        struct or if limitation is not allowed on module/function
339
     * @throws \eZ\Publish\API\Repository\Exceptions\LimitationValidationException if a limitation in the $policyCreateStruct is not valid
340
     *
341
     * @param \eZ\Publish\API\Repository\Values\User\RoleDraft $roleDraft
342
     * @param \eZ\Publish\API\Repository\Values\User\PolicyCreateStruct $policyCreateStruct
343
     *
344
     * @return \eZ\Publish\API\Repository\Values\User\RoleDraft
345
     */
346 View Code Duplication
    public function addPolicyByRoleDraft(APIRoleDraft $roleDraft, APIPolicyCreateStruct $policyCreateStruct)
347
    {
348
        if (!is_string($policyCreateStruct->module) || empty($policyCreateStruct->module)) {
349
            throw new InvalidArgumentValue('module', $policyCreateStruct->module, 'PolicyCreateStruct');
350
        }
351
352
        if (!is_string($policyCreateStruct->function) || empty($policyCreateStruct->function)) {
353
            throw new InvalidArgumentValue('function', $policyCreateStruct->function, 'PolicyCreateStruct');
354
        }
355
356
        if ($policyCreateStruct->module === '*' && $policyCreateStruct->function !== '*') {
357
            throw new InvalidArgumentValue('module', $policyCreateStruct->module, 'PolicyCreateStruct');
358
        }
359
360
        if ($this->repository->hasAccess('role', 'update') !== true) {
361
            throw new UnauthorizedException('role', 'update');
362
        }
363
364
        $loadedRoleDraft = $this->loadRoleDraft($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...
365
366
        $limitations = $policyCreateStruct->getLimitations();
367
        $limitationValidationErrors = $this->validatePolicy(
368
            $policyCreateStruct->module,
369
            $policyCreateStruct->function,
370
            $limitations
371
        );
372
        if (!empty($limitationValidationErrors)) {
373
            throw new LimitationValidationException($limitationValidationErrors);
0 ignored issues
show
Documentation introduced by
$limitationValidationErrors is of type array<integer,array<inte...Type\ValidationError>>>, but the function expects a array<integer,object<eZ\...dType\ValidationError>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
374
        }
375
376
        $spiPolicy = $this->roleDomainMapper->buildPersistencePolicyObject(
377
            $policyCreateStruct->module,
378
            $policyCreateStruct->function,
379
            $limitations
380
        );
381
382
        $this->repository->beginTransaction();
383
        try {
384
            $this->userHandler->addPolicyByRoleDraft($loadedRoleDraft->id, $spiPolicy);
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...
385
            $this->repository->commit();
386
        } catch (Exception $e) {
387
            $this->repository->rollback();
388
            throw $e;
389
        }
390
391
        return $this->loadRoleDraft($loadedRoleDraft->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...
392
    }
393
394
    /**
395
     * Removes a policy from a RoleDraft.
396
     *
397
     * @since 6.0
398
     *
399
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to remove a policy
400
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if policy does not belong to the given RoleDraft
401
     *
402
     * @param \eZ\Publish\API\Repository\Values\User\RoleDraft $roleDraft
403
     * @param PolicyDraft $policyDraft the policy to remove from the RoleDraft
404
     *
405
     * @return APIRoleDraft if the authenticated user is not allowed to remove a policy
406
     */
407 View Code Duplication
    public function removePolicyByRoleDraft(APIRoleDraft $roleDraft, PolicyDraft $policyDraft)
408
    {
409
        if ($this->repository->hasAccess('role', 'update') !== true) {
410
            throw new UnauthorizedException('role', 'update');
411
        }
412
413
        if ($policyDraft->roleId != $roleDraft->id) {
0 ignored issues
show
Documentation introduced by
The property $roleId is declared protected in eZ\Publish\API\Repository\Values\User\Policy. 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...
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...
414
            throw new InvalidArgumentException('$policy', 'Policy does not belong to the given role');
415
        }
416
417
        $this->internalDeletePolicy($policyDraft);
418
419
        return $this->loadRoleDraft($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...
420
    }
421
422
    /**
423
     * Updates the limitations of a policy. The module and function cannot be changed and
424
     * the limitations are replaced by the ones in $roleUpdateStruct.
425
     *
426
     * @since 6.0
427
     *
428
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to update a policy
429
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if limitation of the same type is repeated in policy update
430
     *                                                                        struct or if limitation is not allowed on module/function
431
     * @throws \eZ\Publish\API\Repository\Exceptions\LimitationValidationException if a limitation in the $policyUpdateStruct is not valid
432
     *
433
     * @param \eZ\Publish\API\Repository\Values\User\RoleDraft $roleDraft
434
     * @param \eZ\Publish\API\Repository\Values\User\PolicyDraft $policy
435
     * @param \eZ\Publish\API\Repository\Values\User\PolicyUpdateStruct $policyUpdateStruct
436
     *
437
     * @return \eZ\Publish\API\Repository\Values\User\PolicyDraft
438
     */
439
    public function updatePolicyByRoleDraft(APIRoleDraft $roleDraft, PolicyDraft $policy, APIPolicyUpdateStruct $policyUpdateStruct)
440
    {
441
        if (!is_string($policy->module)) {
0 ignored issues
show
Documentation introduced by
The property $module is declared protected in eZ\Publish\API\Repository\Values\User\Policy. 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...
442
            throw new InvalidArgumentValue('module', $policy->module, 'Policy');
0 ignored issues
show
Documentation introduced by
The property $module is declared protected in eZ\Publish\API\Repository\Values\User\Policy. 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...
443
        }
444
445
        if (!is_string($policy->function)) {
0 ignored issues
show
Documentation introduced by
The property $function is declared protected in eZ\Publish\API\Repository\Values\User\Policy. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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

<?php

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

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

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

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

}

Since the property has write access only, you can use the @property-write annotation instead.

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

See also the PhpDoc documentation for @property.

Loading history...
446
            throw new InvalidArgumentValue('function', $policy->function, 'Policy');
0 ignored issues
show
Documentation introduced by
The property $function is declared protected in eZ\Publish\API\Repository\Values\User\Policy. 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...
447
        }
448
449
        if ($this->repository->hasAccess('role', 'update') !== true) {
450
            throw new UnauthorizedException('role', 'update');
451
        }
452
453
        if ($policy->roleId !== $roleDraft->id) {
0 ignored issues
show
Documentation introduced by
The property $roleId is declared protected in eZ\Publish\API\Repository\Values\User\Policy. 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...
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...
454
            throw new InvalidArgumentException('$policy', "doesn't belong to provided role draft");
455
        }
456
457
        $limitations = $policyUpdateStruct->getLimitations();
458
        $limitationValidationErrors = $this->validatePolicy(
459
            $policy->module,
0 ignored issues
show
Documentation introduced by
The property $module is declared protected in eZ\Publish\API\Repository\Values\User\Policy. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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

<?php

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

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

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

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

}

Since the property has write access only, you can use the @property-write annotation instead.

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

See also the PhpDoc documentation for @property.

Loading history...
460
            $policy->function,
0 ignored issues
show
Documentation introduced by
The property $function is declared protected in eZ\Publish\API\Repository\Values\User\Policy. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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

<?php

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

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

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

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

}

Since the property has write access only, you can use the @property-write annotation instead.

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

See also the PhpDoc documentation for @property.

Loading history...
461
            $limitations
462
        );
463
        if (!empty($limitationValidationErrors)) {
464
            throw new LimitationValidationException($limitationValidationErrors);
0 ignored issues
show
Documentation introduced by
$limitationValidationErrors is of type array<integer,array<inte...Type\ValidationError>>>, but the function expects a array<integer,object<eZ\...dType\ValidationError>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
465
        }
466
467
        $spiPolicy = $this->roleDomainMapper->buildPersistencePolicyObject(
468
            $policy->module,
0 ignored issues
show
Documentation introduced by
The property $module is declared protected in eZ\Publish\API\Repository\Values\User\Policy. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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

<?php

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

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

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

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

}

Since the property has write access only, you can use the @property-write annotation instead.

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

See also the PhpDoc documentation for @property.

Loading history...
469
            $policy->function,
0 ignored issues
show
Documentation introduced by
The property $function is declared protected in eZ\Publish\API\Repository\Values\User\Policy. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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

<?php

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

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

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

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

}

Since the property has write access only, you can use the @property-write annotation instead.

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

See also the PhpDoc documentation for @property.

Loading history...
470
            $limitations
471
        );
472
        $spiPolicy->id = $policy->id;
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\User\Policy. 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...
473
        $spiPolicy->roleId = $policy->roleId;
0 ignored issues
show
Documentation introduced by
The property $roleId is declared protected in eZ\Publish\API\Repository\Values\User\Policy. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

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

<?php

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

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

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

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

}

Since the property has write access only, you can use the @property-write annotation instead.

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

See also the PhpDoc documentation for @property.

Loading history...
474
        $spiPolicy->originalId = $policy->originalId;
475
476
        $this->repository->beginTransaction();
477
        try {
478
            $this->userHandler->updatePolicy($spiPolicy);
479
            $this->repository->commit();
480
        } catch (Exception $e) {
481
            $this->repository->rollback();
482
            throw $e;
483
        }
484
485
        return $this->roleDomainMapper->buildDomainPolicyObject($spiPolicy);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->roleDomainMapper-...licyObject($spiPolicy); of type eZ\Publish\Core\Reposito...tory\Values\User\Policy adds the type eZ\Publish\Core\Repository\Values\User\Policy to the return on line 485 which is incompatible with the return type declared by the interface eZ\Publish\API\Repositor...updatePolicyByRoleDraft of type eZ\Publish\API\Repository\Values\User\PolicyDraft.
Loading history...
486
    }
487
488
    /**
489
     * Deletes the given RoleDraft.
490
     *
491
     * @since 6.0
492
     *
493
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to delete this RoleDraft
494
     *
495
     * @param \eZ\Publish\API\Repository\Values\User\RoleDraft $roleDraft
496
     */
497
    public function deleteRoleDraft(APIRoleDraft $roleDraft)
498
    {
499
        $loadedRoleDraft = $this->loadRoleDraft($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...
500
501
        $this->repository->beginTransaction();
502
        try {
503
            $this->userHandler->deleteRole($loadedRoleDraft->id, Role::STATUS_DRAFT);
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...
504
            $this->repository->commit();
505
        } catch (Exception $e) {
506
            $this->repository->rollback();
507
            throw $e;
508
        }
509
    }
510
511
    /**
512
     * Publishes a given RoleDraft.
513
     *
514
     * @since 6.0
515
     *
516
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to publish this RoleDraft
517
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException if the role draft cannot be loaded
518
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if the role draft has no policies
519
     *
520
     * @param \eZ\Publish\API\Repository\Values\User\RoleDraft $roleDraft
521
     */
522 View Code Duplication
    public function publishRoleDraft(APIRoleDraft $roleDraft)
523
    {
524
        if ($this->repository->hasAccess('role', 'update') !== true) {
525
            throw new UnauthorizedException('role', 'update');
526
        }
527
528
        try {
529
            $loadedRoleDraft = $this->loadRoleDraft($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...
530
        } catch (APINotFoundException $e) {
531
            throw new BadStateException(
532
                '$roleDraft',
533
                'The role does not have a draft.',
534
                $e
535
            );
536
        }
537
538
        // TODO: Uncomment when role policy editing is done, see EZP-24711 & EZP-24713
539
        /*if (count($loadedRoleDraft->getPolicies()) === 0) {
540
            throw new InvalidArgumentException(
541
                "\$roleDraft",
542
                'The role draft should have at least one policy.'
543
            );
544
        }*/
545
546
        $this->repository->beginTransaction();
547
        try {
548
            $this->userHandler->publishRoleDraft($loadedRoleDraft->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...
549
            $this->repository->commit();
550
        } catch (Exception $e) {
551
            $this->repository->rollback();
552
            throw $e;
553
        }
554
    }
555
556
    /**
557
     * Updates the name of the role.
558
     *
559
     * @deprecated since 6.0, use {@see updateRoleDraft}
560
     *
561
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to update a role
562
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if the name of the role already exists
563
     *
564
     * @param \eZ\Publish\API\Repository\Values\User\Role $role
565
     * @param \eZ\Publish\API\Repository\Values\User\RoleUpdateStruct $roleUpdateStruct
566
     *
567
     * @return \eZ\Publish\API\Repository\Values\User\Role
568
     */
569
    public function updateRole(APIRole $role, RoleUpdateStruct $roleUpdateStruct)
570
    {
571 View Code Duplication
        if ($roleUpdateStruct->identifier !== null && !is_string($roleUpdateStruct->identifier)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
572
            throw new InvalidArgumentValue('identifier', $roleUpdateStruct->identifier, 'RoleUpdateStruct');
573
        }
574
575
        $loadedRole = $this->loadRole($role->id);
576
577
        if ($this->repository->hasAccess('role', 'update') !== true) {
578
            throw new UnauthorizedException('role', 'update');
579
        }
580
581
        if ($roleUpdateStruct->identifier !== null) {
582
            try {
583
                $existingRole = $this->loadRoleByIdentifier($roleUpdateStruct->identifier);
584
585
                if ($existingRole->id != $loadedRole->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...
586
                    throw new InvalidArgumentException(
587
                        '$roleUpdateStruct',
588
                        'Role with provided identifier already exists'
589
                    );
590
                }
591
            } catch (APINotFoundException $e) {
592
                // Do nothing
593
            }
594
        }
595
596
        $this->repository->beginTransaction();
597
        try {
598
            $this->userHandler->updateRole(
599
                new SPIRoleUpdateStruct(
600
                    array(
601
                        'id' => $loadedRole->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...
602
                        'identifier' => $roleUpdateStruct->identifier ?: $loadedRole->identifier,
0 ignored issues
show
Documentation introduced by
The property $identifier 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...
603
                    )
604
                )
605
            );
606
            $this->repository->commit();
607
        } catch (Exception $e) {
608
            $this->repository->rollback();
609
            throw $e;
610
        }
611
612
        return $this->loadRole($loadedRole->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...
613
    }
614
615
    /**
616
     * Adds a new policy to the role.
617
     *
618
     * @deprecated since 6.0, use {@see addPolicyByRoleDraft}
619
     *
620
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to add  a policy
621
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if limitation of the same type is repeated in policy create
622
     *                                                                        struct or if limitation is not allowed on module/function
623
     * @throws \eZ\Publish\API\Repository\Exceptions\LimitationValidationException if a limitation in the $policyCreateStruct is not valid
624
     *
625
     * @param \eZ\Publish\API\Repository\Values\User\Role $role
626
     * @param \eZ\Publish\API\Repository\Values\User\PolicyCreateStruct $policyCreateStruct
627
     *
628
     * @return \eZ\Publish\API\Repository\Values\User\Role
629
     */
630 View Code Duplication
    public function addPolicy(APIRole $role, APIPolicyCreateStruct $policyCreateStruct)
631
    {
632
        if (!is_string($policyCreateStruct->module) || empty($policyCreateStruct->module)) {
633
            throw new InvalidArgumentValue('module', $policyCreateStruct->module, 'PolicyCreateStruct');
634
        }
635
636
        if (!is_string($policyCreateStruct->function) || empty($policyCreateStruct->function)) {
637
            throw new InvalidArgumentValue('function', $policyCreateStruct->function, 'PolicyCreateStruct');
638
        }
639
640
        if ($policyCreateStruct->module === '*' && $policyCreateStruct->function !== '*') {
641
            throw new InvalidArgumentValue('module', $policyCreateStruct->module, 'PolicyCreateStruct');
642
        }
643
644
        if ($this->repository->hasAccess('role', 'update') !== true) {
645
            throw new UnauthorizedException('role', 'update');
646
        }
647
648
        $loadedRole = $this->loadRole($role->id);
649
650
        $limitations = $policyCreateStruct->getLimitations();
651
        $limitationValidationErrors = $this->validatePolicy(
652
            $policyCreateStruct->module,
653
            $policyCreateStruct->function,
654
            $limitations
655
        );
656
        if (!empty($limitationValidationErrors)) {
657
            throw new LimitationValidationException($limitationValidationErrors);
0 ignored issues
show
Documentation introduced by
$limitationValidationErrors is of type array<integer,array<inte...Type\ValidationError>>>, but the function expects a array<integer,object<eZ\...dType\ValidationError>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
658
        }
659
660
        $spiPolicy = $this->roleDomainMapper->buildPersistencePolicyObject(
661
            $policyCreateStruct->module,
662
            $policyCreateStruct->function,
663
            $limitations
664
        );
665
666
        $this->repository->beginTransaction();
667
        try {
668
            $this->userHandler->addPolicy($loadedRole->id, $spiPolicy);
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...
669
            $this->repository->commit();
670
        } catch (Exception $e) {
671
            $this->repository->rollback();
672
            throw $e;
673
        }
674
675
        return $this->loadRole($loadedRole->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...
676
    }
677
678
    /**
679
     * Removes a policy from the role.
680
     *
681
     * @deprecated since 5.3, use {@link removePolicyByRoleDraft()} instead.
682
     *
683
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to remove a policy
684
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if policy does not belong to the given role
685
     *
686
     * @param \eZ\Publish\API\Repository\Values\User\Role $role
687
     * @param \eZ\Publish\API\Repository\Values\User\Policy $policy the policy to remove from the role
688
     *
689
     * @return \eZ\Publish\API\Repository\Values\User\Role the updated role
690
     */
691 View Code Duplication
    public function removePolicy(APIRole $role, APIPolicy $policy)
692
    {
693
        if ($this->repository->hasAccess('role', 'update') !== true) {
694
            throw new UnauthorizedException('role', 'update');
695
        }
696
697
        if ($policy->roleId != $role->id) {
698
            throw new InvalidArgumentException('$policy', 'Policy does not belong to the given role');
699
        }
700
701
        $this->internalDeletePolicy($policy);
702
703
        return $this->loadRole($role->id);
704
    }
705
706
    /**
707
     * Deletes a policy.
708
     *
709
     * @deprecated since 6.0, use {@link removePolicyByRoleDraft()} instead.
710
     *
711
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to remove a policy
712
     *
713
     * @param \eZ\Publish\API\Repository\Values\User\Policy $policy the policy to delete
714
     */
715
    public function deletePolicy(APIPolicy $policy)
716
    {
717
        if ($this->repository->hasAccess('role', 'update') !== true) {
718
            throw new UnauthorizedException('role', 'update');
719
        }
720
721
        $this->internalDeletePolicy($policy);
722
    }
723
724
    /**
725
     * Deletes a policy.
726
     *
727
     * Used by {@link removePolicy()} and {@link deletePolicy()}
728
     *
729
     * @param APIPolicy $policy
730
     *
731
     * @throws \Exception
732
     */
733
    protected function internalDeletePolicy(APIPolicy $policy)
734
    {
735
        $this->repository->beginTransaction();
736
        try {
737
            $this->userHandler->deletePolicy($policy->id);
738
            $this->repository->commit();
739
        } catch (Exception $e) {
740
            $this->repository->rollback();
741
            throw $e;
742
        }
743
    }
744
745
    /**
746
     * Updates the limitations of a policy. The module and function cannot be changed and
747
     * the limitations are replaced by the ones in $roleUpdateStruct.
748
     *
749
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to update a policy
750
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if limitation of the same type is repeated in policy update
751
     *                                                                        struct or if limitation is not allowed on module/function
752
     * @throws \eZ\Publish\API\Repository\Exceptions\LimitationValidationException if a limitation in the $policyUpdateStruct is not valid
753
     *
754
     * @param \eZ\Publish\API\Repository\Values\User\PolicyUpdateStruct $policyUpdateStruct
755
     * @param \eZ\Publish\API\Repository\Values\User\Policy $policy
756
     *
757
     * @return \eZ\Publish\API\Repository\Values\User\Policy
758
     */
759
    public function updatePolicy(APIPolicy $policy, APIPolicyUpdateStruct $policyUpdateStruct)
760
    {
761
        if (!is_string($policy->module)) {
762
            throw new InvalidArgumentValue('module', $policy->module, 'Policy');
763
        }
764
765
        if (!is_string($policy->function)) {
766
            throw new InvalidArgumentValue('function', $policy->function, 'Policy');
767
        }
768
769
        if ($this->repository->hasAccess('role', 'update') !== true) {
770
            throw new UnauthorizedException('role', 'update');
771
        }
772
773
        $limitations = $policyUpdateStruct->getLimitations();
774
        $limitationValidationErrors = $this->validatePolicy(
775
            $policy->module,
776
            $policy->function,
777
            $limitations
778
        );
779
        if (!empty($limitationValidationErrors)) {
780
            throw new LimitationValidationException($limitationValidationErrors);
0 ignored issues
show
Documentation introduced by
$limitationValidationErrors is of type array<integer,array<inte...Type\ValidationError>>>, but the function expects a array<integer,object<eZ\...dType\ValidationError>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
781
        }
782
783
        $spiPolicy = $this->roleDomainMapper->buildPersistencePolicyObject(
784
            $policy->module,
785
            $policy->function,
786
            $limitations
787
        );
788
        $spiPolicy->id = $policy->id;
789
        $spiPolicy->roleId = $policy->roleId;
790
791
        $this->repository->beginTransaction();
792
        try {
793
            $this->userHandler->updatePolicy($spiPolicy);
794
            $this->repository->commit();
795
        } catch (Exception $e) {
796
            $this->repository->rollback();
797
            throw $e;
798
        }
799
800
        return $this->roleDomainMapper->buildDomainPolicyObject($spiPolicy);
801
    }
802
803
    /**
804
     * Loads a role for the given id.
805
     *
806
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to read this role
807
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if a role with the given id was not found
808
     *
809
     * @param mixed $id
810
     *
811
     * @return \eZ\Publish\API\Repository\Values\User\Role
812
     */
813 View Code Duplication
    public function loadRole($id)
814
    {
815
        if ($this->repository->hasAccess('role', 'read') !== true) {
816
            throw new UnauthorizedException('role', 'read');
817
        }
818
819
        $spiRole = $this->userHandler->loadRole($id);
820
821
        return $this->roleDomainMapper->buildDomainRoleObject($spiRole);
822
    }
823
824
    /**
825
     * Loads a role for the given identifier.
826
     *
827
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to read this role
828
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if a role with the given name was not found
829
     *
830
     * @param string $identifier
831
     *
832
     * @return \eZ\Publish\API\Repository\Values\User\Role
833
     */
834 View Code Duplication
    public function loadRoleByIdentifier($identifier)
835
    {
836
        if (!is_string($identifier)) {
837
            throw new InvalidArgumentValue('identifier', $identifier);
838
        }
839
840
        if ($this->repository->hasAccess('role', 'read') !== true) {
841
            throw new UnauthorizedException('role', 'read');
842
        }
843
844
        $spiRole = $this->userHandler->loadRoleByIdentifier($identifier);
845
846
        return $this->roleDomainMapper->buildDomainRoleObject($spiRole);
847
    }
848
849
    /**
850
     * Loads all roles.
851
     *
852
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to read the roles
853
     *
854
     * @return \eZ\Publish\API\Repository\Values\User\Role[]
855
     */
856 View Code Duplication
    public function loadRoles()
857
    {
858
        if ($this->repository->hasAccess('role', 'read') !== true) {
859
            throw new UnauthorizedException('role', 'read');
860
        }
861
862
        $spiRoles = $this->userHandler->loadRoles();
863
864
        $roles = array();
865
        foreach ($spiRoles as $spiRole) {
866
            $roles[] = $this->roleDomainMapper->buildDomainRoleObject($spiRole);
867
        }
868
869
        return $roles;
870
    }
871
872
    /**
873
     * Deletes the given role.
874
     *
875
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to delete this role
876
     *
877
     * @param \eZ\Publish\API\Repository\Values\User\Role $role
878
     */
879 View Code Duplication
    public function deleteRole(APIRole $role)
880
    {
881
        if ($this->repository->hasAccess('role', 'delete') !== true) {
882
            throw new UnauthorizedException('role', 'delete');
883
        }
884
885
        $loadedRole = $this->loadRole($role->id);
886
887
        $this->repository->beginTransaction();
888
        try {
889
            $this->userHandler->deleteRole($loadedRole->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...
890
            $this->repository->commit();
891
        } catch (Exception $e) {
892
            $this->repository->rollback();
893
            throw $e;
894
        }
895
    }
896
897
    /**
898
     * Loads all policies from roles which are assigned to a user or to user groups to which the user belongs.
899
     *
900
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if a user with the given id was not found
901
     *
902
     * @param mixed $userId
903
     *
904
     * @return \eZ\Publish\API\Repository\Values\User\Policy[]
905
     */
906
    public function loadPoliciesByUserId($userId)
907
    {
908
        $spiPolicies = $this->userHandler->loadPoliciesByUserId($userId);
909
910
        $policies = array();
911
        foreach ($spiPolicies as $spiPolicy) {
912
            $policies[] = $this->roleDomainMapper->buildDomainPolicyObject($spiPolicy);
913
        }
914
915
        if (empty($policies)) {
916
            $this->userHandler->load($userId);
917
        }// For NotFoundException in case userId is invalid
918
919
        return $policies;
920
    }
921
922
    /**
923
     * Assigns a role to the given user group.
924
     *
925
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to assign a role
926
     * @throws \eZ\Publish\API\Repository\Exceptions\LimitationValidationException if $roleLimitation is not valid
927
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If assignment already exists
928
     *
929
     * @param \eZ\Publish\API\Repository\Values\User\Role $role
930
     * @param \eZ\Publish\API\Repository\Values\User\UserGroup $userGroup
931
     * @param \eZ\Publish\API\Repository\Values\User\Limitation\RoleLimitation $roleLimitation an optional role limitation (which is either a subtree limitation or section limitation)
932
     */
933 View Code Duplication
    public function assignRoleToUserGroup(APIRole $role, UserGroup $userGroup, RoleLimitation $roleLimitation = null)
934
    {
935
        if ($this->repository->canUser('role', 'assign', $userGroup, $role) !== true) {
936
            throw new UnauthorizedException('role', 'assign');
937
        }
938
939
        if ($roleLimitation === null) {
940
            $limitation = null;
941
        } else {
942
            $limitationValidationErrors = $this->limitationService->validateLimitation($roleLimitation);
943
            if (!empty($limitationValidationErrors)) {
944
                throw new LimitationValidationException($limitationValidationErrors);
945
            }
946
947
            $limitation = array($roleLimitation->getIdentifier() => $roleLimitation->limitationValues);
948
        }
949
950
        // Check if objects exists
951
        $spiRole = $this->userHandler->loadRole($role->id);
952
        $loadedUserGroup = $this->repository->getUserService()->loadUserGroup($userGroup->id);
953
954
        $limitation = $this->checkAssignmentAndFilterLimitationValues($loadedUserGroup->id, $spiRole, $limitation);
955
956
        $this->repository->beginTransaction();
957
        try {
958
            $this->userHandler->assignRole(
959
                $loadedUserGroup->id,
960
                $spiRole->id,
961
                $limitation
962
            );
963
            $this->repository->commit();
964
        } catch (Exception $e) {
965
            $this->repository->rollback();
966
            throw $e;
967
        }
968
    }
969
970
    /**
971
     * removes a role from the given user group.
972
     *
973
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to remove a role
974
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException  If the role is not assigned to the given user group
975
     *
976
     * @param \eZ\Publish\API\Repository\Values\User\Role $role
977
     * @param \eZ\Publish\API\Repository\Values\User\UserGroup $userGroup
978
     */
979 View Code Duplication
    public function unassignRoleFromUserGroup(APIRole $role, UserGroup $userGroup)
980
    {
981
        if ($this->repository->canUser('role', 'assign', $userGroup, $role) !== true) {
982
            throw new UnauthorizedException('role', 'assign');
983
        }
984
985
        $spiRoleAssignments = $this->userHandler->loadRoleAssignmentsByGroupId($userGroup->id);
986
        $isAssigned = false;
987
        foreach ($spiRoleAssignments as $spiRoleAssignment) {
988
            if ($spiRoleAssignment->roleId === $role->id) {
989
                $isAssigned = true;
990
                break;
991
            }
992
        }
993
994
        if (!$isAssigned) {
995
            throw new InvalidArgumentException(
996
                '$userGroup',
997
                'Role is not assigned to the given UserGroup'
998
            );
999
        }
1000
1001
        $this->repository->beginTransaction();
1002
        try {
1003
            $this->userHandler->unassignRole($userGroup->id, $role->id);
1004
            $this->repository->commit();
1005
        } catch (Exception $e) {
1006
            $this->repository->rollback();
1007
            throw $e;
1008
        }
1009
    }
1010
1011
    /**
1012
     * Assigns a role to the given user.
1013
     *
1014
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to assign a role
1015
     * @throws \eZ\Publish\API\Repository\Exceptions\LimitationValidationException if $roleLimitation is not valid
1016
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If assignment already exists
1017
     *
1018
     * @param \eZ\Publish\API\Repository\Values\User\Role $role
1019
     * @param \eZ\Publish\API\Repository\Values\User\User $user
1020
     * @param \eZ\Publish\API\Repository\Values\User\Limitation\RoleLimitation $roleLimitation an optional role limitation (which is either a subtree limitation or section limitation)
1021
     */
1022 View Code Duplication
    public function assignRoleToUser(APIRole $role, User $user, RoleLimitation $roleLimitation = null)
1023
    {
1024
        if ($this->repository->canUser('role', 'assign', $user, $role) !== true) {
1025
            throw new UnauthorizedException('role', 'assign');
1026
        }
1027
1028
        if ($roleLimitation === null) {
1029
            $limitation = null;
1030
        } else {
1031
            $limitationValidationErrors = $this->limitationService->validateLimitation($roleLimitation);
1032
            if (!empty($limitationValidationErrors)) {
1033
                throw new LimitationValidationException($limitationValidationErrors);
1034
            }
1035
1036
            $limitation = array($roleLimitation->getIdentifier() => $roleLimitation->limitationValues);
1037
        }
1038
1039
        // Check if objects exists
1040
        $spiRole = $this->userHandler->loadRole($role->id);
1041
        $spiUser = $this->userHandler->load($user->id);
1042
1043
        $limitation = $this->checkAssignmentAndFilterLimitationValues($spiUser->id, $spiRole, $limitation);
1044
1045
        $this->repository->beginTransaction();
1046
        try {
1047
            $this->userHandler->assignRole(
1048
                $spiUser->id,
1049
                $spiRole->id,
1050
                $limitation
1051
            );
1052
            $this->repository->commit();
1053
        } catch (Exception $e) {
1054
            $this->repository->rollback();
1055
            throw $e;
1056
        }
1057
    }
1058
1059
    /**
1060
     * removes a role from the given user.
1061
     *
1062
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to remove a role
1063
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If the role is not assigned to the user
1064
     *
1065
     * @param \eZ\Publish\API\Repository\Values\User\Role $role
1066
     * @param \eZ\Publish\API\Repository\Values\User\User $user
1067
     */
1068 View Code Duplication
    public function unassignRoleFromUser(APIRole $role, User $user)
1069
    {
1070
        if ($this->repository->canUser('role', 'assign', $user, $role) !== true) {
1071
            throw new UnauthorizedException('role', 'assign');
1072
        }
1073
1074
        $spiRoleAssignments = $this->userHandler->loadRoleAssignmentsByGroupId($user->id);
1075
        $isAssigned = false;
1076
        foreach ($spiRoleAssignments as $spiRoleAssignment) {
1077
            if ($spiRoleAssignment->roleId === $role->id) {
1078
                $isAssigned = true;
1079
                break;
1080
            }
1081
        }
1082
1083
        if (!$isAssigned) {
1084
            throw new InvalidArgumentException(
1085
                '$user',
1086
                'Role is not assigned to the given User'
1087
            );
1088
        }
1089
1090
        $this->repository->beginTransaction();
1091
        try {
1092
            $this->userHandler->unassignRole($user->id, $role->id);
1093
            $this->repository->commit();
1094
        } catch (Exception $e) {
1095
            $this->repository->rollback();
1096
            throw $e;
1097
        }
1098
    }
1099
1100
    /**
1101
     * Removes the given role assignment.
1102
     *
1103
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to remove a role assignment
1104
     *
1105
     * @param \eZ\Publish\API\Repository\Values\User\RoleAssignment $roleAssignment
1106
     */
1107 View Code Duplication
    public function removeRoleAssignment(RoleAssignment $roleAssignment)
1108
    {
1109
        if ($this->repository->canUser('role', 'assign', $roleAssignment) !== true) {
1110
            throw new UnauthorizedException('role', 'assign');
1111
        }
1112
1113
        $spiRoleAssignment = $this->userHandler->loadRoleAssignment($roleAssignment->id);
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repositor...ues\User\RoleAssignment. 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...
1114
1115
        $this->repository->beginTransaction();
1116
        try {
1117
            $this->userHandler->removeRoleAssignment($spiRoleAssignment->id);
1118
            $this->repository->commit();
1119
        } catch (Exception $e) {
1120
            $this->repository->rollback();
1121
            throw $e;
1122
        }
1123
    }
1124
1125
    /**
1126
     * Loads a role assignment for the given id.
1127
     *
1128
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to read this role
1129
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If the role assignment was not found
1130
     *
1131
     * @param mixed $roleAssignmentId
1132
     *
1133
     * @return \eZ\Publish\API\Repository\Values\User\RoleAssignment
1134
     */
1135
    public function loadRoleAssignment($roleAssignmentId)
1136
    {
1137
        if ($this->repository->hasAccess('role', 'read') !== true) {
1138
            throw new UnauthorizedException('role', 'read');
1139
        }
1140
1141
        $spiRoleAssignment = $this->userHandler->loadRoleAssignment($roleAssignmentId);
1142
        $userService = $this->repository->getUserService();
1143
        $role = $this->loadRole($spiRoleAssignment->roleId);
1144
        $roleAssignment = null;
1145
1146
        // First check if the Role is assigned to a User
1147
        // If no User is found, see if it belongs to a UserGroup
1148
        try {
1149
            $user = $userService->loadUser($spiRoleAssignment->contentId);
1150
            $roleAssignment = $this->roleDomainMapper->buildDomainUserRoleAssignmentObject(
1151
                $spiRoleAssignment,
1152
                $user,
1153
                $role
1154
            );
1155
        } catch (APINotFoundException $e) {
1156
            try {
1157
                $userGroup = $userService->loadUserGroup($spiRoleAssignment->contentId);
1158
                $roleAssignment = $this->roleDomainMapper->buildDomainUserGroupRoleAssignmentObject(
1159
                    $spiRoleAssignment,
1160
                    $userGroup,
1161
                    $role
1162
                );
1163
            } catch (APINotFoundException $e) {
1164
                // Do nothing
1165
            }
1166
        }
1167
1168
        return $roleAssignment;
1169
    }
1170
1171
    /**
1172
     * Returns the assigned user and user groups to this role.
1173
     *
1174
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to read a role
1175
     *
1176
     * @param \eZ\Publish\API\Repository\Values\User\Role $role
1177
     *
1178
     * @return \eZ\Publish\API\Repository\Values\User\RoleAssignment[]
1179
     */
1180
    public function getRoleAssignments(APIRole $role)
1181
    {
1182
        if ($this->repository->hasAccess('role', 'read') !== true) {
1183
            throw new UnauthorizedException('role', 'read');
1184
        }
1185
1186
        $userService = $this->repository->getUserService();
1187
        $spiRoleAssignments = $this->userHandler->loadRoleAssignmentsByRoleId($role->id);
1188
        $roleAssignments = array();
1189
1190
        foreach ($spiRoleAssignments as $spiRoleAssignment) {
1191
            // First check if the Role is assigned to a User
1192
            // If no User is found, see if it belongs to a UserGroup
1193
            try {
1194
                $user = $userService->loadUser($spiRoleAssignment->contentId);
1195
                $roleAssignments[] = $this->roleDomainMapper->buildDomainUserRoleAssignmentObject(
1196
                    $spiRoleAssignment,
1197
                    $user,
1198
                    $role
1199
                );
1200
            } catch (APINotFoundException $e) {
1201
                try {
1202
                    $userGroup = $userService->loadUserGroup($spiRoleAssignment->contentId);
1203
                    $roleAssignments[] = $this->roleDomainMapper->buildDomainUserGroupRoleAssignmentObject(
1204
                        $spiRoleAssignment,
1205
                        $userGroup,
1206
                        $role
1207
                    );
1208
                } catch (APINotFoundException $e) {
1209
                    // Do nothing
1210
                }
1211
            }
1212
        }
1213
1214
        return $roleAssignments;
1215
    }
1216
1217
    /**
1218
     * @see \eZ\Publish\API\Repository\RoleService::getRoleAssignmentsForUser()
1219
     */
1220
    public function getRoleAssignmentsForUser(User $user, $inherited = false)
1221
    {
1222
        if ($this->repository->hasAccess('role', 'read') !== true) {
1223
            throw new UnauthorizedException('role', 'read');
1224
        }
1225
1226
        $roleAssignments = array();
1227
        $spiRoleAssignments = $this->userHandler->loadRoleAssignmentsByGroupId($user->id, $inherited);
1228
        foreach ($spiRoleAssignments as $spiRoleAssignment) {
1229
            $role = $this->loadRole($spiRoleAssignment->roleId);
1230
            if (!$inherited || $spiRoleAssignment->contentId == $user->id) {
1231
                $roleAssignments[] = $this->roleDomainMapper->buildDomainUserRoleAssignmentObject(
1232
                    $spiRoleAssignment,
1233
                    $user,
1234
                    $role
1235
                );
1236
            } else {
1237
                $userGroup = $this->repository->getUserService()->loadUserGroup($spiRoleAssignment->contentId);
1238
                $roleAssignments[] = $this->roleDomainMapper->buildDomainUserGroupRoleAssignmentObject(
1239
                    $spiRoleAssignment,
1240
                    $userGroup,
1241
                    $role
1242
                );
1243
            }
1244
        }
1245
1246
        return $roleAssignments;
1247
    }
1248
1249
    /**
1250
     * Returns the roles assigned to the given user group.
1251
     *
1252
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to read a role
1253
     *
1254
     * @param \eZ\Publish\API\Repository\Values\User\UserGroup $userGroup
1255
     *
1256
     * @return \eZ\Publish\API\Repository\Values\User\UserGroupRoleAssignment[]
1257
     */
1258
    public function getRoleAssignmentsForUserGroup(UserGroup $userGroup)
1259
    {
1260
        if ($this->repository->hasAccess('role', 'read') !== true) {
1261
            throw new UnauthorizedException('role', 'read');
1262
        }
1263
1264
        $roleAssignments = array();
1265
        $spiRoleAssignments = $this->userHandler->loadRoleAssignmentsByGroupId($userGroup->id);
1266
        foreach ($spiRoleAssignments as $spiRoleAssignment) {
1267
            $role = $this->loadRole($spiRoleAssignment->roleId);
1268
            $roleAssignments[] = $this->roleDomainMapper->buildDomainUserGroupRoleAssignmentObject(
1269
                $spiRoleAssignment,
1270
                $userGroup,
1271
                $role
1272
            );
1273
        }
1274
1275
        return $roleAssignments;
1276
    }
1277
1278
    /**
1279
     * Instantiates a role create class.
1280
     *
1281
     * @param string $name
1282
     *
1283
     * @return \eZ\Publish\API\Repository\Values\User\RoleCreateStruct
1284
     */
1285
    public function newRoleCreateStruct($name)
1286
    {
1287
        return new RoleCreateStruct(
1288
            array(
1289
                'identifier' => $name,
1290
                'policies' => array(),
1291
            )
1292
        );
1293
    }
1294
1295
    /**
1296
     * Instantiates a policy create class.
1297
     *
1298
     * @param string $module
1299
     * @param string $function
1300
     *
1301
     * @return \eZ\Publish\API\Repository\Values\User\PolicyCreateStruct
1302
     */
1303
    public function newPolicyCreateStruct($module, $function)
1304
    {
1305
        return new PolicyCreateStruct(
1306
            array(
1307
                'module' => $module,
1308
                'function' => $function,
1309
                'limitations' => array(),
1310
            )
1311
        );
1312
    }
1313
1314
    /**
1315
     * Instantiates a policy update class.
1316
     *
1317
     * @return \eZ\Publish\API\Repository\Values\User\PolicyUpdateStruct
1318
     */
1319
    public function newPolicyUpdateStruct()
1320
    {
1321
        return new PolicyUpdateStruct(
1322
            array(
1323
                'limitations' => array(),
1324
            )
1325
        );
1326
    }
1327
1328
    /**
1329
     * Instantiates a policy update class.
1330
     *
1331
     * @return \eZ\Publish\API\Repository\Values\User\RoleUpdateStruct
1332
     */
1333
    public function newRoleUpdateStruct()
1334
    {
1335
        return new RoleUpdateStruct();
1336
    }
1337
1338
    /**
1339
     * Returns the LimitationType registered with the given identifier.
1340
     *
1341
     * Returns the correct implementation of API Limitation value object
1342
     * based on provided identifier
1343
     *
1344
     * @param string $identifier
1345
     *
1346
     * @return \eZ\Publish\SPI\Limitation\Type
1347
     *
1348
     * @throws \RuntimeException if there is no LimitationType with $identifier
1349
     */
1350
    public function getLimitationType($identifier)
1351
    {
1352
        return $this->limitationService->getLimitationType($identifier);
1353
    }
1354
1355
    /**
1356
     * Returns the LimitationType's assigned to a given module/function.
1357
     *
1358
     * Typically used for:
1359
     *  - Internal validation limitation value use on Policies
1360
     *  - Role admin gui for editing policy limitations incl list limitation options via valueSchema()
1361
     *
1362
     * @param string $module Legacy name of "controller", it's a unique identifier like "content"
1363
     * @param string $function Legacy name of a controller "action", it's a unique within the controller like "read"
1364
     *
1365
     * @return \eZ\Publish\SPI\Limitation\Type[]
1366
     *
1367
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException If module/function to limitation type mapping
1368
     *                                                                 refers to a non existing identifier.
1369
     */
1370
    public function getLimitationTypesByModuleFunction($module, $function)
1371
    {
1372
        if (empty($this->settings['policyMap'][$module][$function])) {
1373
            return array();
1374
        }
1375
1376
        $types = array();
1377
        try {
1378
            foreach (array_keys($this->settings['policyMap'][$module][$function]) as $identifier) {
1379
                $types[$identifier] = $this->limitationService->getLimitationType($identifier);
1380
            }
1381
        } catch (LimitationNotFoundException $e) {
1382
            throw new BadStateException(
1383
                "{$module}/{$function}",
1384
                "policyMap configuration is referring to non existing identifier: {$identifier}",
1385
                $e
1386
            );
1387
        }
1388
1389
        return $types;
1390
    }
1391
1392
    /**
1393
     * Validates Policies and Limitations in Role create struct.
1394
     *
1395
     * @uses validatePolicy()
1396
     *
1397
     * @param \eZ\Publish\API\Repository\Values\User\RoleCreateStruct $roleCreateStruct
1398
     *
1399
     * @return \eZ\Publish\Core\FieldType\ValidationError[][][]
1400
     */
1401
    protected function validateRoleCreateStruct(APIRoleCreateStruct $roleCreateStruct)
1402
    {
1403
        $allErrors = array();
1404
        foreach ($roleCreateStruct->getPolicies() as $key => $policyCreateStruct) {
1405
            $errors = $this->validatePolicy(
1406
                $policyCreateStruct->module,
1407
                $policyCreateStruct->function,
1408
                $policyCreateStruct->getLimitations()
1409
            );
1410
1411
            if (!empty($errors)) {
1412
                $allErrors[$key] = $errors;
1413
            }
1414
        }
1415
1416
        return $allErrors;
1417
    }
1418
1419
    /**
1420
     * Validates Policy context: Limitations on a module and function.
1421
     *
1422
     * @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException If the same limitation is repeated or if
1423
     *                                                                   limitation is not allowed on module/function
1424
     *
1425
     * @param string $module
1426
     * @param string $function
1427
     * @param \eZ\Publish\API\Repository\Values\User\Limitation[] $limitations
1428
     *
1429
     * @return \eZ\Publish\Core\FieldType\ValidationError[][]
1430
     */
1431
    protected function validatePolicy($module, $function, array $limitations)
1432
    {
1433
        if ($module !== '*' && $function !== '*' && !empty($limitations)) {
1434
            $limitationSet = array();
1435
            foreach ($limitations as $limitation) {
1436
                if (isset($limitationSet[$limitation->getIdentifier()])) {
1437
                    throw new InvalidArgumentException(
1438
                        'limitations',
1439
                        "'{$limitation->getIdentifier()}' was found several times among the limitations"
1440
                    );
1441
                }
1442
1443
                if (!isset($this->settings['policyMap'][$module][$function][$limitation->getIdentifier()])) {
1444
                    throw new InvalidArgumentException(
1445
                        'policy',
1446
                        "The limitation '{$limitation->getIdentifier()}' is not applicable on '{$module}/{$function}'"
1447
                    );
1448
                }
1449
1450
                $limitationSet[$limitation->getIdentifier()] = true;
1451
            }
1452
        }
1453
1454
        return $this->limitationService->validateLimitations($limitations);
1455
    }
1456
1457
    /**
1458
     * Validate that assignments not already exists and filter validations against existing.
1459
     *
1460
     * @param mixed $contentId
1461
     * @param SPIRole $spiRole
1462
     * @param array|null $limitation
1463
     *
1464
     * @return array[]|null Filtered version of $limitation
1465
     *
1466
     * @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException If assignment already exists
1467
     */
1468
    protected function checkAssignmentAndFilterLimitationValues($contentId, SPIRole $spiRole, array $limitation = null)
1469
    {
1470
        $spiRoleAssignments = $this->userHandler->loadRoleAssignmentsByGroupId($contentId);
1471
        foreach ($spiRoleAssignments as $spiAssignment) {
1472
            // Ignore assignments to other roles
1473
            if ($spiAssignment->roleId !== $spiRole->id) {
1474
                continue;
1475
            }
1476
1477
            // Throw if Role is already assigned without limitations
1478
            if ($spiAssignment->limitationIdentifier === null) {
1479
                throw new InvalidArgumentException(
1480
                    '$role',
1481
                    "Role '{$spiRole->id}' already assigned without limitations"
1482
                );
1483
            }
1484
1485
            // Ignore if we are going to assign without limitations
1486
            if ($limitation === null) {
1487
                continue;
1488
            }
1489
1490
            // Ignore if not assigned with same limitation identifier
1491
            if (!isset($limitation[$spiAssignment->limitationIdentifier])) {
1492
                continue;
1493
            }
1494
1495
            // Throw if Role is already assigned with all the same limitations
1496
            $newValues = array_diff($limitation[$spiAssignment->limitationIdentifier], $spiAssignment->values);
1497
            if (empty($newValues)) {
1498
                throw new InvalidArgumentException(
1499
                    '$role',
1500
                    "Role '{$spiRole->id}' already assigned with same '{$spiAssignment->limitationIdentifier}' value"
1501
                );
1502
            }
1503
1504
            // Continue using the filtered list of limitations
1505
            $limitation[$spiAssignment->limitationIdentifier] = $newValues;
1506
        }
1507
1508
        return $limitation;
1509
    }
1510
}
1511