Completed
Pull Request — master (#134)
by Tobias
06:30
created

LinkedIn::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 4
crap 1
1
<?php
2
3
namespace Happyr\LinkedIn;
4
5
use Happyr\LinkedIn\Exception\LoginError;
6
use Happyr\LinkedIn\Http\GlobalVariableGetter;
7
use Happyr\LinkedIn\Http\RequestManager;
8
use Happyr\LinkedIn\Http\ResponseConverter;
9
use Happyr\LinkedIn\Http\UrlGenerator;
10
use Happyr\LinkedIn\Http\UrlGeneratorInterface;
11
use Happyr\LinkedIn\Storage\DataStorageInterface;
12
use Http\Client\HttpClient;
13
use Http\Message\MessageFactory;
14
use Psr\Http\Message\ResponseInterface;
15
16
/**
17
 * Class LinkedIn lets you talk to LinkedIn api.
18
 *
19
 * When a new user arrives and want to authenticate here is whats happens:
20
 * 1. You redirect him to whatever url getLoginUrl() returns.
21
 * 2. The user logs in on www.linkedin.com and authorize your application.
22
 * 3. The user returns to your site with a *code* in the the $_REQUEST.
23
 * 4. You call isAuthenticated() or getAccessToken()
24
 * 5. If we don't have an access token (only a *code*), getAccessToken() will call fetchNewAccessToken()
25
 * 6. fetchNewAccessToken() gets the *code* from the $_REQUEST and calls getAccessTokenFromCode()
26
 * 7. getAccessTokenFromCode() makes a request to www.linkedin.com and exchanges the *code* for an access token
27
 * 8. When you have the access token you should store it in a database and/or query the API.
28
 * 9. When you make a second request to the API we have the access token in memory, so we don't go through all these
29
 *    authentication steps again.
30
 *
31
 * @author Tobias Nyholm <[email protected]>
32
 */
33
class LinkedIn implements LinkedInInterface
34
{
35
    /**
36
     * The OAuth access token received in exchange for a valid authorization
37
     * code.  null means the access token has yet to be determined.
38
     *
39
     * @var AccessToken
40
     */
41
    protected $accessToken = null;
42
43
    /**
44
     * @var string format
45
     */
46
    private $format;
47
48
    /**
49
     * @var string responseFormat
50
     */
51
    private $responseDataType;
52
53
    /**
54
     * @var ResponseInterface
55
     */
56
    private $lastResponse;
57
58
    /**
59
     * @var RequestManager
60
     */
61
    private $requestManager;
62
63
    /**
64
     * @var Authenticator
65
     */
66
    private $authenticator;
67
68
    /**
69
     * @var UrlGeneratorInterface
70
     */
71
    private $urlGenerator;
72
73
    /**
74
     * Constructor.
75
     *
76
     * @param string $appId
77
     * @param string $appSecret
78
     * @param string $format           'json', 'xml'
79
     * @param string $responseDataType 'array', 'string', 'simple_xml' 'psr7', 'stream'
80
     */
81 9
    public function __construct($appId, $appSecret, $format = 'json', $responseDataType = 'array')
82
    {
83 9
        $this->format = $format;
84 9
        $this->responseDataType = $responseDataType;
85
86 9
        $this->requestManager = new RequestManager();
87 9
        $this->authenticator = new Authenticator($this->requestManager, $appId, $appSecret);
88 9
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93 1
    public function isAuthenticated()
94
    {
95 1
        $accessToken = $this->getAccessToken();
96 1
        if ($accessToken === null) {
97 1
            return false;
98
        }
99
100 1
        $user = $this->api('GET', '/v1/people/~:(id,firstName,lastName)', ['format' => 'json', 'response_data_type' => 'array']);
101
102 1
        return !empty($user['id']);
103
    }
104
105
    /**
106
     * {@inheritdoc}
107
     */
108 1
    public function api($method, $resource, array $options = [])
109
    {
110
        // Add access token to the headers
111 1
        $options['headers']['Authorization'] = sprintf('Bearer %s', (string) $this->getAccessToken());
112
113
        // Do logic and adjustments to the options
114 1
        $requestFormat = $this->filterRequestOption($options);
115
116
        // Generate an url
117 1
        $url = $this->getUrlGenerator()->getUrl(
118 1
            'api',
119 1
            $resource,
120 1
            isset($options['query']) ? $options['query'] : []
121 1
        );
122
123 1
        $body = isset($options['body']) ? $options['body'] : null;
124 1
        $this->lastResponse = $this->getRequestManager()->sendRequest($method, $url, $options['headers'], $body);
125
126
        //Get the response data format
127 1
        if (isset($options['response_data_type'])) {
128
            $responseDataType = $options['response_data_type'];
129
        } else {
130 1
            $responseDataType = $this->getResponseDataType();
131
        }
132
133 1
        return ResponseConverter::convert($this->lastResponse, $requestFormat, $responseDataType);
134
    }
135
136
    /**
137
     * Modify and filter the request options. Make sure we use the correct query parameters and headers.
138
     *
139
     * @param array &$options
140
     *
141
     * @return string the request format to use
142
     */
143 1
    protected function filterRequestOption(array &$options)
144
    {
145 1
        if (isset($options['json'])) {
146 1
            $options['format'] = 'json';
147 1
            $options['body'] = json_encode($options['json']);
148 1
        } elseif (!isset($options['format'])) {
149
            // Make sure we always have a format
150
            $options['format'] = $this->getFormat();
151
        }
152
153
        // Set correct headers for this format
154 1
        switch ($options['format']) {
155 1
            case 'xml':
156
                $options['headers']['Content-Type'] = 'text/xml';
157
                break;
158 1
            case 'json':
159 1
                $options['headers']['Content-Type'] = 'application/json';
160 1
                $options['headers']['x-li-format'] = 'json';
161 1
                $options['query']['format'] = 'json';
162 1
                break;
163
            default:
164
                // Do nothing
165 1
        }
166
167 1
        return $options['format'];
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173 2
    public function getLoginUrl($options = [])
174
    {
175 2
        $urlGenerator = $this->getUrlGenerator();
176
177
        // Set redirect_uri to current URL if not defined
178 2
        if (!isset($options['redirect_uri'])) {
179 1
            $options['redirect_uri'] = $urlGenerator->getCurrentUrl();
180 1
        }
181
182 2
        return $this->getAuthenticator()->getLoginUrl($urlGenerator, $options);
183
    }
184
185
    /**
186
     * See docs for LinkedIn::api().
187
     *
188
     * @param string $resource
189
     * @param array  $options
190
     *
191
     * @return mixed
192
     */
193
    public function get($resource, array $options = [])
194
    {
195
        return $this->api('GET', $resource, $options);
196
    }
197
198
    /**
199
     * See docs for LinkedIn::api().
200
     *
201
     * @param string $resource
202
     * @param array  $options
203
     *
204
     * @return mixed
205
     */
206
    public function post($resource, array $options = [])
207
    {
208
        return $this->api('POST', $resource, $options);
209
    }
210
211
    /**
212
     * {@inheritdoc}
213
     */
214
    public function clearStorage()
215
    {
216
        $this->getAuthenticator()->clearStorage();
217
218
        return $this;
219
    }
220
221
    /**
222
     * {@inheritdoc}
223
     */
224 3
    public function hasError()
225
    {
226 3
        return GlobalVariableGetter::has('error');
227
    }
228
229
    /**
230
     * {@inheritdoc}
231
     */
232 2
    public function getError()
233
    {
234 2
        if ($this->hasError()) {
235 2
            return new LoginError(GlobalVariableGetter::get('error'), GlobalVariableGetter::get('error_description'));
236
        }
237 1
    }
238
239
    /**
240
     * Get the default format to use when sending requests.
241
     *
242
     * @return string
243
     */
244 1
    protected function getFormat()
245
    {
246 1
        return $this->format;
247
    }
248
249
    /**
250
     * {@inheritdoc}
251
     */
252 1
    public function setFormat($format)
253
    {
254 1
        $this->format = $format;
255
256 1
        return $this;
257
    }
258
259
    /**
260
     * Get the default data type to be returned as a response.
261
     *
262
     * @return string
263
     */
264 1
    protected function getResponseDataType()
265
    {
266 1
        return $this->responseDataType;
267
    }
268
269
    /**
270
     * {@inheritdoc}
271
     */
272
    public function setResponseDataType($responseDataType)
273
    {
274
        $this->responseDataType = $responseDataType;
275
276
        return $this;
277
    }
278
279
    /**
280
     * {@inheritdoc}
281
     */
282
    public function getLastResponse()
283
    {
284
        return $this->lastResponse;
285
    }
286
287
    /**
288
     * {@inheritdoc}
289
     */
290 1
    public function getAccessToken()
291
    {
292 1
        if ($this->accessToken === null) {
293 1
            if (null !== $newAccessToken = $this->getAuthenticator()->fetchNewAccessToken($this->getUrlGenerator())) {
294 1
                $this->setAccessToken($newAccessToken);
295 1
            }
296 1
        }
297
298
        // return the new access token or null if none found
299 1
        return $this->accessToken;
300
    }
301
302
    /**
303
     * {@inheritdoc}
304
     */
305 3
    public function setAccessToken($accessToken)
306
    {
307 3
        $this->accessToken = AccessToken::create($accessToken);
308
309 3
        return $this;
310
    }
311
312
    /**
313
     * {@inheritdoc}
314
     */
315 1
    public function setUrlGenerator(UrlGeneratorInterface $urlGenerator)
316
    {
317 1
        $this->urlGenerator = $urlGenerator;
318
319 1
        return $this;
320
    }
321
322
    /**
323
     * @return UrlGeneratorInterface
324
     */
325 2
    protected function getUrlGenerator()
326
    {
327 2
        if ($this->urlGenerator === null) {
328 2
            $this->urlGenerator = new UrlGenerator();
329 2
        }
330
331 2
        return $this->urlGenerator;
332
    }
333
334
    /**
335
     * {@inheritdoc}
336
     */
337
    public function setStorage(DataStorageInterface $storage)
338
    {
339
        $this->getAuthenticator()->setStorage($storage);
340
341
        return $this;
342
    }
343
344
    /**
345
     * {@inheritdoc}
346
     */
347
    public function setHttpClient(HttpClient $client)
348
    {
349
        $this->getRequestManager()->setHttpClient($client);
350
351
        return $this;
352
    }
353
354
    /**
355
     * {@inheritdoc}
356
     */
357
    public function setHttpMessageFactory(MessageFactory $factory)
358
    {
359
        $this->getRequestManager()->setMessageFactory($factory);
360
361
        return $this;
362
    }
363
364
    /**
365
     * @return RequestManager
366
     */
367
    protected function getRequestManager()
368
    {
369
        return $this->requestManager;
370
    }
371
372
    /**
373
     * @return Authenticator
374
     */
375
    protected function getAuthenticator()
376
    {
377
        return $this->authenticator;
378
    }
379
}
380