Completed
Push — master ( eb16f0...b029a9 )
by Patrick
03:00
created

SQLAuthenticator::isLoggedIn()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace Auth;
3
4
if(!function_exists('password_hash') || !function_exists('password_verify'))
5
{
6
    define('PASSWORD_BCRYPT', 1);
7
    define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);
8
    define('PASSWORD_BCRYPT_DEFAULT_COST', 10);
9
10
    function password_hash($password, $algo = PASSWORD_DEFAULT)
11
    {
12
        if(is_null($password) || is_int($password))
13
        {
14
            $password = (string)$password;
15
        }
16
        if(!is_string($password))
17
        {
18
            trigger_error("password_hash(): Password must be a string", E_USER_WARNING);
19
            return false;
20
        }
21
        if(!is_int($algo))
22
        {
23
            trigger_error("password_hash() expects parameter 2 to be long, ".gettype($algo)." given", E_USER_WARNING);
24
            return false;
25
        }
26
        switch($algo)
27
        {
28
            case PASSWORD_BCRYPT:
29
                $cost = PASSWORD_BCRYPT_DEFAULT_COST;
30
                $rawSaltLen = 16;
31
                $requiredSaltLen = 22;
32
                $hashFormat = sprintf("$2y$%02d$", $cost);
33
                $resultLength = 60;
34
                break;
35
            default:
36
                trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING);
37
                return false;
38
        }
39
        $salt = openssl_random_pseudo_bytes($rawSaltLen);
40
        $base64Digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
41
        $bcrypt64Digits = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
42
        $base64String = base64_encode($salt);
43
        $salt = strtr(rtrim($base64String, '='), $base64Digits, $bcrypt64Digits);
44
        $salt = substr($salt, 0, $requiredSaltLen);
45
        $hash = $hashFormat.$salt;
46
        $ret = crypt($password, $hash);
47
        if(!is_string($ret) || strlen($ret) != $resultLength)
48
        {
49
            return false;
50
        }
51
        return $ret;
52
    }
53
54
    function password_verify($password, $hash)
55
    {
56
        $ret = crypt($password, $hash);
57
        if(!is_string($ret) || strlen($ret) != strlen($hash) || strlen($ret) <= 13)
58
        {
59
            return false;
60
        }
61
        $status = 0;
62
        $count  = strlen($ret);
63
        for($i = 0; $i < $count; $i++)
64
        {
65
            $status |= (ord($ret[$i]) ^ ord($hash[$i]));
66
        }
67
        return $status === 0;
68
    }
