Completed
Pull Request — master (#16)
by Sergii
07:30
created

RawUserContext   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 218
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 26
lcom 1
cbo 11
dl 0
loc 218
ccs 0
cts 97
cp 0
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A entityType() 0 4 1
A getCurrentId() 0 4 2
A getIdByArguments() 0 6 1
A createUserWithRoles() 0 11 2
A loginUser() 0 13 2
B fillLoginForm() 0 23 4
B isLoggedIn() 0 25 5
A logoutUser() 0 7 2
B createTestUser() 0 59 7
1
<?php
2
/**
3
 * @author Sergii Bondarenko, <[email protected]>
4
 */
5
namespace Drupal\TqExtension\Context\User;
6
7
// Contexts.
8
use Drupal\TqExtension\Context\RawTqContext;
9
// Utils.
10
use Drupal\TqExtension\Utils\BaseEntity;
11
use Drupal\TqExtension\Utils\EntityDrupalWrapper;
12
use Drupal\TqExtension\Utils\Database\FetchField;
13
use Drupal\TqExtension\Cores\DrupalKernelPlaceholder;
14
15
class RawUserContext extends RawTqContext
16
{
17
    use BaseEntity;
18
19
    /**
20
     * {@inheritdoc}
21
     */
22
    protected function entityType()
23
    {
24
        return 'user';
25
    }
26
27
    /**
28
     * {@inheritdoc}
29
     */
30
    public function getCurrentId()
31
    {
32
        return empty($this->user->uid) ? 0 : $this->user->uid;
33
    }
34
35
    /**
36
     * @param string $column
37
     *   Column of a "users" table.
38
     * @param string $value
39
     *   Expected value in column.
40
     *
41
     * @return int
42
     */
43
    public function getIdByArguments($column, $value)
44
    {
45
        return (new FetchField('users', 'uid'))
46
            ->condition($column, $value)
47
            ->execute();
48
    }
49
50
    /**
51
     * @param string $roles
52
     *   Necessary user roles separated by comma.
53
     * @param array $fields
54
     *
55
     * @return \stdClass
56
     */
57
    public function createUserWithRoles($roles, array $fields = [])
58
    {
59
        $user = $this->createTestUser($fields);
60
        $driver = $this->getDriver();
61
62
        foreach (array_map('trim', explode(',', $roles)) as $role) {
63
            $driver->userAddRole($user, $role);
64
        }
65
66
        return $user;
67
    }
68
69
    /**
70
     * @throws \Exception
71
     */
72
    public function loginUser()
73
    {
74
        $this->logoutUser();
75
76
        if (empty($this->user)) {
77
            throw new \Exception('Tried to login without a user.');
78
        }
79
80
        $this->fillLoginForm([
81
            'username' => $this->user->name,
82
            'password' => $this->user->pass,
83
        ]);
84
    }
85
86
    /**
87
     * @param array $props
88
     *   An array with two keys: "username" and "password". Both of them are required.
89
     * @param string $message
90
     *   An error message, that will be thrown when user cannot be authenticated.
91
     *
92
     * @throws \Behat\Mink\Exception\ElementNotFoundException
93
     *   When one of a fields cannot be not found.
94
     * @throws \Exception
95
     *   When login process failed.
96
     * @throws \WebDriver\Exception\NoSuchElement
97
     *   When log in button cannot be found.
98
     */
99
    public function fillLoginForm(array $props, $message = '')
100
    {
101
        $this->getRedirectContext()->visitPage('user/login');
102
        $formContext = $this->getFormContext();
103
104
        foreach (['username', 'password'] as $prop) {
105
            $formContext->fillField($this->getDrupalText($prop . '_field'), $props[$prop]);
106
        }
107
108
        $this->getWorkingElement()->pressButton($this->getDrupalText('log_in'));
109
110
        if (!$this->isLoggedIn()) {
111
            throw new \Exception($message ?: sprintf(
112
                'Failed to login as a user "%s" with password "%s".',
113
                $props['username'],
114
                $props['password']
115
            ));
116
        }
117
118
        $this->user = user_load_by_name($props['username']);
119
120
        DrupalKernelPlaceholder::setCurrentUser($this->user);
121
    }
122
123
    /**
124
     * Cookies are set when at least one page of the site has been visited. This
125
     * action done in "beforeScenario" hook of TqContext.
126
     *
127
     * @see TqContext::beforeScenario()
128
     *
129
     * @return bool
130
     */
131
    public function isLoggedIn()
132
    {
133
        $cookieName = session_name();
134
        $baseUrl = parse_url($this->locatePath());
135
136
        // When "base_url" has "https" scheme, then secure cookie (SSESS) will be set to
137
        // mark authentication. "session_name()" will return unsecure name (SESS) since it
138
        // run programmatically. Correct a cookie name if Behat configured for using secure
139
        // URL and name is not "secure".
140
        // "scheme" may not exist in case if, for instance, "127.0.0.1:1234" used as base URL.
141
        if (strpos($cookieName, 'SS') !== 0 && isset($baseUrl['scheme']) && 'https' === $baseUrl['scheme']) {
142
            $cookieName = "S$cookieName";
143
        }
144
145
        $cookie = $this->getSession()->getCookie($cookieName);
146
147
        if (null !== $cookie) {
148
            // "goutte" session using for checking HTTP status codes.
149
            $this->getSession('goutte')->setCookie($cookieName, $cookie);
150
151
            return true;
152
        }
153
154
        return false;
155
    }
156
157
    public function logoutUser()
158
    {
159
        if ($this->isLoggedIn()) {
160
            $this->logout();
161
            $this->user = false;
162
        }
163
    }
164
165
    /**
166
     * @param array $fields
167
     *   Additional data for user account.
168
     *
169
     * @throws \Exception
170
     *
171
     * @return \stdClass
172
     */
173
    public function createTestUser(array $fields = [])
174
    {
175
        $random = $this->getRandom();
176
        $username = $random->name(8);
177
        $user = [
178
            'name' => $username,
179
            'pass' => $random->name(16),
180
            'mail' => "[email protected]",
181
            'roles' => [
182
                DRUPAL_AUTHENTICATED_RID => 'authenticated user',
183
            ],
184
        ];
185
186
        if (!empty($fields)) {
187
            $entity = new EntityDrupalWrapper('user');
188
            // Remove fields such as "name", "pass", "mail" if they are required.
189
            $required = array_diff_key($entity->getRequiredFields(), $user);
190
191
            // Fill fields. Field can be found by name or label.
192
            foreach ($fields as $fieldName => $value) {
193
                $fieldName = $entity->getFieldNameByLocator($fieldName);
194
195
                $user[$fieldName] = $value;
196
                // Remove field from $required if it was there and filled.
197
                unset($required[$fieldName]);
198
            }
199
200
            // Throw an exception when one of required fields was not filled.
201
            if (!empty($required)) {
202
                throw new \Exception(sprintf(
203
                    'The following fields "%s" are required and has not filled.',
204
                    implode('", "', $required)
205
                ));
206
            }
207
        }
208
209
        $user = (object) $user;
210
        $userId = DrupalKernelPlaceholder::getUidByName($user->name);
211
212
        // User is already exists, remove it to create again.
213
        if ($userId > 0) {
214
            DrupalKernelPlaceholder::deleteUser($userId);
215
        }
216
217
        // $this->user always exist but when no user created it has "false" as a value.
218
        // Variable stored to another because RawDrupalContext::userCreate() will modify
219
        // it and this will affect for future actions.
220
        if (!empty($this->user)) {
221
            $tmp = $this->user;
222
        }
223
224
        $this->userCreate($user);
225
226
        if (isset($tmp)) {
227
            $this->user = $tmp;
228
        }
229
230
        return $user;
231
    }
232
}
233