Skip to content
This repository was archived by the owner on Mar 23, 2024. It is now read-only.

Commit d5f2526

Browse files
committed
🚿 abstract query build/parse/merge
1 parent cf021db commit d5f2526

File tree

3 files changed

+51
-33
lines changed

3 files changed

+51
-33
lines changed

src/Core/OAuth1Provider.php

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@
1212

1313
namespace chillerlan\OAuth\Core;
1414

15-
use chillerlan\HTTP\Utils\Query;
16-
use DateTime;
1715
use Psr\Http\Message\{RequestInterface, ResponseInterface, UriInterface};
1816

19-
use function array_merge, base64_encode, bin2hex, function_exists, hash_hmac,
20-
implode, in_array, is_array, parse_url, random_bytes, strtoupper;
21-
use function chillerlan\HTTP\Utils\{decompress_content, r_rawurlencode};
17+
use function array_map, array_merge, base64_encode, bin2hex, function_exists, hash_hmac,
18+
implode, in_array, is_array, random_bytes, strtoupper, time;
19+
use function chillerlan\HTTP\Utils\{decompress_content, parseUrl};
2220

2321
/**
2422
* Implements an abstract OAuth1 provider with all methods required by the OAuth1Interface.
@@ -36,7 +34,7 @@ abstract class OAuth1Provider extends OAuthProvider implements OAuth1Interface{
3634
public function getAuthURL(array $params = null):UriInterface{
3735
$params = array_merge($params ?? [], ['oauth_token' => $this->getRequestToken()->accessToken]);
3836

39-
return $this->uriFactory->createUri(Query::merge($this->authURL, $params));
37+
return $this->uriFactory->createUri($this->mergeQuery($this->authURL, $params));
4038
}
4139

4240
/**
@@ -49,15 +47,15 @@ public function getRequestToken():AccessToken{
4947
'oauth_consumer_key' => $this->options->key,
5048
'oauth_nonce' => $this->nonce(),
5149
'oauth_signature_method' => 'HMAC-SHA1',
52-
'oauth_timestamp' => (new DateTime)->format('U'),
50+
'oauth_timestamp' => time(),
5351
'oauth_version' => '1.0',
5452
];
5553

5654
$params['oauth_signature'] = $this->getSignature($this->requestTokenURL, $params, 'POST');
5755

5856
$request = $this->requestFactory
5957
->createRequest('POST', $this->requestTokenURL)
60-
->withHeader('Authorization', 'OAuth '.Query::build($params, null, ', ', '"'))
58+
->withHeader('Authorization', 'OAuth '.$this->buildQuery($params, null, ', ', '"'))
6159
->withHeader('Accept-Encoding', 'identity')
6260
->withHeader('Content-Length', '0') // tumblr requires a content-length header set
6361
;
@@ -81,7 +79,7 @@ public function getRequestToken():AccessToken{
8179
* @throws \chillerlan\OAuth\Core\ProviderException
8280
*/
8381
protected function parseTokenResponse(ResponseInterface $response, bool $checkCallbackConfirmed = null):AccessToken{
84-
$data = Query::parse(decompress_content($response));
82+
$data = $this->parseQuery(decompress_content($response));
8583

8684
if(!$data || !is_array($data)){
8785
throw new ProviderException('unable to parse token response');
@@ -125,6 +123,7 @@ protected function nonce():string{
125123
$nonce = random_bytes(32);
126124

127125
// use the sodium extension if available
126+
/** @noinspection PhpFullyQualifiedNameUsageInspection */
128127
return function_exists('sodium_bin2hex')
129128
? \sodium_bin2hex($nonce)
130129
: bin2hex($nonce);
@@ -144,23 +143,23 @@ protected function nonce():string{
144143
* @throws \chillerlan\OAuth\Core\ProviderException
145144
*/
146145
protected function getSignature(string $url, array $params, string $method, string $accessTokenSecret = null):string{
147-
$parseURL = parse_url($url);
146+
$parseURL = parseUrl($url);
148147

149148
if(!isset($parseURL['host']) || !isset($parseURL['scheme']) || !in_array($parseURL['scheme'], ['http', 'https'], true)){
150149
throw new ProviderException('getSignature: invalid url');
151150
}
152151

153-
$query = Query::parse($parseURL['query'] ?? '');
152+
$query = $this->parseQuery($parseURL['query'] ?? '');
154153

155154
$signatureParams = array_merge($query, $params);
156155

157156
unset($signatureParams['oauth_signature']);
158157

159-
$key = implode('&', r_rawurlencode([$this->options->secret, $accessTokenSecret ?? '']));
160-
$data = r_rawurlencode([
158+
$key = implode('&', array_map('rawurlencode', [$this->options->secret, $accessTokenSecret ?? '']));
159+
$data = array_map('rawurlencode', [
161160
strtoupper($method ?? 'POST'),
162161
$parseURL['scheme'].'://'.$parseURL['host'].($parseURL['path'] ?? ''),
163-
Query::build($signatureParams),
162+
$this->buildQuery($signatureParams),
164163
]);
165164

166165
return base64_encode(hash_hmac('sha1', implode('&', $data), $key, true));
@@ -172,7 +171,7 @@ protected function getSignature(string $url, array $params, string $method, stri
172171
public function getAccessToken(string $token, string $verifier):AccessToken{
173172

174173
$request = $this->requestFactory
175-
->createRequest('POST', Query::merge($this->accessTokenURL, ['oauth_verifier' => $verifier]))
174+
->createRequest('POST', $this->mergeQuery($this->accessTokenURL, ['oauth_verifier' => $verifier]))
176175
->withHeader('Accept-Encoding', 'identity')
177176
->withHeader('Content-Length', '0')
178177
;
@@ -188,13 +187,13 @@ public function getAccessToken(string $token, string $verifier):AccessToken{
188187
public function getRequestAuthorization(RequestInterface $request, AccessToken $token):RequestInterface{
189188
$uri = $request->getUri();
190189

191-
$query = Query::parse($uri->getQuery());
190+
$query = $this->parseQuery($uri->getQuery());
192191

193192
$parameters = [
194193
'oauth_consumer_key' => $this->options->key,
195194
'oauth_nonce' => $this->nonce(),
196195
'oauth_signature_method' => 'HMAC-SHA1',
197-
'oauth_timestamp' => (new DateTime)->format('U'),
196+
'oauth_timestamp' => time(),
198197
'oauth_token' => $token->accessToken,
199198
'oauth_version' => '1.0',
200199
];
@@ -210,7 +209,7 @@ public function getRequestAuthorization(RequestInterface $request, AccessToken $
210209
$parameters['oauth_session_handle'] = $query['oauth_session_handle']; // @codeCoverageIgnore
211210
}
212211

213-
return $request->withHeader('Authorization', 'OAuth '.Query::build($parameters, null, ', ', '"'));
212+
return $request->withHeader('Authorization', 'OAuth '.$this->buildQuery($parameters, null, ', ', '"'));
214213
}
215214

216215
}

src/Core/OAuth2Provider.php

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,9 @@
1515

1616
namespace chillerlan\OAuth\Core;
1717

18-
use chillerlan\HTTP\Utils\Query;
1918
use Psr\Http\Message\{RequestInterface, ResponseInterface, UriInterface};
2019

21-
use function array_merge, base64_encode, date, hash_equals, http_build_query,
22-
implode, is_array, json_decode, random_bytes, sha1, sprintf;
20+
use function array_merge, base64_encode, date, hash_equals, implode, is_array, json_decode, random_bytes, sha1, sprintf;
2321
use function chillerlan\HTTP\Utils\decompress_content;
2422

2523
use const JSON_THROW_ON_ERROR, PHP_QUERY_RFC1738;
@@ -93,7 +91,7 @@ public function getAuthURL(array $params = null, array $scopes = null):UriInterf
9391
$params = $this->setState($params);
9492
}
9593

96-
return $this->uriFactory->createUri(Query::merge($this->authURL, $params));
94+
return $this->uriFactory->createUri($this->mergeQuery($this->authURL, $params));
9795
}
9896

9997
/**
@@ -162,7 +160,7 @@ public function getAccessToken(string $code, string $state = null):AccessToken{
162160
->createRequest('POST', $this->accessTokenURL)
163161
->withHeader('Content-Type', 'application/x-www-form-urlencoded')
164162
->withHeader('Accept-Encoding', 'identity')
165-
->withBody($this->streamFactory->createStream(http_build_query($body, '', '&', PHP_QUERY_RFC1738)));
163+
->withBody($this->streamFactory->createStream($this->buildQuery($body, PHP_QUERY_RFC1738)));
166164

167165
foreach($this->authHeaders as $header => $value){
168166
$request = $request->withHeader($header, $value);
@@ -185,7 +183,7 @@ public function getRequestAuthorization(RequestInterface $request, AccessToken $
185183
}
186184

187185
if($this->authMethod === OAuth2Interface::AUTH_METHOD_QUERY){
188-
$uri = Query::merge((string)$request->getUri(), [$this->authMethodQuery => $token->accessToken]);
186+
$uri = $this->mergeQuery((string)$request->getUri(), [$this->authMethodQuery => $token->accessToken]);
189187

190188
return $request->withUri($this->uriFactory->createUri($uri));
191189
}
@@ -220,7 +218,7 @@ public function getClientCredentialsToken(array $scopes = null):AccessToken{
220218
->withHeader('Authorization', 'Basic '.base64_encode($this->options->key.':'.$this->options->secret))
221219
->withHeader('Content-Type', 'application/x-www-form-urlencoded')
222220
->withHeader('Accept-Encoding', 'identity')
223-
->withBody($this->streamFactory->createStream(http_build_query($params, '', '&', PHP_QUERY_RFC1738)))
221+
->withBody($this->streamFactory->createStream($this->buildQuery($params, PHP_QUERY_RFC1738)))
224222
;
225223

226224
foreach($this->authHeaders as $header => $value){
@@ -274,7 +272,7 @@ public function refreshAccessToken(AccessToken $token = null):AccessToken{
274272
->createRequest('POST', $this->refreshTokenURL ?? $this->accessTokenURL)
275273
->withHeader('Content-Type', 'application/x-www-form-urlencoded')
276274
->withHeader('Accept-Encoding', 'identity')
277-
->withBody($this->streamFactory->createStream(http_build_query($body, '', '&', PHP_QUERY_RFC1738)))
275+
->withBody($this->streamFactory->createStream($this->buildQuery($body, PHP_QUERY_RFC1738)))
278276
;
279277

280278
foreach($this->authHeaders as $header => $value){

src/Core/OAuthProvider.php

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@
2525
use Psr\Log\{LoggerAwareTrait, LoggerInterface, NullLogger};
2626
use ReflectionClass;
2727

28-
use function array_slice, class_exists, count, http_build_query, implode, in_array, is_array,
29-
is_scalar, is_string, json_encode, parse_url, sprintf, strpos, strtolower;
28+
use function array_slice, class_exists, count, implode, in_array, is_array,
29+
is_scalar, is_string, json_encode, sprintf, strpos, strtolower;
3030

31+
use function chillerlan\HTTP\Utils\parseUrl;
3132
use const PHP_QUERY_RFC1738;
32-
use const PHP_URL_HOST;
3333

3434
/**
3535
* Implements an abstract OAuth provider with all methods required by the OAuthInterface.
@@ -359,6 +359,27 @@ protected function cleanBodyParams(iterable $params):array{
359359
return Query::cleanParams($params, Query::BOOLEANS_AS_BOOL, true);
360360
}
361361

362+
/**
363+
* Merges a set of parameters into the given querystring and returns the result querystring
364+
*/
365+
protected function mergeQuery(string $uri, array $query):string{
366+
return Query::merge($uri, $query);
367+
}
368+
369+
/**
370+
* Builds a query string from the given parameters
371+
*/
372+
protected function buildQuery(array $params, int $encoding = null, string $delimiter = null, string $enclosure = null):string{
373+
return Query::build($params, $encoding, $delimiter, $enclosure);
374+
}
375+
376+
/**
377+
* Parses the given querystring into an associative array
378+
*/
379+
protected function parseQuery(string $querystring, int $urlEncoding = null):array{
380+
return Query::parse($querystring, $urlEncoding);
381+
}
382+
362383
/**
363384
* @inheritDoc
364385
*/
@@ -371,7 +392,7 @@ public function request(
371392
):ResponseInterface{
372393

373394
$request = $this->requestFactory
374-
->createRequest($method ?? 'GET', Query::merge($this->getRequestTarget($path), $params ?? []));
395+
->createRequest($method ?? 'GET', $this->mergeQuery($this->getRequestTarget($path), $params ?? []));
375396

376397
foreach(array_merge($this->apiHeaders, $headers ?? []) as $header => $value){
377398
$request = $request->withAddedHeader($header, $value);
@@ -382,7 +403,7 @@ public function request(
382403

383404
if(is_array($body)){
384405
if($contentType === 'application/x-www-form-urlencoded'){
385-
$body = $this->streamFactory->createStream(http_build_query($body, '', '&', PHP_QUERY_RFC1738));
406+
$body = $this->streamFactory->createStream($this->buildQuery($body, PHP_QUERY_RFC1738));
386407
}
387408
elseif($contentType === 'application/json' || $contentType === 'application/vnd.api+json'){
388409
$body = $this->streamFactory->createStream(json_encode($body));
@@ -414,7 +435,7 @@ public function request(
414435
* @throws \chillerlan\OAuth\Core\ProviderException
415436
*/
416437
protected function getRequestTarget(string $uri):string{
417-
$parsedURL = parse_url($uri);
438+
$parsedURL = parseUrl($uri);
418439

419440
if(!isset($parsedURL['path'])){
420441
throw new ProviderException('invalid path');
@@ -424,7 +445,7 @@ protected function getRequestTarget(string $uri):string{
424445
if(isset($parsedURL['host'])){
425446

426447
// back out if it doesn't match
427-
if($parsedURL['host'] !== parse_url($this->apiURL, PHP_URL_HOST)){
448+
if($parsedURL['host'] !== parseUrl($this->apiURL)['host']){
428449
throw new ProviderException('given host does not match provider host');
429450
}
430451

0 commit comments

Comments
 (0)