Completed
Push — master ( b65b29...f39982 )
by Tobias
03:16 queued 01:01
created

LinkedIn::api()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 27
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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