Completed
Push — ezp26175-exception_on_non_defa... ( 77d2f3...ca5fc8 )
by
unknown
39:33
created

UserContext   F

Complexity

Total Complexity 68

Size/Duplication

Total Lines 568
Duplicated Lines 5.99 %

Coupling/Cohesion

Components 1
Dependencies 18

Importance

Changes 0
Metric Value
dl 34
loc 568
rs 2.9203
c 0
b 0
f 0
wmc 68
lcom 1
cbo 18

25 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
B searchUserByLogin() 0 22 6
A searchUserGroups() 0 17 2
B createUser() 0 30 4
A createUserGroup() 0 11 2
B ensureUserExists() 8 38 6
C ensureUserDoesntExist() 8 31 8
A checkUserExistenceByUsername() 0 17 4
B checkUserExistenceByEmail() 0 19 6
A createPasswordHash() 18 18 4
A iHaveUser() 0 6 1
A iHaveUserWithUsernameEmailAndPassword() 0 4 1
A iHaveUserInGroup() 0 6 1
A iHaveUserWithUsernameEmailAndPasswordInGroup() 0 4 1
A iDontHaveUser() 0 4 1
A iDontHaveUserInGroup() 0 4 1
A iHaveTheFollowingUsers() 0 9 2
A assertUserWithNameExists() 0 7 1
A assertUserWithNameDoesntExist() 0 7 1
A assertUserWithNameExistsInGroup() 0 7 1
A assertUserWithNameDoesntExistInGroup() 0 7 1
A assertUserWithNameDoesntExistInGroups() 0 12 2
B assertUserWithNameExistsWithFields() 0 31 4
A findNonExistingUserEmail() 0 16 4
A findNonExistingUserName() 0 11 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 UserContext 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 UserContext, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
4
 * @license For full copyright and license information view LICENSE file distributed with this source code.
5
 * @version //autogentag//
6
 */
7
namespace eZ\Bundle\EzPublishCoreBundle\Features\Context;
8
9
use Behat\Gherkin\Node\TableNode;
10
use Behat\Behat\Context\Context;
11
use PHPUnit_Framework_Assert as Assertion;
12
use EzSystems\PlatformBehatBundle\Context\RepositoryContext;
13
use eZ\Publish\API\Repository\Repository;
14
use eZ\Publish\API\Repository\UserService;
15
use eZ\Publish\API\Repository\SearchService;
16
use eZ\Publish\API\Repository\Values\ValueObject;
17
use eZ\Publish\API\Repository\Exceptions as ApiExceptions;
18
use eZ\Publish\API\Repository\Values\Content\Query;
19
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
20
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
21
22
/**
23
 * Sentences for Users.
24
 */
