Completed
Push — develop ( 098743...5f7eab )
by Raphael De
02:19
created

Server::__construct()   B

Complexity

Conditions 6
Paths 32

Size

Total Lines 25
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 25
ccs 0
cts 22
cp 0
rs 8.439
cc 6
eloc 19
nc 32
nop 8
crap 42

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Majora\Component\OAuth\Server;
4
5
use Majora\Component\OAuth\Entity\AccessToken;
6
use Majora\Component\OAuth\Entity\LoginAttempt;
7
use Majora\Component\OAuth\Entity\RefreshToken;
8
use Majora\Component\OAuth\Event\AccessTokenEvent;
9
use Majora\Component\OAuth\Event\AccessTokenEvents;
10
use Majora\Component\OAuth\Event\RefreshTokenEvent;
11
use Majora\Component\OAuth\Event\RefreshTokenEvents;
12
use Majora\Component\OAuth\Exception\InvalidGrantException;
13
use Majora\Component\OAuth\Generator\RandomTokenGenerator;
14
use Majora\Component\OAuth\GrantType\GrantExtensionInterface;
15
use Majora\Component\OAuth\Loader\ApplicationLoaderInterface;
16
use Majora\Component\OAuth\Model\AccessTokenInterface;
17
use Majora\Component\OAuth\Model\AccountInterface;
18
use Majora\Component\OAuth\Model\ApplicationInterface;
19
use Majora\Component\OAuth\Model\RefreshTokenInterface;
20
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
21
use Symfony\Component\OptionsResolver\OptionsResolver;
22
23
/**
24
 * OAuth server main class.
25
 */
