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

RawUserContext::isLoggedIn()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

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