25
class UserContext implements Context
26
{
27
    use RepositoryContext;
28
29
    const DEFAULT_LANGUAGE = 'eng-GB';
30
31
    /**
32
     * These values are set by the default eZ Publish installation.
33
     */
34
    const USER_IDENTIFIER = 'user';
35
36
    const USERGROUP_ROOT_CONTENT_ID = 4;
37
    const USERGROUP_ROOT_LOCATION = 5;
38
    const USERGROUP_ROOT_SUBTREE = '/1/5/';
39
    const USERGROUP_CONTENT_IDENTIFIER = 'user_group';
40
41
    /**
42
     * @var \eZ\Publish\API\Repository\UserService
43
     */
44
    protected $userService;
45
46
    /**
47
     * @var \eZ\Publish\API\Repository\SearchService
48
     */
49
    protected $searchService;
50
51
    /**
52
     * @injectService $repository @ezpublish.api.repository
53
     * @injectService $userService @ezpublish.api.service.user
54
     * @injectService $searchService @ezpublish.api.service.search
55
     */
56
    public function __construct(Repository $repository, UserService $userService, SearchService $searchService)
57
    {
58
        $this->setRepository($repository);
59
        $this->userService = $userService;
60
        $this->searchService = $searchService;
61
    }
62
63
    /**
64
     * Search User with given username, optionally at given location.
65
     *
66
     * @param string $username name of User to search for
67
     * @param string $parentGroupLocationId where to search, in User Group tree
0 ignored issues
show
Bug introduced by
There is no parameter named $parentGroupLocationId. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
68
     *
69
     * @return User found
70
     */
71
    public function searchUserByLogin($username, $parentGroupId = null)
72
    {
73
        try {
74
            $user = $this->userService->loadUserByLogin($username);
75
        } catch (ApiExceptions\NotFoundException $e) {
76
            return null;
77
        }
78
79
        if ($user && $parentGroupId) {
80
            $userGroups = $this->userService->loadUserGroupsOfUser($user);
81
82
            foreach ($userGroups as $userGroup) {
83
                if ($userGroup->getVersionInfo()->getContentInfo()->id == $parentGroupId) {
84
                    return $user;
85
                }
86
            }
87
            // user not found in $parentGroupId
88
            return null;
89
        }
90
91
        return $user;
92
    }
93
94
    /**
95
     * Search User Groups with given name.
96
     *
97
     * @param string $name name of User Group to search for
98
     * @param string $parentLocationId (optional) parent location id to search in
99
     *
100
     * @return search results
101
     */
102
    public function searchUserGroups($name, $parentLocationId = null)
103
    {
104
        $criterionArray = array(
105
            new Criterion\Subtree(self::USERGROUP_ROOT_SUBTREE),
106
            new Criterion\ContentTypeIdentifier(self::USERGROUP_CONTENT_IDENTIFIER),
107
            new Criterion\Field('name', Criterion\Operator::EQ, $name),
108
        );
109
        if ($parentLocationId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parentLocationId of type string|null is loosely compared to true; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
110
            $criterionArray[] = new Criterion\ParentLocationId($parentLocationId);
111
        }
112
        $query = new Query();
113
        $query->filter = new Criterion\LogicalAnd($criterionArray);
114
115
        $result = $this->searchService->findContent($query, array(), false);
116
117
        return $result->searchHits;
118
    }
119
120
    /**
121
     * Create user inside given User Group; DELETES existing User if login already exists!
122
     *
123
     * @param $username username of the user to create
124
     * @param $email email address of user to create
125
     * @param $password account password for user to create
126
     * @param $parentGroup pathstring wherein to create user
127
     *
128
     * @return eZ\Publish\API\Repository\Values\User\User
129
     */
130
    protected function createUser($username, $email, $password, $parentGroup = null, $fields = array())
131
    {
132
        $userCreateStruct = $this->userService->newUserCreateStruct(
133
            $username,
134
            $email,
135
            $password,
136
            self::DEFAULT_LANGUAGE
137
        );
138
        $userCreateStruct->setField('first_name', $username);
139
        $userCreateStruct->setField('last_name', $username);
140
141
        foreach ($fields as $fieldName => $fieldValue) {
142
            $userCreateStruct->setField($fieldName, $fieldValue);
143
        }
144
145
        try {
146
            $existingUser = $this->userService->loadUserByLogin($username);
147
            $this->userService->deleteUser($existingUser);
148
        } catch (NotFoundException $e) {
149
            // do nothing
150
        }
151
152
        if (!$parentGroup) {
153
            $parentGroup = $this->userService->loadUserGroup(self::USERGROUP_ROOT_CONTENT_ID);
154
        }
155
156
        $user = $this->userService->createUser($userCreateStruct, array($parentGroup));
157
158
        return $user;
159
    }
160
161
    /**
162
     * Create new User Group inside existing parent User Group.
163
     *
164
     * @param string $name  User Group name
165
     * @param \eZ\Publish\API\Repository\Values\User\UserGroup $parentGroup  (optional) parent user group, defaults to UserGroup "/Users"
166
     *
167
     * @return \eZ\Publish\API\Repository\Values\User\UserGroup
168
     */
169
    public function createUserGroup($name, $parentGroup = null)
170
    {
171
        if (!$parentGroup) {
172
            $parentGroup = $this->userService->loadUserGroup(self::USERGROUP_ROOT_CONTENT_ID);
173
        }
174
175
        $userGroupCreateStruct = $this->userService->newUserGroupCreateStruct('eng-GB');
176
        $userGroupCreateStruct->setField('name', $name);
177
178
        return $this->userService->createUserGroup($userGroupCreateStruct, $parentGroup);
179
    }
180
181
    /**
182
     * Make sure a User with name $username, $email and $password exists in parent group.
183
     *
184
     * @param string $username User name
185
     * @param string $email User's email
186
     * @param string $password User's password
187
     * @param string $parentGroupName (optional) name of the parent group to check
188
     *
189
     * @return \eZ\Publish\API\Repository\Values\User\User
190
     */
191
    public function ensureUserExists($username, $email, $password, $parentGroupName = null)
192
    {
193
        if ($parentGroupName) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parentGroupName of type string|null is loosely compared to true; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
194
            $parentSearchHits = $this->searchUserGroups($parentGroupName);
195
196
            // Found matching Group(s)
197
            if (!empty($parentSearchHits)) {
198
                $firstGroupId = $parentSearchHits[0]->valueObject->contentInfo->id;
0 ignored issues
show
Documentation introduced by
The property contentInfo does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

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

<?php

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

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

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

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

}

If the property has read access only, you can use the @property-read annotation instead.

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

See also the PhpDoc documentation for @property.

Loading history...
199 View Code Duplication
                foreach ($parentSearchHits as $userGroupHit) {
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...
200
                    $groupId = $userGroupHit->valueObject->contentInfo->id;
0 ignored issues
show
Documentation introduced by
The property contentInfo does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

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

<?php

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

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

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

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

}

If the property has read access only, you can use the @property-read annotation instead.

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

See also the PhpDoc documentation for @property.

Loading history...
201
                    // Search for user in this group
202
                    $user = $this->searchUserByLogin($username, $groupId);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $user is correct as $this->searchUserByLogin($username, $groupId) (which targets eZ\Bundle\EzPublishCoreB...xt::searchUserByLogin()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
203
                    if ($user) {
204
                        return $user;
205
                    }
206
                }
207
208
                // create user inside existing parent Group, use first group found
209
                $parentGroup = $this->userService->loadUserGroup($firstGroupId);
210
211
                return $this->createUser($username, $email, $password, $parentGroup);
212
            } // else
213
214
            // Parent Group does not exist yet, so create it at "root" User Group.
215
            $rootGroup = $this->userService->loadUserGroup(self::USERGROUP_ROOT_CONTENT_ID);
216
            $parentGroup = $this->createUserGroup($parentGroupName, $rootGroup);
217
218
            return $this->createUser($username, $email, $password, $parentGroup);
219
        }