26
class Server
27
{
28
    /**
29
     * @var GrantExtensionInterface[]
30
     */
31
    protected $grantExtensions;
32
33
    /**
34
     * @var ApplicationLoaderInterface
35
     */
36
    protected $applicationLoader;
37
38
    /**
39
     * @var EventDispatcherInterface
40
     */
41
    protected $eventDispatcher;
42
43
    /**
44
     * @var RandomTokenGenerator
45
     */
46
    protected $randomTokenGenerator;
47
48
    /**
49
     * @var int
50
     */
51
    protected $accessTokenTtl;
52
53
    /**
54
     * @var string
55
     */
56
    protected $accessTokenClassName;
57
58
    /**
59
     * @var int
60
     */
61
    protected $refreshTokenTtl;
62
63
    /**
64
     * @var string
65
     */
66
    protected $refreshTokenClassName;
67
68
    /**
69
     * Construct.
70
     *
71
     * @param EventDispatcherInterface   $eventDispatcher
72
     * @param ApplicationLoaderInterface $applicationLoader
73
     * @param int                        $accessTokenTtl
74
     * @param string                     $accessTokenClassName
75
     * @param int                        $refreshTokenTtl
76
     * @param string                     $refreshTokenClassName
77
     * @param RandomTokenGenerator       $randomTokenGenerator
78
     * @param array                      $grantExtensions
79
     */
80
    public function __construct(
81
        EventDispatcherInterface $eventDispatcher,
82
        ApplicationLoaderInterface $applicationLoader,
83
        $accessTokenTtl,
84
        $accessTokenClassName,
85
        $refreshTokenTtl,
86
        $refreshTokenClassName,
87
        RandomTokenGenerator $randomTokenGenerator,
88
        array $grantExtensions = array()
89
    ) {
90
        $this->applicationLoader = $applicationLoader;
91
        $this->eventDispatcher = $eventDispatcher;
92
        $this->randomTokenGenerator = $randomTokenGenerator;
93
94
        $this->accessTokenTtl = $accessTokenTtl ?: AccessTokenInterface::DEFAULT_TTL;
95
        $this->accessTokenClassName = $accessTokenClassName ?: AccessToken::class;
96
97
        $this->refreshTokenTtl = $refreshTokenTtl ?: RefreshTokenInterface::DEFAULT_TTL;
98
        $this->refreshTokenClassName = $refreshTokenClassName ?: RefreshToken::class;
99
100
        $this->grantExtensions = array();
101
        foreach ($grantExtensions as $grantType => $extension) {
102
            $this->registerGrantExtension($grantType, $extension);
103
        }
104
    }
105
106
    /**
107
     * Register an extension under given grant type.
108
     *
109
     * @param string                  $grantType
110
     * @param GrantExtensionInterface $extension
111
     */
112
    public function registerGrantExtension($grantType, GrantExtensionInterface $extension)
113
    {
114
        $this->grantExtensions[$grantType] = $extension;
115
    }
116
117
    /**
118
     * Validate given request parameters and build a
119
     * LoginAttempt object with it.
120
     *
121
     * @param array $data
122
     * @param array $headers
123
     * @param array $query
124
     *
125
     * @return LoginAttempt
126
     */
127
    protected function createLoginAttempt(array $data, array $headers, array $query)
128
    {
129
        // validate grant_type manually (needed to guess specialized option resolver)
130
        if (empty($data['grant_type'])) {
131
            throw new \InvalidArgumentException('Any grant_type given.');
132
        }
133
        $grantType = $data['grant_type'];
134
        if (!isset($this->grantExtensions[$grantType])) {
135
            throw new \InvalidArgumentException('Given grant_type is invalid.');
136
        }
137
138
        // create option resolver
139
        $requestResolver = new OptionsResolver();
140
        $requestResolver->setRequired(array(
141
            'client_secret',
142
            'client_api_key',
143
            'grant_type',
144
        ));
145
        $this->grantExtensions[$grantType]->configureRequestParameters(
146
            $requestResolver
147
        );
148
149
        return new LoginAttempt(
150
            $query,
151
            $requestResolver->resolve($data),
152
            $headers
153
        );
154
    }
155
156
    /**
157
     * Loads application for given login attempt.
158
     *
159
     * @param LoginAttempt $loginAttempt
160
     *
161
     * @return ApplicationInterface
162
     *
163
     * @throws InvalidGrantException
164
     */
165
    protected function loadApplication(LoginAttempt $loginAttempt)
166
    {
167
        // retrieve Application
168
        if (!$application = $this->applicationLoader->retrieveByApiKeyAndSecret(
169
            $loginAttempt->getData('client_api_key'),
170
            $loginAttempt->getData('client_secret')
171
        )) {
172
            throw new InvalidGrantException(
173
                $loginAttempt,
174
                'Any application found for given api_key / secret.'
175
            );
176
        }
177
178
        return $application;
179
    }
180
181
    /**
182
     * Runs grant extension to load accounts.
183
     *
184
     * @param ApplicationInterface $application
185
     * @param LoginAttempt         $loginAttempt
186
     *
187
     * @return AccountInterface
188
     *
189
     * @throws \InvalidArgumentException
190
     * @throws UnknownGrantTypeException
191
     */
192
    protected function loadAccount(
193
        ApplicationInterface $application,
194
        LoginAttempt $loginAttempt
195
    ) {
196
        // run grant extension
197
        return $this->grantExtensions[$loginAttempt->getData('grant_type')]->grant(
198
            $application,
199
            $loginAttempt
200
        );
201
    }
202
203
    /**
204
     * Grant given credentials, or throws an exception if invalid
205
     * credentials for application or account.
206
     *
207
     * @param array $data    login request data
208
     * @param array $headers optionnal login request headers
209
     * @param array $query   optionnal login request query
210
     *
211
     * @return AccessTokenInterface
212
     */
213
    public function grant(array $data, array $headers = array(), array $query = array())
214
    {
215
        // create and validate login attempt from given data
216
        $loginAttempt = $this->createLoginAttempt(
217
            $data, $headers, $query
218
        );
219
220
        // load application / account
221
        $account = $this->loadAccount(
222
            $application = $this->loadApplication($loginAttempt),
223
            $loginAttempt
224
        );
225
226
        // event call
227
        $this->eventDispatcher->dispatch(
228
            AccessTokenEvents::MAJORA_ACCESS_TOKEN_CREATED,
229
            new AccessTokenEvent(
230
                $accessToken = new $this->accessTokenClassName(
231
                    $application,
232
                    $account,
233
                    $this->accessTokenTtl,
234
                    $this->randomTokenGenerator->generate('access_token')
235
                )
236
            )
237
        );
238
239
        $this->eventDispatcher->dispatch(
240
            RefreshTokenEvents::MAJORA_REFRESH_TOKEN_CREATED,
241
            new RefreshTokenEvent(
242
                $refreshToken = new $this->refreshTokenClassName(
243
                    $application,
244
                    $account,
245
                    $this->refreshTokenTtl,
246
                    $this->randomTokenGenerator->generate('refresh_token')
247
                )
248
            )
249
        );
250
251
        return $accessToken;
252
    }
253
}
254