Completed
Push — master ( e0017c...6b1304 )
by Tom
14s queued 11s
created

Authentication/Adapter/ObjectRepository.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
namespace DoctrineModule\Authentication\Adapter;
6
7
use Doctrine\Common\Inflector\Inflector;
8
use DoctrineModule\Options\Authentication as AuthenticationOptions;
9
use Laminas\Authentication\Adapter\AbstractAdapter;
10
use Laminas\Authentication\Adapter\Exception;
11
use Laminas\Authentication\Result as AuthenticationResult;
12
use function call_user_func;
13
use function get_class;
14
use function method_exists;
15
use function property_exists;
16
use function sprintf;
17
18
/**
19
 * Authentication adapter that uses a Doctrine object for verification.
20
 *
21
 * @link    http://www.doctrine-project.org/
22
 */
23
class ObjectRepository extends AbstractAdapter
24
{
25
    /** @var AuthenticationOptions */
26
    protected $options;
27
28
    /**
29
     * Contains the authentication results.
30
     *
31
     * @var mixed[]
32
     */
33
    protected $authenticationResultInfo = null;
34
35
    /**
36
     * Constructor
37
     *
38
     * @param mixed[]|AuthenticationOptions $options
39
     */
40 13
    public function __construct($options = [])
41
    {
42 13
        $this->setOptions($options);
43 11
    }
44
45
    /**
46
     * @param mixed[]|AuthenticationOptions $options
47
     */
48 13
    public function setOptions($options) : self
49
    {
50 13
        if (! $options instanceof AuthenticationOptions) {
51 11
            $options = new AuthenticationOptions($options);
52
        }
53
54 11
        $this->options = $options;
55
56 11
        return $this;
57
    }
58
59
    public function getOptions() : AuthenticationOptions
60
    {
61
        return $this->options;
62
    }
63
64 8
    public function authenticate() : AuthenticationResult
65
    {
66 8
        $this->setup();
67 6
        $options  = $this->options;
68
        $identity = $options
69 6
            ->getObjectRepository()
70 6
            ->findOneBy([$options->getIdentityProperty() => $this->identity]);
71
72 6
        if (! $identity) {
73 2
            $this->authenticationResultInfo['code']       = AuthenticationResult::FAILURE_IDENTITY_NOT_FOUND;
74 2
            $this->authenticationResultInfo['messages'][] = 'A record with the supplied identity could not be found.';
75
76 2
            return $this->createAuthenticationResult();
77
        }
78
79 6
        return $this->validateIdentity($identity);
80
    }
81
82
    /**
83
     * This method attempts to validate that the record in the resultset is indeed a
84
     * record that matched the identity provided to this adapter.
85
     *
86
     * @throws Exception\UnexpectedValueException
87
     */
88 6
    protected function validateIdentity(object $identity) : AuthenticationResult
89
    {
90 6
        $credentialProperty = $this->options->getCredentialProperty();
91 6
        $getter             = 'get' . Inflector::classify($credentialProperty);
92 6
        $documentCredential = null;
0 ignored issues
show
$documentCredential 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...
93
94 6
        if (method_exists($identity, $getter)) {
95 3
            $documentCredential = $identity->$getter();
96 3
        } elseif (property_exists($identity, $credentialProperty)) {
97 1
            $documentCredential = $identity->{$credentialProperty};
98
        } else {
99 2
            throw new Exception\UnexpectedValueException(
100 2
                sprintf(
101 2
                    'Property (%s) in (%s) is not accessible. You should implement %s::%s()',
102 2
                    $credentialProperty,
103 2
                    get_class($identity),
104 2
                    get_class($identity),
105 2
                    $getter
106
                )
107
            );
108
        }
109
110 4
        $credentialValue = $this->credential;
111 4
        $callable        = $this->options->getCredentialCallable();
112
113 4
        if ($callable) {
114 1
            $credentialValue = call_user_func($callable, $identity, $credentialValue);
115
        }
116
117 4
        if ($credentialValue !== true && $credentialValue !== $documentCredential) {
118 2
            $this->authenticationResultInfo['code']       = AuthenticationResult::FAILURE_CREDENTIAL_INVALID;
119 2
            $this->authenticationResultInfo['messages'][] = 'Supplied credential is invalid.';
120
121 2
            return $this->createAuthenticationResult();
122
        }
123
124 3
        $this->authenticationResultInfo['code']       = AuthenticationResult::SUCCESS;
125 3
        $this->authenticationResultInfo['identity']   = $identity;
126 3
        $this->authenticationResultInfo['messages'][] = 'Authentication successful.';
127
128 3
        return $this->createAuthenticationResult();
129
    }
130
131
    /**
132
     * This method abstracts the steps involved with making sure that this adapter was
133
     * indeed setup properly with all required pieces of information.
134
     *
135
     * @throws Exception\RuntimeException In the event that setup was not
136
     *                                    done properly throw exception.
137
     */
138 8
    protected function setup() : void
139
    {
140 8
        if ($this->identity === null) {
141 1
            throw new Exception\RuntimeException(
142
                'A value for the identity was not provided prior to authentication with ObjectRepository '
143 1
                . 'authentication adapter'
144
            );
145
        }
146
147 7
        if ($this->credential === null) {
148 1
            throw new Exception\RuntimeException(
149
                'A credential value was not provided prior to authentication with ObjectRepository'
150 1
                . ' authentication adapter'
151
            );
152
        }
153
154 6
        $this->authenticationResultInfo = [
0 ignored issues
show
Documentation Bug introduced by
It seems like array('code' => \Laminas... 'messages' => array()) of type array<string,*,{"identit...*","messages":"array"}> is incompatible with the declared type array<integer,*> of property $authenticationResultInfo.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
155 6
            'code' => AuthenticationResult::FAILURE,
156 6
            'identity' => $this->identity,
157
            'messages' => [],
158
        ];
159 6
    }
160
161
    /**
162
     * Creates a Laminas\Authentication\Result object from the information that has been collected
163
     * during the authenticate() attempt.
164
     */
165 4
    protected function createAuthenticationResult() : AuthenticationResult
166
    {
167 4
        return new AuthenticationResult(
168 4
            $this->authenticationResultInfo['code'],
169 4
            $this->authenticationResultInfo['identity'],
170 4
            $this->authenticationResultInfo['messages']
171
        );
172
    }
173
}
174