220
        // else,
221
222
        $user = $this->searchUserByLogin($username);
223
        if (!$user) {
224
            $user = $this->createUser($username, $email, $password);
225
        }
226
227
        return $user;
228
    }
229
230
    /**
231
     * Make sure a User with name $username does not exist (in parent group).
232
     *
233
     * @param string $username          User name
234
     * @param string $parentGroupName   (optional) name of the parent group to check
235
     */
236
    public function ensureUserDoesntExist($username, $parentGroupName = null)
237
    {
238
        $user = null;
239
        if ($parentGroupName) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parentGroupName of type string|null is loosely compared to true; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
240
            // find matching Parent Group name
241
            $parentSearchHits = $this->searchUserGroups($parentGroupName, self::USERGROUP_ROOT_LOCATION);
242
            if (!empty($parentSearchHits)) {
243 View Code Duplication
                foreach ($parentSearchHits as $parentGroupFound) {
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...
244
                    $groupId = $parentGroupFound->valueObject->contentInfo->id;
0 ignored issues
show
Documentation introduced by
The property contentInfo does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

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

<?php

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

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

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

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

}

If the property has read access only, you can use the @property-read annotation instead.

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

See also the PhpDoc documentation for @property.

Loading history...
245
                    //Search for already existing matching Child user
246
                    $user = $this->searchUserByLogin($username, $groupId);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $user is correct as $this->searchUserByLogin($username, $groupId) (which targets eZ\Bundle\EzPublishCoreB...xt::searchUserByLogin()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
247
                    if ($user) {
248
                        break;
249
                    }
250
                }
251
            }
252
        } else {
253
            try {
254
                $user = $this->userService->loadUserByLogin($username);
255
            } catch (ApiExceptions\NotFoundException $e) {
256
                // nothing to do
257
            }
258
        }
