From 3c298ed1bd92c0a01c3a21b31562ba6d59edb175 Mon Sep 17 00:00:00 2001 From: andyvanee <1andyvanee@gmail.com> Date: Wed, 9 May 2018 13:03:38 -0600 Subject: [PATCH 1/4] Responses are ResultSet objects which extend ArrayObject ResultSet objects provide access to the original request as well as the total and totalPages headers supplied by the REST API. --- specs/Endpoint/abstract-wp-endpoint.spec.php | 45 ++++++++++++-- src/Endpoint/AbstractWpEndpoint.php | 12 ++-- src/Endpoint/ResultSet.php | 62 ++++++++++++++++++++ 3 files changed, 109 insertions(+), 10 deletions(-) create mode 100644 src/Endpoint/ResultSet.php diff --git a/specs/Endpoint/abstract-wp-endpoint.spec.php b/specs/Endpoint/abstract-wp-endpoint.spec.php index 11c82c7..aea8d09 100644 --- a/specs/Endpoint/abstract-wp-endpoint.spec.php +++ b/specs/Endpoint/abstract-wp-endpoint.spec.php @@ -17,7 +17,7 @@ $endpoint = new FakeEndpoint($client->reveal()); $data = $endpoint->get(55); - expect($data)->to->equal(['foo' => 'bar']); + expect($data['foo'])->to->equal('bar'); }); it('should make a GET request without any ID', function () { @@ -31,7 +31,7 @@ $endpoint = new FakeEndpoint($client->reveal()); $data = $endpoint->get(); - expect($data)->to->equal(['foo' => 'bar']); + expect($data['foo'])->to->equal('bar'); }); it('should make a GET request with parameters', function () { @@ -45,9 +45,46 @@ $endpoint = new FakeEndpoint($client->reveal()); $data = $endpoint->get(null, ['bar'=>'baz']); - expect($data)->to->equal(['foo' => 'bar']); + expect($data['foo'])->to->equal('bar'); }); + it('should expose WP-Total headers', function () { + $client = $this->getProphet()->prophesize(WpClient::class); + + $request = new Request('GET', '/foo/55'); + + $headers = [ + 'Content-Type' => 'application/json', + 'X-WP-Total' => 1, + 'X-WP-TotalPages' => 2, + ]; + + $response = new \GuzzleHttp\Psr7\Response(200, $headers, '{"foo": "bar"}'); + + $client->send($request)->willReturn($response)->shouldBeCalled(); + + $endpoint = new FakeEndpoint($client->reveal()); + + $data = $endpoint->get(55); + + expect($data->total)->to->equal(1); + expect($data->totalPages)->to->equal(2); + }); + + it('should include original request', function () { + $client = $this->getProphet()->prophesize(WpClient::class); + + $request = new Request('GET', '/foo/55'); + $response = new \GuzzleHttp\Psr7\Response(200, [], '{"foo": "bar"}'); + + $client->send($request)->willReturn($response)->shouldBeCalled(); + + $endpoint = new FakeEndpoint($client->reveal()); + + $data = $endpoint->get(55); + + expect($data->request->getUri()->getPath())->to->equal('/foo/55'); + }); }); describe('save()', function () { @@ -59,7 +96,7 @@ $endpoint = new FakeEndpoint($client->reveal()); $data = $endpoint->save(['foo' => 'bar']); - expect($data)->to->equal(['foo' => 'bar']); + expect($data['foo'])->to->equal('bar'); }); }); diff --git a/src/Endpoint/AbstractWpEndpoint.php b/src/Endpoint/AbstractWpEndpoint.php index d1664b6..0b7c327 100644 --- a/src/Endpoint/AbstractWpEndpoint.php +++ b/src/Endpoint/AbstractWpEndpoint.php @@ -42,10 +42,10 @@ public function get($id = null, array $params = null) $request = new Request('GET', $uri); $response = $this->client->send($request); + $results = new ResultSet($request, $response); - if ($response->hasHeader('Content-Type') - && substr($response->getHeader('Content-Type')[0], 0, 16) === 'application/json') { - return json_decode($response->getBody()->getContents(), true); + if (count($results)) { + return $results; } throw new RuntimeException('Unexpected response'); @@ -66,10 +66,10 @@ public function save(array $data) $request = new Request('POST', $url, ['Content-Type' => 'application/json'], json_encode($data)); $response = $this->client->send($request); + $results = new ResultSet($request, $response); - if ($response->hasHeader('Content-Type') - && substr($response->getHeader('Content-Type')[0], 0, 16) === 'application/json') { - return json_decode($response->getBody()->getContents(), true); + if (count($results)) { + return $results; } throw new RuntimeException('Unexpected response'); diff --git a/src/Endpoint/ResultSet.php b/src/Endpoint/ResultSet.php new file mode 100644 index 0000000..d2c8173 --- /dev/null +++ b/src/Endpoint/ResultSet.php @@ -0,0 +1,62 @@ +request = $request; + + if ($this->validateResponse($response)) { + parent::__construct(json_decode($response->getBody()->getContents(), true)); + $this->setHeaders($response); + } + } + + private function setHeaders(ResponseInterface &$response) + { + if ($response->hasHeader('X-WP-Total')) { + $this->total = (int) $response->getHeader('X-WP-Total')[0]; + } + + if ($response->hasHeader('X-WP-TotalPages')) { + $this->totalPages = (int) $response->getHeader('X-WP-TotalPages')[0]; + } + } + + private function validateResponse(ResponseInterface &$response) + { + return ( + $response->hasHeader('Content-Type') && + substr($response->getHeader('Content-Type')[0], 0, 16) === 'application/json'); + } +} From 097c0f90caf68e67a8ae2ebf1fb08aa4bb6d98dd Mon Sep 17 00:00:00 2001 From: andyvanee <1andyvanee@gmail.com> Date: Wed, 9 May 2018 14:22:55 -0600 Subject: [PATCH 2/4] Fix failing test --- specs/Endpoint/abstract-wp-endpoint.spec.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/Endpoint/abstract-wp-endpoint.spec.php b/specs/Endpoint/abstract-wp-endpoint.spec.php index aea8d09..a1c7d5e 100644 --- a/specs/Endpoint/abstract-wp-endpoint.spec.php +++ b/specs/Endpoint/abstract-wp-endpoint.spec.php @@ -75,7 +75,7 @@ $client = $this->getProphet()->prophesize(WpClient::class); $request = new Request('GET', '/foo/55'); - $response = new \GuzzleHttp\Psr7\Response(200, [], '{"foo": "bar"}'); + $response = new \GuzzleHttp\Psr7\Response(200, ['Content-Type' => 'application/json'], '{"foo": "bar"}'); $client->send($request)->willReturn($response)->shouldBeCalled(); From 7a5a086be801574ae50d1f8388189ea0c1c0cdfa Mon Sep 17 00:00:00 2001 From: Oleksandr Chernyi Date: Fri, 1 Jun 2018 23:55:32 +0300 Subject: [PATCH 3/4] Added possibility to use WP.Com publick API. --- src/Endpoint/AbstractWpEndpoint.php | 29 +++++++++++++--------- src/Endpoint/Categories.php | 2 +- src/Endpoint/Comments.php | 2 +- src/Endpoint/Media.php | 2 +- src/Endpoint/Pages.php | 2 +- src/Endpoint/PostStatuses.php | 2 +- src/Endpoint/PostTypes.php | 2 +- src/Endpoint/Posts.php | 2 +- src/Endpoint/ResultSet.php | 2 +- src/Endpoint/Tags.php | 2 +- src/Endpoint/Users.php | 2 +- src/WpClient.php | 38 +++++++++++++++++++++++++---- 12 files changed, 60 insertions(+), 27 deletions(-) diff --git a/src/Endpoint/AbstractWpEndpoint.php b/src/Endpoint/AbstractWpEndpoint.php index 0b7c327..f64c31c 100644 --- a/src/Endpoint/AbstractWpEndpoint.php +++ b/src/Endpoint/AbstractWpEndpoint.php @@ -17,6 +17,11 @@ abstract class AbstractWpEndpoint */ private $client; + /** + * @var bool + */ + private $public; + /** * Users constructor. * @param WpClient $client @@ -24,6 +29,7 @@ abstract class AbstractWpEndpoint public function __construct(WpClient $client) { $this->client = $client; + $this->public = $client->isPublic(); } abstract protected function getEndpoint(); @@ -40,15 +46,7 @@ public function get($id = null, array $params = null) $uri .= (is_null($id)?'': '/' . $id); $uri .= (is_null($params)?'': '?' . http_build_query($params)); - $request = new Request('GET', $uri); - $response = $this->client->send($request); - $results = new ResultSet($request, $response); - - if (count($results)) { - return $results; - } - - throw new RuntimeException('Unexpected response'); + return $this->sendRequest(new Request('GET', $uri)); } /** @@ -64,12 +62,19 @@ public function save(array $data) unset($data['id']); } - $request = new Request('POST', $url, ['Content-Type' => 'application/json'], json_encode($data)); + return $this->sendRequest(new Request('POST', $url, ['Content-Type' => 'application/json'], json_encode($data))); + } + + /** + * @param \GuzzleHttp\Psr7\Request $request + * @return array + */ + public function sendRequest(Request $request) { $response = $this->client->send($request); $results = new ResultSet($request, $response); - if (count($results)) { - return $results; + if (count($results)) { + return $results; } throw new RuntimeException('Unexpected response'); diff --git a/src/Endpoint/Categories.php b/src/Endpoint/Categories.php index 607d468..6077059 100644 --- a/src/Endpoint/Categories.php +++ b/src/Endpoint/Categories.php @@ -13,6 +13,6 @@ class Categories extends AbstractWpEndpoint */ protected function getEndpoint() { - return '/wp-json/wp/v2/categories'; + return '/categories'; } } diff --git a/src/Endpoint/Comments.php b/src/Endpoint/Comments.php index 611e4fe..fb66bfa 100644 --- a/src/Endpoint/Comments.php +++ b/src/Endpoint/Comments.php @@ -13,6 +13,6 @@ class Comments extends AbstractWpEndpoint */ protected function getEndpoint() { - return '/wp-json/wp/v2/comments'; + return '/comments'; } } diff --git a/src/Endpoint/Media.php b/src/Endpoint/Media.php index 6647ffd..04d86e7 100644 --- a/src/Endpoint/Media.php +++ b/src/Endpoint/Media.php @@ -13,6 +13,6 @@ class Media extends AbstractWpEndpoint */ protected function getEndpoint() { - return '/wp-json/wp/v2/media'; + return '/media'; } } diff --git a/src/Endpoint/Pages.php b/src/Endpoint/Pages.php index ac2f823..4386eee 100644 --- a/src/Endpoint/Pages.php +++ b/src/Endpoint/Pages.php @@ -13,6 +13,6 @@ class Pages extends AbstractWpEndpoint */ protected function getEndpoint() { - return '/wp-json/wp/v2/pages'; + return '/pages'; } } diff --git a/src/Endpoint/PostStatuses.php b/src/Endpoint/PostStatuses.php index 8e70d73..338afa4 100644 --- a/src/Endpoint/PostStatuses.php +++ b/src/Endpoint/PostStatuses.php @@ -13,6 +13,6 @@ class PostStatuses extends AbstractWpEndpoint */ protected function getEndpoint() { - return '/wp-json/wp/v2/statuses'; + return '/statuses'; } } diff --git a/src/Endpoint/PostTypes.php b/src/Endpoint/PostTypes.php index 907347c..c0762bb 100644 --- a/src/Endpoint/PostTypes.php +++ b/src/Endpoint/PostTypes.php @@ -13,6 +13,6 @@ class PostTypes extends AbstractWpEndpoint */ protected function getEndpoint() { - return '/wp-json/wp/v2/types'; + return '/types'; } } diff --git a/src/Endpoint/Posts.php b/src/Endpoint/Posts.php index 7bcc94b..f676af0 100644 --- a/src/Endpoint/Posts.php +++ b/src/Endpoint/Posts.php @@ -13,6 +13,6 @@ class Posts extends AbstractWpEndpoint */ protected function getEndpoint() { - return '/wp-json/wp/v2/posts'; + return '/posts'; } } diff --git a/src/Endpoint/ResultSet.php b/src/Endpoint/ResultSet.php index d2c8173..6eabe3f 100644 --- a/src/Endpoint/ResultSet.php +++ b/src/Endpoint/ResultSet.php @@ -23,7 +23,7 @@ class ResultSet extends ArrayObject public $totalPages = 0; /** - * @var Psr\Http\Message\RequestInterface + * @var \Psr\Http\Message\RequestInterface */ public $request; diff --git a/src/Endpoint/Tags.php b/src/Endpoint/Tags.php index 8edd362..86e90c2 100644 --- a/src/Endpoint/Tags.php +++ b/src/Endpoint/Tags.php @@ -13,6 +13,6 @@ class Tags extends AbstractWpEndpoint */ protected function getEndpoint() { - return '/wp-json/wp/v2/tags'; + return '/tags'; } } diff --git a/src/Endpoint/Users.php b/src/Endpoint/Users.php index f007458..0d2e34b 100644 --- a/src/Endpoint/Users.php +++ b/src/Endpoint/Users.php @@ -13,6 +13,6 @@ class Users extends AbstractWpEndpoint */ protected function getEndpoint() { - return '/wp-json/wp/v2/users'; + return '/users'; } } diff --git a/src/WpClient.php b/src/WpClient.php index c35ebe0..7e78fc1 100644 --- a/src/WpClient.php +++ b/src/WpClient.php @@ -45,15 +45,22 @@ class WpClient */ private $endPoints = []; + /** + * @var bool + */ + private $public; + /** * WpClient constructor. * @param ClientInterface $httpClient * @param string $wordpressUrl + * @param bool $public */ - public function __construct(ClientInterface $httpClient, $wordpressUrl = '') + public function __construct(ClientInterface $httpClient, $wordpressUrl = '', $public = FALSE) { $this->httpClient = $httpClient; $this->wordpressUrl = $wordpressUrl; + $this->public = $public; } /** @@ -72,6 +79,22 @@ public function setCredentials(AuthInterface $auth) $this->credentials = $auth; } + /** + * @param bool + */ + public function setPublic($public = TRUE) + { + $this->public = $public; + } + + /** + * @return bool + */ + public function isPublic() + { + return (bool) $this->public; + } + /** * @param $endpoint * @param array $args @@ -100,10 +123,15 @@ public function send(RequestInterface $request) if ($this->credentials) { $request = $this->credentials->addCredentials($request); } - - $request = $request->withUri( - $this->httpClient->makeUri($this->wordpressUrl . $request->getUri()) - ); + if ($this->isPublic()) { + $raw_uri = $this->httpClient->makeUri($this->wordpressUrl); + $public_uri = 'https://public-api.wordpress.com/wp/v2/sites/' . $raw_uri->getHost(); + $uri = $this->httpClient->makeUri($public_uri . $request->getUri()); + } + else { + $uri = $this->httpClient->makeUri( $this->wordpressUrl . '/wp-json/wp/v2' . $request->getUri()); + } + $request = $request->withUri($uri); return $this->httpClient->send($request); } From b89218006ddb96ef6272cd772bbc9ec0824c3d17 Mon Sep 17 00:00:00 2001 From: Oleksandr Chernyi Date: Sat, 2 Jun 2018 02:07:39 +0300 Subject: [PATCH 4/4] Refactored composer.json --- composer.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 7499943..9a9e1c3 100644 --- a/composer.json +++ b/composer.json @@ -1,10 +1,6 @@ { "name": "vnn/wordpress-rest-api-client", - "autoload": { - "psr-4": { - "Vnn\\WpApiClient\\": "src/" - } - }, + "license": "MIT", "require": { "php": ">= 5.6, <= 8.0", "psr/http-message": "^1.0" @@ -18,5 +14,10 @@ }, "suggest": { "guzzlehttp/guzzle": "^6.2" + }, + "autoload": { + "psr-4": { + "Vnn\\WpApiClient\\": "src/" + } } }