Passed
Push — master ( 77a6e6...0cc661 )
by Gaetano
08:48
created

UserManager::matchUsers()   C

Complexity

Conditions 12
Paths 35

Size

Total Lines 32
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 14.7316

Importance

Changes 0
Metric Value
cc 12
eloc 18
nc 35
nop 2
dl 0
loc 32
ccs 11
cts 15
cp 0.7332
crap 14.7316
rs 6.9666
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
        $this->setReferences($user, $step);
74 2
75
        return $user;
76
    }
77 1
78
    protected function load($step)
79 1
    {
80
        $userCollection = $this->matchUsers('load', $step);
81 1
82
        $this->validateResultsCount($userCollection, $step);
83 1
84
        $this->setReferences($userCollection, $step);
85
86
        return $userCollection;
87
    }
88
89
    /**
90
     * Method to handle the update operation of the migration instructions
91 1
     *
92
     * @todo allow setting extra profile attributes!
93 1
     */
94
    protected function update($step)
95 1
    {
96
        $userCollection = $this->matchUsers('user', $step);
97
98
        $this->validateResultsCount($userCollection, $step);
99 1
100
        if (count($userCollection) > 1 && isset($step->dsl['email'])) {
101
            throw new \Exception("Can not execute User update because multiple users match, and an email section is specified in the dsl.");
102
        }
103 1
104
        $userService = $this->repository->getUserService();
105 1
106
        foreach ($userCollection as $key => $user) {
107 1
108
            $userUpdateStruct = $userService->newUserUpdateStruct();
109 1
110 1
            if (isset($step->dsl['email'])) {
111
                $userUpdateStruct->email = $this->referenceResolver->resolveReference($step->dsl['email']);
112 1
            }
113 1
            if (isset($step->dsl['password'])) {
114
                $userUpdateStruct->password = (string)$this->referenceResolver->resolveReference($step->dsl['password']);
115 1
            }
116 1
            if (isset($step->dsl['enabled'])) {
117
                $userUpdateStruct->enabled = $this->referenceResolver->resolveReference($step->dsl['enabled']);
118
            }
119 1
120
            $user = $userService->updateUser($user, $userUpdateStruct);
121 1
122 1
            if (isset($step->dsl['groups'])) {
123
                $groups = $step->dsl['groups'];
124 1
125 1
                if (!is_array($groups)) {
126
                    $groups = array($groups);
127
                }
128 1
129
                $assignedGroups = $userService->loadUserGroupsOfUser($user);
130 1
131
                $targetGroupIds = [];
132 1
                // Assigning new groups to the user
133 1
                foreach ($groups as $groupToAssignId) {
134 1
                    $groupId = $this->referenceResolver->resolveReference($groupToAssignId);
135 1
                    $groupToAssign = $this->userGroupMatcher->matchOneByKey($groupId);
136
                    $targetGroupIds[] = $groupToAssign->id;
137 1
138 1
                    $present = false;
139
                    foreach ($assignedGroups as $assignedGroup) {
140 1
                        // Make sure we assign the user only to groups he isn't already assigned to
141 1
                        if ($assignedGroup->id == $groupToAssign->id) {
142 1
                            $present = true;
143
                            break;
144
                        }
145 1
                    }
146 1
                    if (!$present) {
147
                        $userService->assignUserToUserGroup($user, $groupToAssign);
148
                    }
149
                }
150
151 1
                // Unassigning groups that are not in the list in the migration
152 1
                foreach ($assignedGroups as $assignedGroup) {
153 1
                    if (!in_array($assignedGroup->id, $targetGroupIds)) {
154
                        $userService->unAssignUserFromUserGroup($user, $assignedGroup);
155
                    }
156
                }
157
            }
158 1
159
            $userCollection[$key] = $user;
160
        }
161 1
162
        $this->setReferences($userCollection, $step);
163 1
164
        return $userCollection;
165
    }
166
167
    /**
168
     * Method to handle the delete operation of the migration instructions
169 2
     */
170
    protected function delete($step)
171 2
    {
172
        $userCollection = $this->matchUsers('delete', $step);
173 2
174
        $this->validateResultsCount($userCollection, $step);
175 2
176
        $this->setReferences($userCollection, $step);
177 2
178 2
        $userService = $this->repository->getUserService();
179
180
        foreach ($userCollection as $user) {
181 2
            $userService->deleteUser($user);
182
        }
183
184
        return $userCollection;
185
    }
186
187
    /**
188
     * @param string $action
189 2
     * @return UserCollection
190
     * @throws \Exception
191 2
     */
192
    protected function matchUsers($action, $step)
193
    {
194
        if (!isset($step->dsl['id']) && !isset($step->dsl['user_id']) && !isset($step->dsl['email']) && !isset($step->dsl['username']) && !isset($step->dsl['match'])) {
195
            throw new InvalidStepDefinitionException("The id, email or username of a user or a match condition is required to $action it");
196 2
        }
197 2
198
        // Backwards compat
199 1
        if (isset($step->dsl['match'])) {
200 1
            $match = $step->dsl['match'];
201 1
        } else {
202
            $conds = array();
203 1
            if (isset($step->dsl['id'])) {
204
                $conds['id'] = $step->dsl['id'];
205
            }
206 1
            if (isset($step->dsl['user_id'])) {
207
                $conds['id'] = $step->dsl['user_id'];
208
            }
209 1
            if (isset($step->dsl['email'])) {
210
                $conds['email'] = $step->dsl['email'];
211
            }
212 1
            if (isset($step->dsl['username'])) {
213
                $conds['login'] = $step->dsl['username'];
214
            }
215
            $match = $conds;
216 2
        }
217
218 2
        // convert the references passed in the match
219
        $match = $this->resolveReferencesRecursively($match);
220
221
        $tolerateMisses = isset($step->dsl['match_tolerate_misses']) ? $this->referenceResolver->resolveReference($step->dsl['match_tolerate_misses']) : false;
222
223
        return $this->userMatcher->match($match, $tolerateMisses);
224
    }
225
226
    /**
227
     * @param User $user
228
     * @param array $references the definitions of the references to set
229 2
     * @throws \InvalidArgumentException When trying to assign a reference to an unsupported attribute
230
     * @return array key: the reference names, values: the reference values
231 2
     *
232
     * @todo allow setting refs to all the attributes that can be gotten for Contents
233 2
     */
234
    protected function getReferencesValues($user, array $references, $step)
235 2
    {
236 2
        $refs = array();
237 2
238 2
        foreach ($references as $reference) {
239 2
240 1
            switch ($reference['attribute']) {
241 1
                case 'user_id':
242 1
                case 'id':
243 1
                    $value = $user->id;
244 1
                    break;
245 1
                case 'email':
246 1
                    $value = $user->email;
247 1
                    break;
248 1
                case 'enabled':
249 1
                    $value = $user->enabled;
250 1
                    break;
251 1
                case 'login':
252 1
                    $value = $user->login;
253 1
                    break;
254 1
                case 'groups_ids':
255
                    $value = [];
256 1
                    $userService = $this->repository->getUserService();
257
                    $userGroups = $userService->loadUserGroupsOfUser($user);
258
                    foreach ($userGroups as $userGroup) {
259
                        $value[] = $userGroup->id;
260
                    }
261 2
                    break;
262
                default:
263
                    throw new \InvalidArgumentException('User Manager does not support setting references for attribute ' . $reference['attribute']);
264 2
            }
265
266
            $refs[$reference['identifier']] = $value;
267
        }
268
269
        return $refs;
270
    }
271
}
272