259
        if ($user) {
260
            try {
261
                $this->userService->deleteUser($user);
262
            } catch (ApiExceptions\NotFoundException $e) {
263
                // nothing to do
264
            }
265
        }
266
    }
267
268
    /**
269
     * Checks if the User with username $username exists.
270
     *
271
     * @param string $username User name
272
     * @param string $parentGroupName User group name to search inside
273
     *
274
     * @return bool true if it exists, false if user or group don't exist
275
     */
276
    public function checkUserExistenceByUsername($username, $parentGroupName = null)
277
    {
278
        if ($parentGroupName) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parentGroupName of type string|null is loosely compared to true; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
279
            // find parent group name
280
            $searchResults = $this->searchUserGroups($parentGroupName);
281
            if (empty($searchResults)) {
282
                // group not found, so return immediately
283
                return false;
284
            }
285
            $groupId = $searchResults[0]->valueObject->contentInfo->id;
0 ignored issues
show
Documentation introduced by
The property contentInfo does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

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

<?php

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

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

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

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

}

If the property has read access only, you can use the @property-read annotation instead.

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

See also the PhpDoc documentation for @property.

Loading history...
286
        } else {
287
            $groupId = null;
288
        }
289
        $searchResults = $this->searchUserByLogin($username, $groupId);
290
291
        return empty($searchResults) ? false : true;
292
    }
293
294
    /**
295
     * Checks if the User with email $email exists.
296
     *
297
     * @param string $email User email
298
     * @param string $parentGroupName User group name to search inside
299
     *
300
     * @return bool true if it exists, false if not
301
     */
302
    public function checkUserExistenceByEmail($email, $parentGroupName = null)
303
    {
304
        $existingUsers = $this->userService->loadUsersByEmail($email);
305
        if (count($existingUsers) == 0) {
306
            return false;
307
        }
308
        if ($parentGroupName) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parentGroupName of type string|null is loosely compared to true; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
309
            foreach ($existingUsers as $user) {
310
                $userGroups = $this->userService->loadUserGroupsOfUser($user);
311
                foreach ($userGroups as $userGroup) {
312
                    if ($userGroup->getFieldValue('name') == $parentGroupName) {
313
                        return true;
314
                    }
315
                }
316
            }
317
        }
318
319
        return false;
320
    }
321
322 View Code Duplication
    public function createPasswordHash($login, $password, $type)
323
    {
324
        switch ($type) {
325
            case 2:
326
                /* PASSWORD_HASH_MD5_USER */
327
                return md5("{$login}\n{$password}");
328
            case 3:
329
                /* PASSWORD_HASH_MD5_SITE */
330
                $site = null;
331
332
                return md5("{$login}\n{$password}\n{$site}");
333
            case 5:
334
                /* PASSWORD_HASH_PLAINTEXT */
335
                return $password;
336
        }
337
        /* PASSWORD_HASH_MD5_PASSWORD (1) */
338
        return md5($password);
339
    }
340
341
    /**
342
     * @Given there is a User with name :username
343
     *
344
     * Ensures a user with username ':username' exists, creating a new one if necessary.
345
     *
346
     * @return \eZ\Publish\API\Repository\Values\User\User
347
     */
348
    public function iHaveUser($username)
349
    {
350
        $email = $this->findNonExistingUserEmail($username);
351
        $password = $username;
352
        $user = $this->ensureUserExists($username, $email, $password);
0 ignored issues
show
Unused Code introduced by
$user is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
353
    }
354
355
    /**
356
     * @Given there is a User with name :username, email :email and password :password
357
     *
358
     * Ensures a user exists with given username/email/password, creating a new one if necessary.
359
     *
360
     * @return \eZ\Publish\API\Repository\Values\User\User
361
     */
362
    public function iHaveUserWithUsernameEmailAndPassword($username, $email, $password)
