Completed
Push — master ( 44e9c6...5609e7 )
by Michael
06:24
created

Client::createHeader()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 1
1
<?php
2
/**
3
 * Part of the Joomla Framework OAuth1 Package
4
 *
5
 * @copyright  Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
6
 * @license    GNU General Public License version 2 or later; see LICENSE
7
 */
8
9
namespace Joomla\Oauth1;
10
11
use Joomla\Http\Http;
12
use Joomla\Input\Input;
13
use Joomla\Application\AbstractWebApplication;
14
15
/**
16
 * Joomla Framework class for interacting with an OAuth 1.0 and 1.0a server.
17
 *
18
 * @since  1.0
19
 */
20
abstract class Client
21
{
22
	/**
23
	 * @var    array  Options for the Client object.
24
	 * @since  1.0
25
	 */
26
	protected $options;
27
28
	/**
29
	 * @var    array  Contains access token key, secret and verifier.
30
	 * @since  1.0
31
	 */
32
	protected $token = array();
33
34
	/**
35
	 * @var    Http  The HTTP client object to use in sending HTTP requests.
36
	 * @since  1.0
37
	 */
38
	protected $client;
39
40
	/**
41
	 * @var    Input The input object to use in retrieving GET/POST data.
42
	 * @since  1.0
43
	 */
44
	protected $input;
45
46
	/**
47
	 * @var    AbstractWebApplication  The application object to send HTTP headers for redirects.
48
	 * @since  1.0
49
	 */
50
	protected $application;
51
52
	/**
53
	 * @var    string  Selects which version of OAuth to use: 1.0 or 1.0a.
54
	 * @since  1.0
55
	 */
56
	protected $version;
57
58
	/**
59
	 * Constructor.
60
	 *
61
	 * @param   array                   $options      OAuth1 Client options array.
62
	 * @param   Http                    $client       The HTTP client object.
63
	 * @param   Input                   $input        The input object
64
	 * @param   AbstractWebApplication  $application  The application object
65
	 * @param   string                  $version      Specify the OAuth version. By default we are using 1.0a.
66
	 *
67
	 * @since   1.0
68
	 */
69
	public function __construct($options = array(), Http $client, Input $input, AbstractWebApplication $application, $version = '1.0a')
70
	{
71
		$this->options = $options;
72
		$this->client = $client;
73
		$this->input = $input;
74
		$this->application = $application;
75
		$this->version = $version;
76
	}
77
78
	/**
79
	 * Method to form the oauth flow.
80
	 *
81
	 * @return  string  The access token.
82
	 *
83
	 * @since   1.0
84
	 * @throws  \DomainException
85
	 */
86
	public function authenticate()
87
	{
88
		// Already got some credentials stored?
89
		if ($this->token)
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->token of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
90
		{
91
			$response = $this->verifyCredentials();
92
93
			if ($response)
0 ignored issues
show
Bug Best Practice introduced by
The expression $response of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
94
			{
95
				return $this->token;
96
			}
97
			else
98
			{
99
				$this->token = null;
0 ignored issues
show
Documentation Bug introduced by
It seems like null of type null is incompatible with the declared type array of property $token.

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...
100
			}
101
		}
102
103
		// Check for callback.
104
		if (strcmp($this->version, '1.0a') === 0)
105
		{
106
			$verifier = $this->input->get('oauth_verifier');
107
		}
108
		else
109
		{
110
			$verifier = $this->input->get('oauth_token');
111
		}
112
113
		if (empty($verifier))
114
		{
115
			// Generate a request token.
116
			$this->generateRequestToken();
117
118
			// Authenticate the user and authorise the app.
119
			$this->authorise();
120
		}
121
122
		// Callback
123
		else
124
		{
125
			$session = $this->application->getSession();
126
127
			// Get token form session.
128
			$this->token = array('key' => $session->get('oauth_token.key', null), 'secret' => $session->get('oauth_token.secret', null));
129
130
			// Verify the returned request token.
131
			if (strcmp($this->token['key'], $this->input->get('oauth_token')) !== 0)
132
			{
133
				throw new \DomainException('Bad session!');
134
			}
135
136
			// Set token verifier for 1.0a.
137
			if (strcmp($this->version, '1.0a') === 0)
138
			{
139
				$this->token['verifier'] = $this->input->get('oauth_verifier');
140
			}
141
142
			// Generate access token.
143
			$this->generateAccessToken();
144
145
			// Return the access token.
146
			return $this->token;
147
		}
148
	}
149
150
	/**
151
	 * Method used to get a request token.
152
	 *
153
	 * @return  void
154
	 *
155
	 * @since   __DEPLOY_VERSION__
156
	 * @throws  \DomainException
157
	 */
158
	private function generateRequestToken()
159
	{
160
		// Set the callback URL.
161
		if ($this->getOption('callback'))
162
		{
163
			$parameters = array(
164
				'oauth_callback' => $this->getOption('callback')
165
			);
166
		}
167
		else
168
		{
169
			$parameters = array();
170
		}
171
172
		// Make an OAuth request for the Request Token.
173
		$response = $this->oauthRequest($this->getOption('requestTokenURL'), 'POST', $parameters);
174
175
		parse_str($response->body, $params);
176
177
		if (strcmp($this->version, '1.0a') === 0 && strcmp($params['oauth_callback_confirmed'], 'true') !== 0)
178
		{
179
			throw new \DomainException('Bad request token!');
180
		}
181
182
		// Save the request token.
183
		$this->token = array('key' => $params['oauth_token'], 'secret' => $params['oauth_token_secret']);
184
185
		// Save the request token in session
186
		$session = $this->application->getSession();
187
		$session->set('oauth_token.key', $this->token['key']);
188
		$session->set('oauth_token.secret', $this->token['secret']);
189
	}
190
191
	/**
192
	 * Method used to authorise the application.
193
	 *
194
	 * @return  void
195
	 *
196
	 * @since   __DEPLOY_VERSION__
197
	 */
198
	private function authorise()
199
	{
200
		$url = $this->getOption('authoriseURL') . '?oauth_token=' . $this->token['key'];
201
202
		if ($this->getOption('scope'))
203
		{
204
			$scope = is_array($this->getOption('scope')) ? implode(' ', $this->getOption('scope')) : $this->getOption('scope');
205
			$url .= '&scope=' . urlencode($scope);
206
		}
207
208
		if ($this->getOption('sendheaders'))
209
		{
210
			$this->application->redirect($url);
211
		}
212
	}
213
214
	/**
215
	 * Method used to get an access token.
216
	 *
217
	 * @return  void
218
	 *
219
	 * @since   __DEPLOY_VERSION__
220
	 */
221
	private function generateAccessToken()
222
	{
223
		// Set the parameters.
224
		$parameters = array(
225
			'oauth_token' => $this->token['key']
226
		);
227
228
		if (strcmp($this->version, '1.0a') === 0)
229
		{
230
			$parameters = array_merge($parameters, array('oauth_verifier' => $this->token['verifier']));
231
		}
232
233
		// Make an OAuth request for the Access Token.
234
		$response = $this->oauthRequest($this->getOption('accessTokenURL'), 'POST', $parameters);
235
236
		parse_str($response->body, $params);
237
238
		// Save the access token.
239
		$this->token = array('key' => $params['oauth_token'], 'secret' => $params['oauth_token_secret']);
240
	}
241
242
	/**
243
	 * Method used to make an OAuth request.
244
	 *
245
	 * @param   string  $url         The request URL.
246
	 * @param   string  $method      The request method.
247
	 * @param   array   $parameters  Array containing request parameters.
248
	 * @param   mixed   $data        The POST request data.
249
	 * @param   array   $headers     An array of name-value pairs to include in the header of the request
250
	 *
251
	 * @return  object  The Response object.
252
	 *
253
	 * @since   1.0
254
	 * @throws  \DomainException
255
	 */
256
	public function oauthRequest($url, $method, $parameters, $data = array(), $headers = array())
257
	{
258
		// Set the parameters.
259
		$defaults = array(
260
			'oauth_consumer_key' => $this->getOption('consumer_key'),
261
			'oauth_signature_method' => 'HMAC-SHA1',
262
			'oauth_version' => '1.0',
263
			'oauth_nonce' => $this->generateNonce(),
264
			'oauth_timestamp' => time()
265
		);
266
267
		$parameters = array_merge($parameters, $defaults);
268
269
		// Do not encode multipart parameters. Do not include $data in the signature if $data is not array.
270
		if (isset($headers['Content-Type']) && strpos($headers['Content-Type'], 'multipart/form-data') !== false || !is_array($data))
271
		{
272
			$oauthHeaders = $parameters;
273
		}
274
		else
275
		{
276
			// Use all parameters for the signature.
277
			$oauthHeaders = array_merge($parameters, $data);
278
		}
279
280
		// Sign the request.
281
		$oauthHeaders = $this->signRequest($url, $method, $oauthHeaders);
282
283
		// Get parameters for the Authorisation header.
284
		if (is_array($data))
285
		{
286
			$oauthHeaders = array_diff_key($oauthHeaders, $data);
287
		}
288
289
		// Send the request.
290
		switch ($method)
291
		{
292 View Code Duplication
			case 'GET':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
293
				$url = $this->toUrl($url, $data);
294
				$response = $this->client->get($url, array('Authorization' => $this->createHeader($oauthHeaders)));
295
				break;
296 View Code Duplication
			case 'POST':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
297
				$headers = array_merge($headers, array('Authorization' => $this->createHeader($oauthHeaders)));
298
				$response = $this->client->post($url, $data, $headers);
299
				break;
300 View Code Duplication
			case 'PUT':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
301
				$headers = array_merge($headers, array('Authorization' => $this->createHeader($oauthHeaders)));
302
				$response = $this->client->put($url, $data, $headers);
303
				break;
304 View Code Duplication
			case 'DELETE':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
305
				$headers = array_merge($headers, array('Authorization' => $this->createHeader($oauthHeaders)));
306
				$response = $this->client->delete($url, $headers);
307
				break;
308
		}
309
310
		// Validate the response code.
311
		$this->validateResponse($url, $response);
0 ignored issues
show
Bug introduced by
The variable $response 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...
Documentation introduced by
$response is of type object<Joomla\Http\Response>, but the function expects a object<Joomla\Oauth1\Response>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
312
313
		return $response;
314
	}
315
316
	/**
317
	 * Method to validate a response.
318
	 *
319
	 * @param   string    $url       The request URL.
320
	 * @param   Response  $response  The response to validate.
321
	 *
322
	 * @return  void
323
	 *
324
	 * @since   1.0
325
	 * @throws  \DomainException
326
	 */
327
	abstract public function validateResponse($url, $response);
328
329
	/**
330
	 * Method used to create the header for the POST request.
331
	 *
332
	 * @param   array  $parameters  Array containing request parameters.
333
	 *
334
	 * @return  string  The header.
335
	 *
336
	 * @since   __DEPLOY_VERSION__
337
	 */
338
	private function createHeader($parameters)
339
	{
340
		$header = 'OAuth ';
341
342
		foreach ($parameters as $key => $value)
343
		{
344
			if (!strcmp($header, 'OAuth '))
345
			{
346
				$header .= $key . '="' . $this->safeEncode($value) . '"';
347
			}
348
			else
349
			{
350
				$header .= ', ' . $key . '="' . $value . '"';
351
			}
352
		}
353
354
		return $header;
355
	}
356
357
	/**
358
	 * Method to create the URL formed string with the parameters.
359
	 *
360
	 * @param   string  $url         The request URL.
361
	 * @param   array   $parameters  Array containing request parameters.
362
	 *
363
	 * @return  string  The formed URL.
364
	 *
365
	 * @since   1.0
366
	 */
367
	public function toUrl($url, $parameters)
368
	{
369
		foreach ($parameters as $key => $value)
370
		{
371
			if (is_array($value))
372
			{
373
				foreach ($value as $k => $v)
374
				{
375
					if (strpos($url, '?') === false)
376
					{
377
						$url .= '?' . $key . '=' . $v;
378
					}
379
					else
380
					{
381
						$url .= '&' . $key . '=' . $v;
382
					}
383
				}
384
			}
385
			else
386
			{
387
				if (strpos($value, ' ') !== false)
388
				{
389
					$value = $this->safeEncode($value);
390
				}
391
392
				if (strpos($url, '?') === false)
393
				{
394
					$url .= '?' . $key . '=' . $value;
395
				}
396
				else
397
				{
398
					$url .= '&' . $key . '=' . $value;
399
				}
400
			}
401
		}
402
403
		return $url;
404
	}
405
406
	/**
407
	 * Method used to sign requests.
408
	 *
409
	 * @param   string  $url         The URL to sign.
410
	 * @param   string  $method      The request method.
411
	 * @param   array   $parameters  Array containing request parameters.
412
	 *
413
	 * @return  array  The array containing the request parameters, including signature.
414
	 *
415
	 * @since   __DEPLOY_VERSION__
416
	 */
417
	private function signRequest($url, $method, $parameters)
418
	{
419
		// Create the signature base string.
420
		$base = $this->baseString($url, $method, $parameters);
421
422
		$parameters['oauth_signature'] = $this->safeEncode(
423
			base64_encode(
424
				hash_hmac('sha1', $base, $this->prepareSigningKey(), true)
425
			)
426
		);
427
428
		return $parameters;
429
	}
430
431
	/**
432
	 * Prepare the signature base string.
433
	 *
434
	 * @param   string  $url         The URL to sign.
435
	 * @param   string  $method      The request method.
436
	 * @param   array   $parameters  Array containing request parameters.
437
	 *
438
	 * @return  string  The base string.
439
	 *
440
	 * @since   __DEPLOY_VERSION__
441
	 */
442
	private function baseString($url, $method, $parameters)
443
	{
444
		// Sort the parameters alphabetically
445
		uksort($parameters, 'strcmp');
446
447
		// Encode parameters.
448
		foreach ($parameters as $key => $value)
449
		{
450
			$key = $this->safeEncode($key);
451
452
			if (is_array($value))
453
			{
454
				foreach ($value as $k => $v)
455
				{
456
					$v = $this->safeEncode($v);
457
					$kv[] = "{$key}={$v}";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$kv was never initialized. Although not strictly required by PHP, it is generally a good practice to add $kv = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
458
				}
459
			}
460
			else
461
			{
462
				$value = $this->safeEncode($value);
463
				$kv[] = "{$key}={$value}";
0 ignored issues
show
Bug introduced by
The variable $kv 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...
464
			}
465
		}
466
467
		// Form the parameter string.
468
		$params = implode('&', $kv);
469
470
		// Signature base string elements.
471
		$base = array(
472
			$method,
473
			$url,
474
			$params
475
			);
476
477
		// Return the base string.
478
		return implode('&', $this->safeEncode($base));
479
	}
480
481
	/**
482
	 * Encodes the string or array passed in a way compatible with OAuth.
483
	 * If an array is passed each array value will will be encoded.
484
	 *
485
	 * @param   mixed  $data  The scalar or array to encode.
486
	 *
487
	 * @return  string  $data encoded in a way compatible with OAuth.
488
	 *
489
	 * @since   1.0
490
	 */
491
	public function safeEncode($data)
492
	{
493
		if (is_array($data))
494
		{
495
			return array_map(array($this, 'safeEncode'), $data);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return array_map(array($... 'safeEncode'), $data); (array) is incompatible with the return type documented by Joomla\Oauth1\Client::safeEncode of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
496
		}
497
498
		if (is_scalar($data))
499
		{
500
			return str_ireplace(
501
				array('+', '%7E'),
502
				array(' ', '~'),
503
				rawurlencode($data)
504
			);
505
		}
506
507
		return '';
508
	}
509
510
	/**
511
	 * Method used to generate the current nonce.
512
	 *
513
	 * @return  string  The current nonce.
514
	 *
515
	 * @since   1.0
516
	 */
517
	public static function generateNonce()
518
	{
519
		$mt = microtime();
520
		$rand = random_bytes(16);
521
522
		// The md5s look nicer than numbers.
523
		return md5($mt . $rand);
524
	}
525
526
	/**
527
	 * Prepares the OAuth signing key.
528
	 *
529
	 * @return  string  The prepared signing key.
530
	 *
531
	 * @since   __DEPLOY_VERSION__
532
	 */
533
	private function prepareSigningKey()
534
	{
535
		return $this->safeEncode($this->getOption('consumer_secret')) . '&' . $this->safeEncode(($this->token) ? $this->token['secret'] : '');
536
	}
537
538
	/**
539
	 * Returns an HTTP 200 OK response code and a representation of the requesting user if authentication was successful;
540
	 * returns a 401 status code and an error message if not.
541
	 *
542
	 * @return  array  The decoded JSON response
543
	 *
544
	 * @since   1.0
545
	 */
546
	abstract public function verifyCredentials();
547
548
	/**
549
	 * Get an option from the OAuth1 Client instance.
550
	 *
551
	 * @param   string  $key  The name of the option to get
552
	 *
553
	 * @return  mixed  The option value
554
	 *
555
	 * @since   1.0
556
	 */
557
	public function getOption($key)
558
	{
559
		return isset($this->options[$key]) ? $this->options[$key] : null;
560
	}
561
562
	/**
563
	 * Set an option for the OAuth1 Client instance.
564
	 *
565
	 * @param   string  $key    The name of the option to set
566
	 * @param   mixed   $value  The option value to set
567
	 *
568
	 * @return  Client  This object for method chaining
569
	 *
570
	 * @since   1.0
571
	 */
572
	public function setOption($key, $value)
573
	{
574
		$this->options[$key] = $value;
575
576
		return $this;
577
	}
578
579
	/**
580
	 * Get the oauth token key or secret.
581
	 *
582
	 * @return  array  The oauth token key and secret.
583
	 *
584
	 * @since   1.0
585
	 */
586
	public function getToken()
587
	{
588
		return $this->token;
589
	}
590
591
	/**
592
	 * Set the oauth token.
593
	 *
594
	 * @param   array  $token  The access token key and secret.
595
	 *
596
	 * @return  Client  This object for method chaining.
597
	 *
598
	 * @since   1.0
599
	 */
600
	public function setToken($token)
601
	{
602
		$this->token = $token;
603
604
		return $this;
605
	}
606
}
607