diff --git a/examples/get.php b/examples/get.php index 1615346..42eab03 100644 --- a/examples/get.php +++ b/examples/get.php @@ -8,11 +8,7 @@ $client = new Client($privateApiKey, $publicApiKey); -$response = $client->get('characters', 1009351); - -$wrapper = $response->getDataWrapper(); - -$character = $wrapper->getData()->getResults()[0]; +$character = $client->characters(1009351); echo "{$character->getName()}\n"; echo "{$character->getDescription()}\n"; diff --git a/examples/get_character_by_id.php b/examples/get_character_by_id.php new file mode 100644 index 0000000..1615346 --- /dev/null +++ b/examples/get_character_by_id.php @@ -0,0 +1,23 @@ +get('characters', 1009351); + +$wrapper = $response->getDataWrapper(); + +$character = $wrapper->getData()->getResults()[0]; + +echo "{$character->getName()}\n"; +echo "{$character->getDescription()}\n"; + +foreach ($character->getEvents()->getItems() as $event) { + echo "\t{$event->getName()}\n"; +} + diff --git a/examples/search.php b/examples/search.php new file mode 100644 index 0000000..c72cbcd --- /dev/null +++ b/examples/search.php @@ -0,0 +1,16 @@ +comics(['characters' => 1009165]); + +foreach ($comics as $comic) { + echo "{$comic->getTitle()}\n"; +} diff --git a/src/Client.php b/src/Client.php index 6746743..479e79e 100644 --- a/src/Client.php +++ b/src/Client.php @@ -153,4 +153,29 @@ final private function getFromCache(RequestInterface $request) return $this->cache->get($request); } + + /** + * Allow calls such as $client->characters(); + * + * @param string $name The name of the api resource + * @param array $arguments The parameters to pass to get() or search() + * + * @return Collection|EntityInterface + */ + final public function __call($name, array $arguments) + { + $resource = strtolower($name); + $parameters = array_shift($arguments); + if ($parameters === null || is_array($parameters)) { + return new Collection($this, $resource, $parameters ?: []); + } + + $response = $this->get($resource, $parameters); + $results = $response->getDataWrapper()->getData()->getResults(); + if (empty($results)) { + return null; + } + + return $results[0]; + } } diff --git a/src/Response.php b/src/Response.php index bbf990a..6db8edb 100644 --- a/src/Response.php +++ b/src/Response.php @@ -92,7 +92,7 @@ final public function getHeaders() */ final public function getDataWrapper() { - if ($this->dataWrapper === null && $this->httpCode === 200) { + if ($this->dataWrapper === null) { $this->dataWrapper = new DataWrapper($this->body); } diff --git a/tests/Assets/ComicAdapter.php b/tests/Assets/ComicAdapter.php index 02526fe..b2db42d 100644 --- a/tests/Assets/ComicAdapter.php +++ b/tests/Assets/ComicAdapter.php @@ -29,10 +29,21 @@ final class ComicAdapter implements AdapterInterface public function send(RequestInterface $request) { $allResults = self::getAllResults(); + $total = count($allResults); $queryString = parse_url($request->getUrl(), PHP_URL_QUERY); $queryParams = []; parse_str($queryString, $queryParams); + + $path = parse_url($request->getUrl(), PHP_URL_PATH); + if (substr($path, -6) !== 'comics') { + $parts = explode('/', $request->getUrl()); + $id = array_pop($parts); + $queryParams['offset'] = $id - 1; + $queryParams['limit'] = 1; + $total = 1; + } + $this->parameters = $queryParams; $offset = (int)$queryParams['offset']; @@ -49,7 +60,7 @@ public function send(RequestInterface $request) 'data' => [ 'offset' => $offset, 'limit' => $limit, - 'total' => 5, + 'total' => $total, 'count' => $count, 'results' => $results, ], diff --git a/tests/Assets/ErrorAdapter.php b/tests/Assets/ErrorAdapter.php new file mode 100644 index 0000000..6cf1e05 --- /dev/null +++ b/tests/Assets/ErrorAdapter.php @@ -0,0 +1,54 @@ +request = $request; + + return new Response( + 404, + [ + 'code' => 'ResourceNotFound', + 'message' => "{$request->getUrl()} was not found", + ], + [ + 'Response Code' => 404, + 'Response Status' => 'Not Found', + 'Content-Type' => 'application/json', + ] + ); + } + + /** + * Return the last request given to this Adapter. + * + * @return RequestInterface + */ + public function getRequest() + { + return $this->request; + } +} diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 901d2a6..e59999e 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -2,7 +2,7 @@ namespace Chadicus\Marvel\Api; -use Chadicus\Marvel\Api\Assets\FakeAdapter; +use Chadicus\Marvel\Api\Assets; use Chadicus\Marvel\Api\Adapter\AdapterInterface; /** @@ -42,7 +42,7 @@ function () { } ); - $adapter = new FakeAdapter(); + $adapter = new Assets\FakeAdapter(); $client = new Client('aPrivateKey', 'aPublicKey', $adapter); $client->search('a Resource', ['key' => 'value']); $request = $adapter->getRequest(); @@ -82,15 +82,15 @@ public function badConstructorData() { return [ // privateApiKey - 'privateApiKey is null' => [null, 'a public key', new FakeAdapter()], - 'privateApiKey is empty' => ['', 'a public key', new FakeAdapter()], - 'privateApiKey is whitespace' => [" \n\t", 'a public key', new FakeAdapter()], - 'privateApiKey is not a string' => [true, 'a public key', new FakeAdapter()], + 'privateApiKey is null' => [null, 'a public key', new Assets\FakeAdapter()], + 'privateApiKey is empty' => ['', 'a public key', new Assets\FakeAdapter()], + 'privateApiKey is whitespace' => [" \n\t", 'a public key', new Assets\FakeAdapter()], + 'privateApiKey is not a string' => [true, 'a public key', new Assets\FakeAdapter()], // publicApiKey - 'publicApiKey is null' => ['a private key', null, new FakeAdapter()], - 'publicApiKey is empty' => ['a private key', '', new FakeAdapter()], - 'publicApiKey is whitespace' => ['a private key', "\n \t", new FakeAdapter()], - 'publicApiKey is not a string' => ['a private key', false, new FakeAdapter()], + 'publicApiKey is null' => ['a private key', null, new Assets\FakeAdapter()], + 'publicApiKey is empty' => ['a private key', '', new Assets\FakeAdapter()], + 'publicApiKey is whitespace' => ['a private key', "\n \t", new Assets\FakeAdapter()], + 'publicApiKey is not a string' => ['a private key', false, new Assets\FakeAdapter()], ]; } @@ -109,7 +109,7 @@ public function badConstructorData() */ public function searchtWithBadData($resource, array $filters) { - (new Client('not under test', 'not under test', new FakeAdapter()))->search($resource, $filters); + (new Client('not under test', 'not under test', new Assets\FakeAdapter()))->search($resource, $filters); } /** @@ -147,7 +147,7 @@ function () { } ); - $adapter = new FakeAdapter(); + $adapter = new Assets\FakeAdapter(); $client = new Client('aPrivateKey', 'aPublicKey', $adapter); $client->get('a Resource', 1); $request = $adapter->getRequest(); @@ -174,7 +174,7 @@ function () { */ public function gettWithBadData($resource, $id) { - (new Client('not under test', 'not under test', new FakeAdapter()))->get($resource, $id); + (new Client('not under test', 'not under test', new Assets\FakeAdapter()))->get($resource, $id); } /** @@ -220,7 +220,7 @@ function () { new Request(Client::BASE_URL . "a+Resource/1?apikey=aPublicKey&ts=1&hash={$hash}", 'GET'), new Response(599, ['custom' => 'header'], ['key' => 'value']) ); - $adapter = new FakeAdapter(); + $adapter = new Assets\FakeAdapter(); $client = new Client('aPrivateKey', 'aPublicKey', $adapter, $cache); $response = $client->get('a Resource', 1); $this->assertSame(599, $response->getHttpCode()); @@ -253,7 +253,7 @@ function () { $request = new Request(Client::BASE_URL . "a+Resource/1?apikey=aPublicKey&ts=1&hash={$hash}", 'GET'); $cache = new Cache\ArrayCache(); - $adapter = new FakeAdapter(); + $adapter = new Assets\FakeAdapter(); $client = new Client('aPrivateKey', 'aPublicKey', $adapter, $cache); $response = $client->get('a Resource', 1); @@ -262,4 +262,69 @@ function () { $this->assertSame($response->getHeaders(), $cachedResponse->getHeaders()); $this->assertSame($response->getBody(), $cachedResponse->getBody()); } + + /** + * Verify bahvior of __call() for single entity. + * + * @test + * @covers ::__call + * + * @return void + */ + public function callEntity() + { + $client = new Client('not under test', 'not under test', new Assets\ComicAdapter()); + $comic = $client->comics(2); + $this->assertInstanceOf('Chadicus\Marvel\Api\Entities\Comic', $comic); + $this->assertSame(2, $comic->getId()); + } + + /** + * Verify bahvior of __call() for entity that is not found. + * + * @test + * @covers ::__call + * + * @return void + */ + public function callEntityNotFound() + { + $client = new Client('not under test', 'not under test', new Assets\EmptyAdapter()); + $comic = $client->comics(1); + $this->assertNull($comic); + } + + /** + * Verify bahvior of __call() for entity that is invalid. + * + * @test + * @covers ::__call + * + * @return void + */ + public function callInvalidEntity() + { + $client = new Client('not under test', 'not under test', new Assets\ErrorAdapter()); + $result = $client->batman(1); + $this->assertNull($result); + } + + /** + * Verify basic bahvior of __call() for entity collection. + * + * @test + * @covers ::__call + * + * @return void + */ + public function callCollection() + { + $client = new Client('not under test', 'not under test', new Assets\ComicAdapter()); + $comics = $client->comics(); + $this->assertInstanceOf('Chadicus\Marvel\Api\Collection', $comics); + $this->assertSame(5, $comics->count()); + foreach ($comics as $key => $comic) { + $this->assertSame($key + 1, $comic->getId()); + } + } }