363
    {
364
        $this->ensureUserExists($username, $email, $password);
365
    }
366
    /**
367
     * @Given there is a User with name :username in :parentGroup group
368
     *
369
     * Ensures a user with username ':username' exists as a child of ':parentGroup' user group, can create either one.
370
     *
371
     * @return \eZ\Publish\API\Repository\Values\User\User
372
     */
373
    public function iHaveUserInGroup($username, $parentGroupName)
374
    {
375
        $email = $this->findNonExistingUserEmail($username);
376
        $password = $username;
377
        $user = $this->ensureUserExists($username, $email, $password, $parentGroupName);
0 ignored issues
show
Unused Code introduced by
$user is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
378
    }
379
    /**
380
     * @Given there is a User with name :username, email :email and password :password in :parentGroup group
381
     *
382
     * Ensures a user with given username/email/password as a child of ':parentGroup' user group, can create either one.
383
     *
384
     * @return \eZ\Publish\API\Repository\Values\User\User
385
     */
386
    public function iHaveUserWithUsernameEmailAndPasswordInGroup($username, $email, $password, $parentGroupName)
387
    {
388
        return $this->ensureUserExists($username, $email, $password, $parentGroupName);
389
    }
390
391
    /**
392
     * @Given there isn't a User with name :username
393
     *
394
     * Makes sure a user with username ':username' doesn't exist, removing it if necessary.
395
     */
396
    public function iDontHaveUser($username)
397
    {
398
        $this->ensureUserDoesntExist($username);
399
    }
400
    /**
401
     * @Given there isn't a User with name :username in :parentGroup group
402
     *
403
     * Makes sure a user with username ':username' doesn't exist as a chield of group ':parentGroup', removing it if necessary.
404
     */
405
    public function iDontHaveUserInGroup($username, $parentGroup)
406
    {
407
        $this->ensureUserDoesntExist($username, $parentGroup);
408
    }
409
410
    /**
411
     * @Given there are the following Users:
412
     *
413
     * Make sure that users in the provided table exist in their respective parent group. Example:
414
     *      | username        | parentGroup      |
415
     *      | testUser1       | Members          |
416
     *      | testUser2       | Editors          |
417
     *      | testUser3       | NewParent        | # Both user and group should be created
418
     */
419
    public function iHaveTheFollowingUsers(TableNode $table)
420
    {
421
        $users = $table->getTable();
422
        array_shift($users);
423
        foreach ($users as $user) {
424
            // array( [0] => userName, [1] => groupName );
425
            $this->ensureUserExists($user[0], $user[1]);
426
        }
427
    }
428
429
    /**
430
     * @Given a User with name :username already exists
431
     * @Then User with name :username exists
432
     *
433
     * Checks that user ':username' exists.
434
     */
435
    public function assertUserWithNameExists($username)
436
    {
437
        Assertion::assertTrue(
438
            $this->checkUserExistenceByUsername($username),
439
            "Couldn't find User with name '$username'."
440
        );
441
    }
442
443
    /**
444
     * @Then User with name :username doesn't exist
445
     *
446
     * Checks that user ':username' does not exist.
447
     */
448
    public function assertUserWithNameDoesntExist($username)
449
    {
450
        Assertion::assertFalse(
451
            $this->checkUserExistenceByUsername($username),
452
            "User with name '$username' was found."
453
        );
454
    }
455
456
    /**
457
     * @Then User with name :username exists in group :parentGroup
458
     * @Then User with name :username exists in :parentGroup group
459
     *
460
     * Checks that user ':username' exists as a child of group ':parentGroup'.
461
     */
462
    public function assertUserWithNameExistsInGroup($username, $parentGroup)
463
    {
464
        Assertion::assertTrue(
465
            $this->checkUserExistenceByUsername($username, $parentGroup),
466
            "Couldn't find User with name '$username' in parent group '$parentGroup'."
467
        );
468
    }
469
470
    /**
471
     * @Then User with name :username doesn't exist in group :parentGroup
472
     * @Then User with name :username doesn't exist in :parentGroup group
473
     *
474
     * Checks that user ':username' does not exist as a child of group ':parentGroup'.
475
     */
