Passed
Push — master ( a565e0...939e78 )
by Gaetano
09:53
created

UserManager   B

Complexity

Total Complexity 46

Size/Duplication

Total Lines 268
Duplicated Lines 0 %

Test Coverage

Coverage 92.62%

Importance

Changes 3
Bugs 1 Features 0
Metric Value
eloc 130
c 3
b 1
f 0
dl 0
loc 268
rs 8.72
ccs 113
cts 122
cp 0.9262
wmc 46

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
C update() 0 71 15
A delete() 0 15 2
C matchUsers() 0 32 12
B create() 0 52 6
B getReferencesValues() 0 38 9
A load() 0 9 1

How to fix   Complexity   

Complex Class

Complex classes like UserManager 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.

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 UserManager, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\Executor;
4
5
use eZ\Publish\API\Repository\Values\User\User;
6
use Kaliop\eZMigrationBundle\API\Collection\UserCollection;
7
use Kaliop\eZMigrationBundle\API\Exception\InvalidStepDefinitionException;
8
use Kaliop\eZMigrationBundle\Core\Matcher\UserGroupMatcher;
9
use Kaliop\eZMigrationBundle\Core\Matcher\UserMatcher;
10
11
/**
12
 * Handles user migrations.
13
 */
14
class UserManager extends RepositoryExecutor
15
{
16
    protected $supportedStepTypes = array('user');
17
    protected $supportedActions = array('create', 'load', 'update', 'delete');
18
19
    protected $userMatcher;
20
21
    protected $userGroupMatcher;
22 96
23
    public function __construct(UserMatcher $userMatcher, UserGroupMatcher $userGroupMatcher)
24 96
    {
25 96
        $this->userMatcher = $userMatcher;
26 96
        $this->userGroupMatcher = $userGroupMatcher;
27
    }
28
29
    /**
30
     * Creates a user based on the DSL instructions.
31
     *
32
     * @todo allow setting extra profile attributes!
33 2
     */
34
    protected function create($step)
35 2
    {
36
        if (!isset($step->dsl['groups'])) {
37
            throw new InvalidStepDefinitionException('No user groups set to create user in.');
38
        }
39 2
40
        if (!is_array($step->dsl['groups'])) {
41
            $step->dsl['groups'] = array($step->dsl['groups']);
42
        }
43 2
44 2
        $userService = $this->repository->getUserService();
45
        $contentTypeService = $this->repository->getContentTypeService();
46 2
47 2
        $userGroups = array();
48 2
        foreach ($step->dsl['groups'] as $groupId) {
49 2
            $groupId = $this->referenceResolver->resolveReference($groupId);
50
            $userGroup = $this->userGroupMatcher->matchOneByKey($groupId);
51
52
            // q: in which case can we have no group? And should we throw an exception?
53 2
            //if ($userGroup) {
54
                $userGroups[] = $userGroup;
55
            //}
56
        }
57 2
58
        $userContentType = $contentTypeService->loadContentTypeByIdentifier($this->getUserContentType($step));
59 2
60 2
        $userCreateStruct = $userService->newUserCreateStruct(
61 2
            $this->referenceResolver->resolveReference($step->dsl['username']),
62 2
            $this->referenceResolver->resolveReference($step->dsl['email']),
63 2
            $this->referenceResolver->resolveReference($step->dsl['password']),
64 2
            $this->getLanguageCode($step),
65
            $userContentType
66 2
        );
67 2
        $userCreateStruct->setField('first_name', $this->referenceResolver->resolveReference($step->dsl['first_name']));
68
        $userCreateStruct->setField('last_name', $this->referenceResolver->resolveReference($step->dsl['last_name']));
69
70 2
        // Create the user
71
        $user = $userService->createUser($userCreateStruct, $userGroups);
72 2
73
        if (isset($step->dsl['roles'])) {
74 2
            $roleService = $this->repository->getRoleService();
75
            // we support both Ids and Identifiers
76
            foreach ($step->dsl['roles'] as $roleId) {
77 1
                $roleId = $this->referenceResolver->resolveReference($roleId);
78
                $role = $this->roleMatcher->matchOneByKey($roleId);
0 ignored issues
show
Bug Best Practice introduced by
The property roleMatcher does not exist on Kaliop\eZMigrationBundle\Core\Executor\UserManager. Did you maybe forget to declare it?
Loading history...
79 1
                $roleService->assignRoleToUser($role, $user);
80
            }
81 1
        }
82
83 1
        $this->setReferences($user, $step);
84
85
        return $user;
86
    }
87
88
    protected function load($step)
89
    {
90
        $userCollection = $this->matchUsers('load', $step);
91 1
92
        $this->validateResultsCount($userCollection, $step);
93 1
94
        $this->setReferences($userCollection, $step);
95 1
96
        return $userCollection;
97
    }
98
99 1
    /**
100
     * Method to handle the update operation of the migration instructions
101
     *
102
     * @todo allow setting extra profile attributes!
103 1
     */
104
    protected function update($step)
105 1
    {
106
        $userCollection = $this->matchUsers('user', $step);
107 1
108
        $this->validateResultsCount($userCollection, $step);
109 1
110 1
        if (count($userCollection) > 1 && isset($step->dsl['email'])) {
111
            throw new \Exception("Can not execute User update because multiple users match, and an email section is specified in the dsl.");
112 1
        }
113 1
114
        $userService = $this->repository->getUserService();
115 1
116 1
        foreach ($userCollection as $key => $user) {
117
118
            $userUpdateStruct = $userService->newUserUpdateStruct();
119 1
120
            if (isset($step->dsl['email'])) {
121 1
                $userUpdateStruct->email = $this->referenceResolver->resolveReference($step->dsl['email']);
122 1
            }
123
            if (isset($step->dsl['password'])) {
124 1
                $userUpdateStruct->password = (string)$this->referenceResolver->resolveReference($step->dsl['password']);
125 1
            }
126
            if (isset($step->dsl['enabled'])) {
127
                $userUpdateStruct->enabled = $this->referenceResolver->resolveReference($step->dsl['enabled']);
128 1
            }
129
130 1
            $user = $userService->updateUser($user, $userUpdateStruct);
131
132 1
            if (isset($step->dsl['groups'])) {
133 1
                $groups = $step->dsl['groups'];
134 1
135 1
                if (!is_array($groups)) {
136
                    $groups = array($groups);
137 1
                }
138 1
139
                $assignedGroups = $userService->loadUserGroupsOfUser($user);
140 1
141 1
                $targetGroupIds = [];
142 1
                // Assigning new groups to the user
143
                foreach ($groups as $groupToAssignId) {
144
                    $groupId = $this->referenceResolver->resolveReference($groupToAssignId);
145 1
                    $groupToAssign = $this->userGroupMatcher->matchOneByKey($groupId);
146 1
                    $targetGroupIds[] = $groupToAssign->id;
147
148
                    $present = false;
149
                    foreach ($assignedGroups as $assignedGroup) {
150
                        // Make sure we assign the user only to groups he isn't already assigned to
151 1
                        if ($assignedGroup->id == $groupToAssign->id) {
152 1
                            $present = true;
153 1
                            break;
154
                        }
155
                    }
156
                    if (!$present) {
157
                        $userService->assignUserToUserGroup($user, $groupToAssign);
158 1
                    }
159
                }
160
161 1
                // Unassigning groups that are not in the list in the migration
162
                foreach ($assignedGroups as $assignedGroup) {
163 1
                    if (!in_array($assignedGroup->id, $targetGroupIds)) {
164
                        $userService->unAssignUserFromUserGroup($user, $assignedGroup);
165
                    }
166
                }
167
            }
168
169 2
            $userCollection[$key] = $user;
170
        }
171 2
172
        $this->setReferences($userCollection, $step);
173 2
174
        return $userCollection;
175 2
    }
176
177 2
    /**
178 2
     * Method to handle the delete operation of the migration instructions
179
     */
180
    protected function delete($step)
181 2
    {
182
        $userCollection = $this->matchUsers('delete', $step);
183
184
        $this->validateResultsCount($userCollection, $step);
185
186
        $this->setReferences($userCollection, $step);
187
188
        $userService = $this->repository->getUserService();
189 2
190
        foreach ($userCollection as $user) {
191 2
            $userService->deleteUser($user);
192
        }
193
194
        return $userCollection;
195
    }
196 2
197 2
    /**
198
     * @param string $action
199 1
     * @return UserCollection
200 1
     * @throws \Exception
201 1
     */
202
    protected function matchUsers($action, $step)
203 1
    {
204
        if (!isset($step->dsl['id']) && !isset($step->dsl['user_id']) && !isset($step->dsl['email']) && !isset($step->dsl['username']) && !isset($step->dsl['match'])) {
205
            throw new InvalidStepDefinitionException("The id, email or username of a user or a match condition is required to $action it");
206 1
        }
207
208
        // Backwards compat
209 1
        if (isset($step->dsl['match'])) {
210
            $match = $step->dsl['match'];
211
        } else {
212 1
            $conds = array();
213
            if (isset($step->dsl['id'])) {
214
                $conds['id'] = $step->dsl['id'];
215
            }
216 2
            if (isset($step->dsl['user_id'])) {
217
                $conds['id'] = $step->dsl['user_id'];
218 2
            }
219
            if (isset($step->dsl['email'])) {
220
                $conds['email'] = $step->dsl['email'];
221
            }
222
            if (isset($step->dsl['username'])) {
223
                $conds['login'] = $step->dsl['username'];
224
            }
225
            $match = $conds;
226
        }
227
228
        // convert the references passed in the match
229 2
        $match = $this->resolveReferencesRecursively($match);
230
231 2
        $tolerateMisses = isset($step->dsl['match_tolerate_misses']) ? $this->referenceResolver->resolveReference($step->dsl['match_tolerate_misses']) : false;
232
233 2
        return $this->userMatcher->match($match, $tolerateMisses);
234
    }
235 2
236 2
    /**
237 2
     * @param User $user
238 2
     * @param array $references the definitions of the references to set
239 2
     * @throws InvalidStepDefinitionException
240 1
     * @return array key: the reference names, values: the reference values
241 1
     *
242 1
     * @todo allow setting refs to all the attributes that can be gotten for Contents
243 1
     */
244 1
    protected function getReferencesValues($user, array $references, $step)
245 1
    {
246 1
        $refs = array();
247 1
248 1
        foreach ($references as $key => $reference) {
249 1
250 1
            $reference = $this->parseReferenceDefinition($key, $reference);
251 1
252 1
            switch ($reference['attribute']) {
253 1
                case 'user_id':
254 1
                case 'id':
255
                    $value = $user->id;
256 1
                    break;
257
                case 'email':
258
                    $value = $user->email;
259
                    break;
260
                case 'enabled':
261 2
                    $value = $user->enabled;
262
                    break;
263
                case 'login':
264 2
                    $value = $user->login;
265
                    break;
266
                case 'groups_ids':
267
                    $value = [];
268
                    $userService = $this->repository->getUserService();
269
                    $userGroups = $userService->loadUserGroupsOfUser($user);
270
                    foreach ($userGroups as $userGroup) {
271
                        $value[] = $userGroup->id;
272
                    }
273
                    break;
274
                default:
275
                    throw new InvalidStepDefinitionException('User Manager does not support setting references for attribute ' . $reference['attribute']);
276
            }
277
278
            $refs[$reference['identifier']] = $value;
279
        }
280
281
        return $refs;
282
    }
283
}
284