Completed
Push — EZP-31383-roles-copying ( d0932a...19a821 )
by
unknown
12:30
created

RoleDomainMapper   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 220
Duplicated Lines 17.27 %

Coupling/Cohesion

Components 2
Dependencies 17

Importance

Changes 0
Metric Value
dl 38
loc 220
rs 10
c 0
b 0
f 0
wmc 23
lcom 2
cbo 17

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A buildDomainRoleObject() 0 16 2
A buildDomainRoleDraftObject() 0 8 1
B buildDomainPolicyObject() 0 26 6
A buildDomainUserRoleAssignmentObject() 19 19 2
A buildDomainUserGroupRoleAssignmentObject() 19 19 2
A buildPersistenceRoleCreateStruct() 0 11 1
A buildPersistenceRoleCopyStruct() 0 13 1
A fillRoleStructWithPolicies() 0 13 2
A buildPersistencePolicyObject() 0 18 5

How to fix   Duplicated Code   

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:

1
<?php
2
3
/**
4
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
5
 * @license For full copyright and license information view LICENSE file distributed with this source code.
6
 */
7
namespace eZ\Publish\Core\Repository\Helper;
8
9
use eZ\Publish\Core\Repository\Permission\LimitationService;
10
use eZ\Publish\Core\Repository\Values\User\Policy;
11
use eZ\Publish\Core\Repository\Values\User\PolicyDraft;
12
use eZ\Publish\Core\Repository\Values\User\Role;
13
use eZ\Publish\API\Repository\Values\User\Role as APIRole;
14
use eZ\Publish\Core\Repository\Values\User\RoleDraft;
15
use eZ\Publish\API\Repository\Values\User\RoleCopyStruct as APIRoleCopyStruct;
16
use eZ\Publish\API\Repository\Values\User\RoleCreateStruct as APIRoleCreateStruct;
17
use eZ\Publish\Core\Repository\Values\User\UserRoleAssignment;
18
use eZ\Publish\Core\Repository\Values\User\UserGroupRoleAssignment;
19
use eZ\Publish\API\Repository\Values\User\User;
20
use eZ\Publish\API\Repository\Values\User\UserGroup;
21
use eZ\Publish\SPI\Persistence\User\Policy as SPIPolicy;
22
use eZ\Publish\SPI\Persistence\User\RoleAssignment as SPIRoleAssignment;
23
use eZ\Publish\SPI\Persistence\User\Role as SPIRole;
24
use eZ\Publish\SPI\Persistence\User\RoleCopyStruct as SPIRoleCopyStruct;
25
use eZ\Publish\SPI\Persistence\User\RoleCreateStruct as SPIRoleCreateStruct;
26
27
/**
28
 * Internal service to map Role objects between API and SPI values.
29
 *
30
 * @internal Meant for internal use by Repository.
31
 */