476
    public function assertUserWithNameDoesntExistInGroup($username, $parentGroup)
477
    {
478
        Assertion::assertFalse(
479
            $this->checkUserExistenceByUsername($username, $parentGroup),
480
            "User with name '$username' was found in parent group '$parentGroup'."
481
        );
482
    }
483
484
    /**
485
     * @Then User with name :username doesn't exist in the following groups:
486
     *
487
     * Checks that user ':username' does not exist in any of the provided groups. Example:
488
     *      | parentGroup           |
489
     *      | Partners              |
490
     *      | Anonymous Users       |
491
     *      | Editors               |
492
     *      | Administrator users   |
493
     */
494
    public function assertUserWithNameDoesntExistInGroups($username, TableNode $table)
495
    {
496
        $groups = $table->getTable();
497
        array_shift($groups);
498
        foreach ($groups as $group) {
499
            $parentGroupName = $group[0];
500
            Assertion::assertFalse(
501
                $this->checkUserExistenceByUsername($username, $parentGroupName),
502
                "User with name '$username' was found in parent group '$parentGroupName'."
503
            );
504
        }
505
    }
506
507
    /**
508
     * @Then User with name :username has the following fields:
509
     * @Then User with name :username exists with the following fields:
510
     *
511
     * Checks that user ':username' exists with the values provided in the field/value table. example:
512
     *       | Name          | value           |
513
     *       | email         | [email protected]  |
514
     *       | password      | testuser        |
515
     *       | first_name    | Test            |
516
     *       | last_name     | User            |
517
     */
518
    public function assertUserWithNameExistsWithFields($username, TableNode $table)
519
    {
520
        Assertion::assertTrue(
521
            $this->checkUserExistenceByUsername($username),
522
            "Couldn't find User with name '$username'."
523
        );
524
        $user = $this->userService->loadUserByLogin($username);
525
        $fieldsTable = $table->getTable();
526
        array_shift($fieldsTable);
527
        $updateFields = array();
0 ignored issues
show
Unused Code introduced by
$updateFields is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
528
        foreach ($fieldsTable as $fieldRow) {
529
            $fieldName = $fieldRow[0];
530
            $expectedValue = $fieldRow[1];
531
            switch ($fieldName) {
532
                case 'email':
533
                    $fieldValue = $user->email;
534
                    break;
535
                case 'password':
536
                    $fieldValue = $user->passwordHash;
537
                    $expectedValue = $this->createPasswordHash($username, $expectedValue, $user->hashAlgorithm);
538
                    break;
539
                default:
540
                    $fieldValue = $user->getFieldValue($fieldName);
541
            }
542
            Assertion::assertEquals(
543
                $expectedValue,
544
                $fieldValue,
545
                "Field '$fieldName' did not contain expected value '$expectedValue'."
546
            );
547
        }
548
    }
549
550
    /**
551
     * Find a non existing User email.
552
     *
553
     * @return string A not used email
554
     *
555
     * @throws \Exception Possible endless loop
556
     */
557
    private function findNonExistingUserEmail($username = 'User')
558
    {
559
        $email = "${username}@ez.no";
560
        if ($this->checkUserExistenceByEmail($email)) {
561
            return $email;
562
        }
563
564
        for ($i = 0; $i < 20; ++$i) {
565
            $email = 'User#' . uniqid() . '@ez.no';
566
            if (!$this->checkUserExistenceByEmail($email)) {
567
                return $email;
568
            }
569
        }
570
571
        throw new \Exception('Possible endless loop when attempting to find a new email for User.');
572
    }
573
574
    /**
575
     * Find a non existing User name.
576
     *
577
     * @return string A not used name
578
     *
579
     * @throws \Exception Possible endless loop
580
     */
581
    private function findNonExistingUserName()
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
582
    {
583
        for ($i = 0; $i < 20; ++$i) {
584
            $username = 'User#' . uniqid();
585
            if (!$this->checkUserExistenceByUsername($username)) {
586
                return $username;
587
            }
588
        }
589
590
        throw new \Exception('Possible endless loop when attempting to find a new name for User.');
591
    }
592
}
593