Test Failed
Pull Request — master (#3)
by Chauncey
01:59
created

Authenticator::changeUserPassword()   B

Complexity

Conditions 9
Paths 14

Size

Total Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 56
rs 7.4044
c 0
b 0
f 0
cc 9
nc 14
nop 3

How to fix   Long Method   

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 Charcoal\User;
4
5
use InvalidArgumentException;
6
7
// From 'charcoal-object'
8
use Charcoal\Object\ContentInterface;
9
10
// From 'charcoal-user'
11
use Charcoal\User\Access\AuthenticatableInterface;
12
use Charcoal\User\UserInterface;
13
14
/**
15
 * The User Authenticator
16
 */
17
class Authenticator extends AbstractAuthenticator
18
{
19
    /**
20
     * Log a user into the application.
21
     *
22
     * @param  AuthenticatableInterface $user     The authenticated user to log in.
23
     * @param  boolean                  $remember Whether to "remember" the user or not.
24
     * @return boolean Success / Failure
25
     */
26
    public function login(AuthenticatableInterface $user, $remember = false)
27
    {
28
        $result = parent::login($user, $remember);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $result is correct as parent::login($user, $remember) (which targets Charcoal\User\AbstractAuthenticator::login()) 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...
29
30
        if ($result) {
31
            $this->touchUserLogin($user);
32
        }
33
34
        return $result;
35
    }
36
37
    /**
38
     * Validate the user authentication state is okay.
39
     *
40
     * For example, inactive users can not authenticate.
41
     *
42
     * @param  AuthenticatableInterface $user The user to validate.
43
     * @return boolean
44
     */
45
    public function validateAuthentication(AuthenticatableInterface $user)
46
    {
47
        if ($user instanceof ContentInterface) {
48
            if (!$user['active']) {
49
                return false;
50
            }
51
        }
52
53
        return parent::validateAuthentication($user);
54
    }
55
56
    /**
57
     * Updates the user's timestamp for their last log in.
58
     *
59
     * @param  AuthenticatableInterface $user     The user to update.
60
     * @param  string                   $password The plain-text password to hash.
0 ignored issues
show
Bug introduced by
There is no parameter named $password. 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...
61
     * @param  boolean                  $update   Whether to persist changes to storage.
62
     * @return boolean Returns TRUE if the password was changed, or FALSE otherwise.
63
     */
64
    protected function touchUserLogin(AuthenticatableInterface $user, $update = true)
65
    {
66
        if (!($user instanceof UserInterface)) {
67
            return false;
68
        }
69
70
        if (!$user->getAuthId()) {
71
            throw new InvalidArgumentException(
72
                'Can not touch user: user has no ID'
73
            );
74
        }
75
76
        $userId = $user->getAuthId();
77
78
        if ($update && $userId) {
79
            $userClass = get_class($user);
80
81
            $this->logger->info(sprintf(
82
                'Updating last login fields for user "%s" (%s)',
83
                $userId,
84
                $userClass
85
            ));
86
        }
87
88
        $user['lastLoginDate'] = 'now';
89
        $user['lastLoginIp']   = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
90
91
        if ($update && $userId) {
92
            $result = $user->update([
93
                'last_login_ip',
94
                'last_login_date',
95
            ]);
96
97
            if ($result) {
98
                $this->logger->notice(sprintf(
99
                    'Last login fields were updated for user "%s" (%s)',
100
                    $userId,
101
                    $userClass
0 ignored issues
show
Bug introduced by
The variable $userClass does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
102
                ));
103
            } else {
104
                $this->logger->warning(sprintf(
105
                    'Last login fields failed to be updated for user "%s" (%s)',
106
                    $userId,
107
                    $userClass
108
                ));
109
            }
110
        }
111
112
        return $result;
0 ignored issues
show
Bug introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
113
    }
114
115
    /**
116
     * Updates the user's password hash.
117
     *
118
     * @param  AuthenticatableInterface $user     The user to update.
119
     * @param  string                   $password The plain-text password to hash.
120
     * @param  boolean                  $update   Whether to persist changes to storage.
121
     * @throws InvalidArgumentException If the password is invalid.
122
     * @return boolean Returns TRUE if the password was changed, or FALSE otherwise.
123
     */
124
    protected function changeUserPassword(AuthenticatableInterface $user, $password, $update = true)
125
    {
126
        if (!($user instanceof UserInterface)) {
127
            return parent::changeUserPassword($user, $password);
128
        }
129
130
        if (!$this->validateAuthPassword($password)) {
131
            throw new InvalidArgumentException(
132
                'Can not reset password: password is invalid'
133
            );
134
        }
135
136
        $userId = $user->getAuthId();
137
138
        if ($update && $userId) {
139
            $userClass = get_class($user);
140
141
            $this->logger->info(sprintf(
142
                'Changing password for user "%s" (%s)',
143
                $userId,
144
                $userClass
145
            ));
146
        }
147
148
        $passwordKey = $user->getAuthPasswordKey();
149
150
        $user[$passwordKey]       = password_hash($password, PASSWORD_DEFAULT);
151
        $user['lastPasswordDate'] = 'now';
152
        $user['lastPasswordIp']   = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
153
154
        if ($update && $userId) {
155
            $result = $user->update([
156
                $passwordKey,
157
                'last_password_date',
158
                'last_password_ip',
159
            ]);
160
161
            if ($result) {
162
                $this->logger->notice(sprintf(
163
                    'Password was changed for user "%s" (%s)',
164
                    $userId,
165
                    $userClass
0 ignored issues
show
Bug introduced by
The variable $userClass does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
166
                ));
167
            } else {
168
                $this->logger->warning(sprintf(
169
                    'Password failed to be changed for user "%s" (%s)',
170
                    $userId,
171
                    $userClass
172
                ));
173
            }
174
175
            return $result;
176
        }
177
178
        return true;
179
    }
180
}
181