69
}
70
71
class SQLAuthenticator extends Authenticator
72
{
73
    public $dataSet = null;
74
    public $pendingDataSet = null;
75
    private $dataTables = array();
76
    private $params;
77
78
    public function __construct($params)
79
    {
80
        parent::__construct($params);
81
        $this->params = $params;
82
        if($this->current)
83
        {
84
            $this->dataSet = $this->getCurrentDataSet();
85
        }
86
        if($this->pending)
87
        {
88
            $this->pendingDataSet = $this->getPendingDataSet();
89
        }
90
    }
91
92
    /**
93
     * @SuppressWarnings("StaticAccess")
94
     */
95
    private function getCurrentDataSet()
96
    {
97
        if(isset($this->params['current_data_set']))
98
        {
99
            return \DataSetFactory::getDataSetByName($this->params['current_data_set']);
100
        }
101
        return \DataSetFactory::getDataSetByName('authentication');
102
    }
103
104
    /**
105
     * @SuppressWarnings("StaticAccess")
106
     */
107
    private function getPendingDataSet()
108
    {
109
        if(isset($this->params['pending_data_set']))
110
        {
111
            return \DataSetFactory::getDataSetByName($this->params['pending_data_set']);
112
        }
113
        return \DataSetFactory::getDataSetByName('pending_authentication');
114
    }
115
116
    private function getDataTable($name, $pending = false)
117
    {
118
        if(isset($this->dataTables[$name]) && isset($this->dataTables[$name][$pending]))
119
        {
120
            return $this->dataTables[$name][$pending];
121
        }
122
        $dataSet = $this->dataSet;
123
        if($pending)
124
        {
125
            $dataSet = $this->pendingDataSet;
126
        }
127
        if($dataSet === null)
128
        {
129
            throw new \Exception('Unable to obtain dataset for SQL Authentication!');
130
        }
131
        $dataTable = $dataSet[$name];
132
        if(!isset($this->dataTables[$name]))
133
        {
134
            $this->dataTables[$name] = array();
135
        }
136
        $this->dataTables[$name][$pending] = $dataTable;
137
        return $dataTable;
138
    }
139
140
    /**
141
     * Get the data table for Pending Users
142
     *
143
     * @return boolean|\Data\DataTable The Pending User Data Table
144
     */
145
    private function getPendingUserDataTable()
146
    {
147
        if(isset($this->params['pending_user_table']))
148
        {
149
            return $this->getDataTable($this->params['pending_user_table'], true);
150
        }
151
        return $this->getDataTable('users', true);
152
    }
153
154
    public function login($username, $password)
155
    {
156
        if($this->current === false)
157
        {
158
            return false;
159
        }
160
        $userDataTable = $this->getDataTable('user');
161
        $filter = new \Data\Filter("uid eq '$username'");
162
        $users = $userDataTable->read($filter);
163
        if($users === false || !isset($users[0]))
164
        {
165
            return false;
166
        }
167
        if(password_verify($password, $users[0]['pass']))
168
        {
169
            return array('res'=>true, 'extended'=>$users[0]);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return array('res' => tr...xtended' => $users[0]); (array) is incompatible with the return type of the parent method Auth\Authenticator::login of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
170
        }
171
        return false;
172
    }
173
174
    public function isLoggedIn($data)
175
    {
176
        if(isset($data['res']))
177
        {
178
            return $data['res'];
179
        }
180
        return false;
181
    }
182
183
    public function getUser($data)
184
    {
185
        if(isset($this->params['current_data_set']))
186
        {
187
            $data['current_data_set'] = $this->params['current_data_set'];
188
        }
189
        return new SQLUser($data, $this);
0 ignored issues
show
Documentation introduced by
$this is of type this<Auth\SQLAuthenticator>, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Bug Best Practice introduced by
The return type of return new \Auth\SQLUser($data, $this); (Auth\SQLUser) is incompatible with the return type of the parent method Auth\Authenticator::getUser of type Auth\Auth\User|null.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
190
    }
191
192 View Code Duplication
    public function getGroupByName($name)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
193
    {
194
        $groupDataTable = $this->getDataTable('group');
195
        $filter = new \Data\Filter("gid eq '$name'");
196
        $groups = $groupDataTable->read($filter);
197
        if($groups === false || !isset($groups[0]))
198
        {
199
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type of the parent method Auth\Authenticator::getGroupByName of type Auth\Auth\Group|null.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
200
        }
201
        return new SQLGroup($groups[0]);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \Auth\SQLGroup($groups[0]); (Auth\SQLGroup) is incompatible with the return type of the parent method Auth\Authenticator::getGroupByName of type Auth\Auth\Group|null.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
202
    }
203
204 View Code Duplication
    public function getUserByName($name)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
205
    {
206
        $userDataTable = $this->getDataTable('user');
207
        $filter = new \Data\Filter("uid eq '$name'");
208
        $users = $userDataTable->read($filter);
209
        if($users === false || !isset($users[0]))
210
        {
211
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type of the parent method Auth\Authenticator::getUserByName of type Auth\Auth\User|null.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
212
        }
213
        return new SQLUser($users[0], $this);
0 ignored issues
show
Documentation introduced by
$this is of type this<Auth\SQLAuthenticator>, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Bug Best Practice introduced by
The return type of return new \Auth\SQLUser($users[0], $this); (Auth\SQLUser) is incompatible with the return type of the parent method Auth\Authenticator::getUserByName of type Auth\Auth\User|null.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
214
    }
215
216
    private function getDataByFilter($dataTableName, $filter, $select, $top, $skip, $orderby)
217
    {
218
        $dataTable = $this->getDataTable($dataTableName);
219
        return $dataTable->read($filter, $select, $top, $skip, $orderby);
220
    }
221
222
    /**
223
     * @param string $dataTableName The Data Table to serach
224
     * @param string $className The class to obtain data in
225
     * @param boolean|array $select The fields to read
226
     * @param boolean|integer $top The number of entities to read
227
     * @param boolean|integer $skip The number of entities to skip
228
     * @param boolean|array $orderby The fields to sort by
229
     */
230
    private function convertDataToClass($dataTableName, $className, $filter, $select, $top, $skip, $orderby)
231
    {
232
        $data = $this->getDataByFilter($dataTableName, $filter, $select, $top, $skip, $orderby);
233
        if($data === false)
234
        {
235
            return false;
236
        }
237
        $count = count($data);
238
        for($i = 0; $i < $count; $i++)
239
        {
240
            $data[$i] = new $className($groups[$i], $this);
0 ignored issues
show
Bug introduced by
The variable $groups does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
241
        }
242
        return $data;
243
    }
244
245
    /**
246
     * @param boolean|array $select The fields to read
247
     * @param boolean|integer $top The number of entities to read
248
     * @param boolean|integer $skip The number of entities to skip
249
     * @param boolean|array $orderby The fields to sort by
250
     */
251
    public function getGroupsByFilter($filter, $select = false, $top = false, $skip = false, $orderby = false)
252
    {
253
        return $this->convertDataToClass('group', 'SQLGroup', $filter, $select, $top, $skip, $orderby);
254
    }
255
256
    /**
257
     * @param boolean|array $select The fields to read
258
     * @param boolean|integer $top The number of entities to read
259
     * @param boolean|integer $skip The number of entities to skip
260
     * @param boolean|array $orderby The fields to sort by
261
     */
262
    public function getUsersByFilter($filter, $select = false, $top = false, $skip = false, $orderby = false)
263
    {
264
        return $this->convertDataToClass('group', 'SQLUser', $filter, $select, $top, $skip, $orderby);
265
    }
266
267
    public function getPendingUserCount()
268
    {
269
        if($this->pending === false)
270
        {
271
            return 0;
272
        }
273
        $dataTable = $this->getPendingUserDataTable();
274
        if($dataTable === null)
275
        {
276
            return 0;
277
        }
278
        return $dataTable->count();
279
    }
280
281
    private function searchPendingUsers($filter, $select, $top, $skip, $orderby)
282
    {
283
        $userDataTable = $this->getPendingUserDataTable();
284
        $fieldData = $filter->to_mongo_filter();
285
        $firstFilter = new \Data\Filter('substringof(data,"'.implode($fieldData, ' ').'")');
286
        $users = $userDataTable->read($firstFilter, $select, $top, $skip, $orderby);
0 ignored issues
show
Documentation introduced by
$firstFilter is of type object<Data\Filter>, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
287
        if($users === false)
288
        {
289
            return false;
290
        }
291
        $ret = array();
292
        $count = count($users);
293
        for($i = 0; $i < $count; $i++)
294
        {
295
            $user = new SQLPendingUser($users[$i], $userDataTable);
0 ignored issues
show
Bug introduced by
It seems like $userDataTable defined by $this->getPendingUserDataTable() on line 283 can also be of type object<Data\DataTable>; however, Auth\SQLPendingUser::__construct() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
296
            $err = false;
297
            foreach($fieldData as $field=>$data)
298
            {
299
                if(strcasecmp($user[$field], $data) !== 0)
300
                {
301
                    $err = true; break;
302
                }
303
            }
304
            if(!$err)
305
            {
306
                array_push($ret, $user);
307
            }
308
        }
309
        return $ret;
310
    }
311
312
    /**
313
     * @param \Data\Filter $filter The filter to read with
314
     * @param boolean|array $select The fields to read
315
     * @param boolean|integer $top The number of entities to read
316
     * @param boolean|integer $skip The number of entities to skip
317
     * @param boolean|array $orderby The fields to sort by
318
     */
319
    public function getPendingUsersByFilter($filter, $select = false, $top = false, $skip = false, $orderby = false)
320
    {
321
        if($this->pending === false)
322
        {
323
            return false;
324
        }
325
        if($filter !== false && !$filter->contains('hash'))
326
        {
327
            return $this->searchPendingUsers($filter, $select, $top, $skip, $orderby);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->searchPendingUser...$top, $skip, $orderby); of type false|array adds the type array to the return on line 327 which is incompatible with the return type of the parent method Auth\Authenticator::getPendingUsersByFilter of type boolean.
Loading history...
328
        }
329
        $userDataTable = $this->getPendingUserDataTable();
330
        $users = $userDataTable->read($filter, $select, $top, $skip, $orderby);
0 ignored issues
show
Documentation introduced by
$filter is of type object<Data\Filter>, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Bug introduced by
It seems like $select defined by parameter $select on line 319 can also be of type array; however, Data\DataTable::read() does only seem to accept boolean, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
Bug introduced by
It seems like $top defined by parameter $top on line 319 can also be of type integer; however, Data\DataTable::read() does only seem to accept boolean, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
Bug introduced by
It seems like $skip defined by parameter $skip on line 319 can also be of type integer; however, Data\DataTable::read() does only seem to accept boolean, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
Bug introduced by
It seems like $orderby defined by parameter $orderby on line 319 can also be of type array; however, Data\DataTable::read() does only seem to accept boolean, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
331
        if($users === false)
332
        {
333
            return false;
334
        }
335
        $count = count($users);
336
        for($i = 0; $i < $count; $i++)
337
        {
338
            $users[$i] = new SQLPendingUser($users[$i], $userDataTable);
0 ignored issues
show
Bug introduced by
It seems like $userDataTable defined by $this->getPendingUserDataTable() on line 329 can also be of type object<Data\DataTable>; however, Auth\SQLPendingUser::__construct() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
339
        }
340
        return $users;
341
    }
342
343
    public function createPendingUser($user)
344
    {
345
        if($this->pending === false)
346
        {
347
            return false;
348
        }
349
        $userDataTable = $this->getPendingUserDataTable();
350
        if(isset($user->password2))
351
        {
352
            unset($user->password2);
353
        }
354
        $json = json_encode($user);
355
        $hash = hash('sha512', $json);
356
        $array = array('hash'=>$hash, 'data'=>$json);
357
        $ret = $userDataTable->create($array);
358
        if($ret !== false)
359
        {
360
            $users = $this->getPendingUsersByFilter(new \Data\Filter("hash eq '$hash'"));
361
            if($users === false || !isset($users[0]))
362
            {
363
                throw new \Exception('Error retreiving user object after successful create!');
364
            }
365
            $users[0]->sendEmail();
366
        }
367
        return $ret;
368
    }
369
370
    public function getTempUserByHash($hash)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
371
    {
372
        $users = $this->getPendingUsersByFilter(new \Data\Filter("hash eq '$hash'"));
373
        if($users === false || !isset($users[0]))
374
        {
375
            return false;
376
        }
377
        return $users[0];
378
    }
379
}
380
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
381