32
class RoleDomainMapper
33
{
34
    /** @var \eZ\Publish\Core\Repository\Permission\LimitationService */
35
    protected $limitationService;
36
37
    /**
38
     * @param \eZ\Publish\Core\Repository\Permission\LimitationService $limitationService
39
     */
40
    public function __construct(LimitationService $limitationService)
41
    {
42
        $this->limitationService = $limitationService;
43
    }
44
45
    /**
46
     * Maps provided SPI Role value object to API Role value object.
47
     *
48
     * @param \eZ\Publish\SPI\Persistence\User\Role $role
49
     *
50
     * @return \eZ\Publish\API\Repository\Values\User\Role
51
     */
52
    public function buildDomainRoleObject(SPIRole $role)
53
    {
54
        $rolePolicies = [];
55
        foreach ($role->policies as $spiPolicy) {
56
            $rolePolicies[] = $this->buildDomainPolicyObject($spiPolicy);
57
        }
58
59
        return new Role(
60
            [
61
                'id' => $role->id,
62
                'identifier' => $role->identifier,
63
                'status' => $role->status,
64
                'policies' => $rolePolicies,
65
            ]
66
        );
67
    }
68
69
    /**
70
     * Builds a RoleDraft domain object from value object returned by persistence
71
     * Decorates Role.
72
     *
73
     * @param \eZ\Publish\SPI\Persistence\User\Role $spiRole
74
     *
75
     * @return \eZ\Publish\API\Repository\Values\User\RoleDraft
76
     */
77
    public function buildDomainRoleDraftObject(SPIRole $spiRole)
78
    {
79
        return new RoleDraft(
80
            [
81
                'innerRole' => $this->buildDomainRoleObject($spiRole),
82
            ]
83
        );
84
    }
85
86
    /**
87
     * Maps provided SPI Policy value object to API Policy value object.
88
     *
89
     * @param \eZ\Publish\SPI\Persistence\User\Policy $spiPolicy
90
     *
91
     * @return \eZ\Publish\API\Repository\Values\User\Policy|\eZ\Publish\API\Repository\Values\User\PolicyDraft
92
     */
93
    public function buildDomainPolicyObject(SPIPolicy $spiPolicy)
94
    {
95
        $policyLimitations = [];
96
        if ($spiPolicy->module !== '*' && $spiPolicy->function !== '*' && $spiPolicy->limitations !== '*') {
97
            foreach ($spiPolicy->limitations as $identifier => $values) {
0 ignored issues
show
Bug introduced by
The expression $spiPolicy->limitations of type array|string is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
98
                $policyLimitations[] = $this->limitationService->getLimitationType($identifier)->buildValue($values);
99
            }
100
        }
101
102
        $policy = new Policy(
103
            [
104
                'id' => $spiPolicy->id,
105
                'roleId' => $spiPolicy->roleId,
106
                'module' => $spiPolicy->module,
107
                'function' => $spiPolicy->function,
108
                'limitations' => $policyLimitations,
109
            ]
110
        );
111
112
        // Original ID is set on SPI policy, which means that it's a draft.
113
        if ($spiPolicy->originalId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $spiPolicy->originalId of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
114
            $policy = new PolicyDraft(['innerPolicy' => $policy, 'originalId' => $spiPolicy->originalId]);
115
        }
116
117
        return $policy;
118
    }
119
120
    /**
121
     * Builds the API UserRoleAssignment object from provided SPI RoleAssignment object.
122
     *
123
     * @param \eZ\Publish\SPI\Persistence\User\RoleAssignment $spiRoleAssignment
124
     * @param \eZ\Publish\API\Repository\Values\User\User $user
125
     * @param \eZ\Publish\API\Repository\Values\User\Role $role
126
     *
127
     * @return \eZ\Publish\API\Repository\Values\User\UserRoleAssignment
128
     */
129 View Code Duplication
    public function buildDomainUserRoleAssignmentObject(SPIRoleAssignment $spiRoleAssignment, User $user, APIRole $role)
130
    {
131
        $limitation = null;
132
        if (!empty($spiRoleAssignment->limitationIdentifier)) {
133
            $limitation = $this
134
                ->limitationService
135
                ->getLimitationType($spiRoleAssignment->limitationIdentifier)
136
                ->buildValue($spiRoleAssignment->values);
0 ignored issues
show
Bug introduced by
It seems like $spiRoleAssignment->values can also be of type null; however, eZ\Publish\SPI\Limitation\Type::buildValue() does only seem to accept array<integer,*>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
137
        }
138
139
        return new UserRoleAssignment(
140
            [
141
                'id' => $spiRoleAssignment->id,
142
                'limitation' => $limitation,
143
                'role' => $role,
144
                'user' => $user,
145
            ]
146
        );
147
    }
148
149
    /**
150
     * Builds the API UserGroupRoleAssignment object from provided SPI RoleAssignment object.
151
     *
152
     * @param \eZ\Publish\SPI\Persistence\User\RoleAssignment $spiRoleAssignment
153
     * @param \eZ\Publish\API\Repository\Values\User\UserGroup $userGroup
154
     * @param \eZ\Publish\API\Repository\Values\User\Role $role
155
     *
156
     * @return \eZ\Publish\API\Repository\Values\User\UserGroupRoleAssignment
157
     */
158 View Code Duplication
    public function buildDomainUserGroupRoleAssignmentObject(SPIRoleAssignment $spiRoleAssignment, UserGroup $userGroup, APIRole $role)
159
    {
160
        $limitation = null;
161
        if (!empty($spiRoleAssignment->limitationIdentifier)) {
162
            $limitation = $this
163
                ->limitationService
164
                ->getLimitationType($spiRoleAssignment->limitationIdentifier)
165
                ->buildValue($spiRoleAssignment->values);
0 ignored issues
show
Bug introduced by
It seems like $spiRoleAssignment->values can also be of type null; however, eZ\Publish\SPI\Limitation\Type::buildValue() does only seem to accept array<integer,*>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
166
        }
167
168
        return new UserGroupRoleAssignment(
169
            [
170
                'id' => $spiRoleAssignment->id,
171
                'limitation' => $limitation,
172
                'role' => $role,
173
                'userGroup' => $userGroup,
174
            ]
175
        );
176
    }
177
178
    /**
179
     * Creates SPI Role create struct from provided API role create struct.
180
     */
181
    public function buildPersistenceRoleCreateStruct(APIRoleCreateStruct $roleCreateStruct): SPIRoleCreateStruct
182
    {
183
        $policiesToCreate = $this->fillRoleStructWithPolicies($roleCreateStruct);
184
185
        return new SPIRoleCreateStruct(
186
            [
187
                'identifier' => $roleCreateStruct->identifier,
188
                'policies' => $policiesToCreate,
189
            ]
190
        );
191
    }
192
193
    /**
194
     * Creates SPI Role copy struct from provided API role copy struct.
195
     */
196
    public function buildPersistenceRoleCopyStruct(APIRoleCopyStruct $roleCopyStruct, int $clonedId, int $status): SPIRoleCopyStruct
197
    {
198
        $policiesToCopy = $this->fillRoleStructWithPolicies($roleCopyStruct);
199
200
        return new SPIRoleCopyStruct(
201
            [
202
                'clonedId' => $clonedId,
203
                'newIdentifier' => $roleCopyStruct->newIdentifier,
204
                'status' => $status,
205
                'policies' => $policiesToCopy,
206
            ]
207
        );
208
    }
209
210
    protected function fillRoleStructWithPolicies(APIRoleCreateStruct $struct)
211
    {
212
        $policies = [];
213
        foreach ($struct->getPolicies() as $policyStruct) {
214
            $policies[] = $this->buildPersistencePolicyObject(
215
                $policyStruct->module,
216
                $policyStruct->function,
217
                $policyStruct->getLimitations()
218
            );
219
        }
220
221
        return $policies;
222
    }
223
224
    /**
225
     * Creates SPI Policy value object from provided module, function and limitations.
226
     *
227
     * @param string $module
228
     * @param string $function
229
     * @param \eZ\Publish\API\Repository\Values\User\Limitation[] $limitations
230
     *
231
     * @return \eZ\Publish\SPI\Persistence\User\Policy
232
     */
233
    public function buildPersistencePolicyObject($module, $function, array $limitations)
234
    {
235
        $limitationsToCreate = '*';
236
        if ($module !== '*' && $function !== '*' && !empty($limitations)) {
237
            $limitationsToCreate = [];
238
            foreach ($limitations as $limitation) {
239
                $limitationsToCreate[$limitation->getIdentifier()] = $limitation->limitationValues;
240
            }
241
        }
242
243
        return new SPIPolicy(
244
            [
245
                'module' => $module,
246
                'function' => $function,
247
                'limitations' => $limitationsToCreate,
248
            ]
249
        );
250
    }
251
}
252