diff --git a/.gitignore b/.gitignore index 3b99cf4..a091e6b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ composer.lock docs vendor coverage -.idea \ No newline at end of file +.idea +.php_cs.cache \ No newline at end of file diff --git a/.php_cs.cache b/.php_cs.cache deleted file mode 100644 index c6affc4..0000000 --- a/.php_cs.cache +++ /dev/null @@ -1 +0,0 @@ -{"php":"7.2.19-0ubuntu0.18.04.2","version":"2.15.3:v2.15.3#705490b0f282f21017d73561e9498d2b622ee34c","indent":" ","lineEnding":"\n","rules":{"blank_line_after_namespace":true,"braces":true,"class_definition":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_constants":true,"lowercase_keywords":true,"method_argument_space":{"ensure_fully_multiline":false},"no_closing_tag":true,"no_spaces_after_function_name":true,"no_spaces_inside_parenthesis":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_import_per_statement":true,"single_line_after_imports":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"visibility_required":true,"encoding":true,"full_opening_tag":true,"array_syntax":{"syntax":"short"},"binary_operator_spaces":{"align_equals":false,"align_double_arrow":false},"cast_spaces":true,"combine_consecutive_unsets":true,"concat_space":{"spacing":"one"},"linebreak_after_opening_tag":true,"no_blank_lines_after_class_opening":true,"no_blank_lines_after_phpdoc":true,"no_extra_consecutive_blank_lines":true,"no_trailing_comma_in_singleline_array":true,"no_whitespace_in_blank_line":true,"no_spaces_around_offset":true,"no_unused_imports":true,"no_useless_else":true,"no_useless_return":true,"no_whitespace_before_comma_in_array":true,"normalize_index_brace":true,"phpdoc_indent":true,"phpdoc_to_comment":true,"phpdoc_trim":true,"single_quote":true,"ternary_to_null_coalescing":true,"trailing_comma_in_multiline_array":true,"trim_array_spaces":true,"blank_line_before_statement":true},"hashes":{"\/tmp\/phpcsfixer_temp.tmp\/src\/Model\/Character.php":3249024362,"\/tmp\/phpcsfixer_temp.tmp\/src\/Api\/AbstractApi.php":347679094}} \ No newline at end of file diff --git a/src/Api/AbstractApi.php b/src/Api/AbstractApi.php index a874011..d02359d 100644 --- a/src/Api/AbstractApi.php +++ b/src/Api/AbstractApi.php @@ -44,6 +44,10 @@ public function sendRequest($uri = null, $arguments = null, $async = false) return $promise; } + /** + * @param null $ids + * @return mixed + */ public function get($ids = null) { $uri = $this->getUri($ids ?? $this->ids); @@ -60,7 +64,7 @@ public function all() * @param array $params * @return $this */ - public function where(array $params) + public function where(array $params) : self { if (!isset($this->arguments['query'])) { $this->arguments['query'] = []; @@ -78,12 +82,11 @@ public function where(array $params) } /** - * You can set ids and add additional filters and then execute API request - * + * You can set ids and add additional filters and then execute API requesr * @param $ids * @return AbstractApi */ - public function whereId($ids) + public function whereId($ids) : self { return $this->where(['id' => $ids]); } @@ -102,7 +105,7 @@ public function raw(string $uri) * * @return $this */ - public function clear() + public function clear() : self { $this->ids = null; $this->arguments['query'] = []; @@ -114,7 +117,7 @@ public function clear() * Get arguments/filters for API * @return array */ - public function getArguments() + public function getArguments() : array { return $this->arguments; } @@ -123,9 +126,9 @@ public function getArguments() * Set page for request * * @param int $page - * @return $this + * @return AbstractApi */ - public function setPage(int $page) + public function setPage(int $page) : self { $this->page = $page; $this->where(['page' => $page]); @@ -135,9 +138,9 @@ public function setPage(int $page) /** * Increment page to simulate pagination - * @return $this + * @return AbstractApi */ - public function nextPage() + public function nextPage() : self { $this->page++; $this->where(['page' => $this->page]); @@ -147,9 +150,9 @@ public function nextPage() /** * Decrement page to simulate pagination - * @return $this + * @return AbstractApi */ - public function previousPage() + public function previousPage() : self { /* * Minimum page number is 1 @@ -189,9 +192,9 @@ public function getUri($ids = null) * Example: whereName('Rick') will internally call where function with argument ['name' => 'Rick'] * @param $name * @param $arguments - * @return $this + * @return AbstractApi */ - public function __call($name, $arguments) + public function __call($name, $arguments) : self { if (strpos($name, 'where') !== 0) { throw new \BadFunctionCallException(); diff --git a/src/Api/Character.php b/src/Api/Character.php index ef24261..85218a3 100644 --- a/src/Api/Character.php +++ b/src/Api/Character.php @@ -30,7 +30,9 @@ public function __construct(Client $client) */ public function getOrigin($id = null) { - return $this->get($id)->getOrigins(); + $origin = $this->get($id); + + return $origin->hasErrors() ? $origin : $origin->getOrigins(); } /** @@ -41,15 +43,17 @@ public function getOrigin($id = null) */ public function getLocation($id = null) { - return $this->get($id)->getLocations(); + $locations = $this->get($id); + + return $locations->hasErrors() ? $locations : $locations->getLocations(); } /** * Query to filter dead characters * - * @return $this + * @return Character */ - public function isDead() + public function isDead() : self { $this->where(['status' => 'dead']); @@ -59,9 +63,9 @@ public function isDead() /** * Query to filter alive characters * - * @return $this + * @return Character */ - public function isAlive() + public function isAlive() : self { $this->where(['status' => 'alive']); @@ -71,9 +75,9 @@ public function isAlive() /** * Query to filter characters with unknown status * - * @return $this + * @return Character */ - public function isStatusUnknown() + public function isStatusUnknown() : self { $this->where(['status' => 'unknown']); @@ -83,9 +87,9 @@ public function isStatusUnknown() /** * Query to filter female characters * - * @return $this + * @return Character */ - public function isFemale() + public function isFemale() : self { $this->where(['gender' => 'female']); @@ -95,9 +99,9 @@ public function isFemale() /** * Query to filter male characters * - * @return $this + * @return Character */ - public function isMale() + public function isMale() : self { $this->where(['gender' => 'male']); @@ -107,9 +111,9 @@ public function isMale() /** * Query to filter genderless characters * - * @return $this + * @return Character */ - public function isGenderless() + public function isGenderless() : self { $this->where(['gender' => 'genderless']); @@ -119,9 +123,9 @@ public function isGenderless() /** * Query to filter characters with unknown gender * - * @return $this + * @return Character */ - public function isGenderUnknown() + public function isGenderUnknown() : self { $this->where(['gender' => 'unknown']); diff --git a/src/Api/Episode.php b/src/Api/Episode.php index 1d895c8..54a4cfa 100644 --- a/src/Api/Episode.php +++ b/src/Api/Episode.php @@ -26,6 +26,8 @@ public function __construct(Client $client) */ public function getCharacters($id = null) { - return $this->get($id)->getCharacters(); + $episodes = $this->get($id); + + return $episodes->hasErrors() ? $episodes : $episodes->getCharacters(); } } diff --git a/src/Api/Location.php b/src/Api/Location.php index e53f554..9180943 100644 --- a/src/Api/Location.php +++ b/src/Api/Location.php @@ -27,6 +27,8 @@ public function __construct(Client $client) */ public function getResidents($id = null) { - return $this->get($id)->getResidents(); + $locations = $this->get($id); + + return $locations->hasErrors() ? $locations : $locations->getResidents(); } } diff --git a/src/Model/AbstractModel.php b/src/Model/AbstractModel.php index 4a00e23..356a569 100644 --- a/src/Model/AbstractModel.php +++ b/src/Model/AbstractModel.php @@ -30,12 +30,39 @@ public function __construct($response, $parent) $this->info = $this->data['info'] ?? null; } - public function toArray() + /** + * Check if there was errors on request + * @return bool + */ + public function hasErrors(): bool + { + return $this->response->getStatusCode() >= 400; + } + + /** + * Get response status code + * + * @return int + */ + public function getResponseStatusCode(): int + { + return $this->response->getStatusCode(); + } + + /** + * Get response data + * @return array + */ + public function toArray(): array { return $this->data; } - public function toJson() + /** + * Get data as json + * @return string + */ + public function toJson(): string { return json_encode($this->data); } @@ -44,7 +71,7 @@ public function toJson() * Check if is first page of response * @return bool */ - public function isFirstPage() + public function isFirstPage(): bool { if ($this->info && $this->info['prev']) { return false; @@ -58,7 +85,7 @@ public function isFirstPage() * * @return bool */ - public function isLastPage() + public function isLastPage(): bool { if ($this->info && $this->info['next']) { return false; @@ -71,7 +98,7 @@ public function isLastPage() * Get total number of records * @return int */ - public function count() + public function count(): int { if ($this->info) { return $this->info['count']; @@ -91,7 +118,7 @@ public function count() /** Get total number of pages * @return int */ - public function pages() + public function pages(): int { return $this->info['pages'] ?? 1; } @@ -122,6 +149,10 @@ public function next() return $this->parent->nextPage()->sendRequest(); } + /** + * Go to first page + * @return mixed + */ public function firstPage() { if ($this->info) { @@ -131,6 +162,11 @@ public function firstPage() return null; } + /** + * Go to desired page + * @param int $page + * @return mixed + */ public function goToPage(int $page) { if ($this->info) { @@ -138,6 +174,10 @@ public function goToPage(int $page) } } + /** + * Go to last page + * @return mixed + */ public function lastPage() { if ($this->info) { @@ -146,4 +186,19 @@ public function lastPage() return null; } + + /** + * Helper function to get ids from urls + * @param array $urls + * @return array + */ + public function parseIdsFromUrl(array $urls) : array + { + $ids = []; + foreach ($urls as $url) { + $ids[] = substr(strrchr($url, '/'), 1); + } + + return $ids; + } } diff --git a/src/Model/Character.php b/src/Model/Character.php index 4084794..aab5846 100644 --- a/src/Model/Character.php +++ b/src/Model/Character.php @@ -2,15 +2,17 @@ namespace Zmaglica\RickAndMortyApiWrapper\Model; +use Zmaglica\RickAndMortyApiWrapper\Api\AbstractApi; + class Character extends AbstractModel { /** * Get all locations without running API call. Useful if you want to perform additional filtering. * * @param bool $removeDuplicates - * @return array|\Zmaglica\RickAndMortyApiWrapper\Api\AbstractApi + * @return AbstractApi */ - public function locations($removeDuplicates = false) + public function locations($removeDuplicates = false) : AbstractApi { $ids = $this->extractIdsFromResponseBasedOnKey('location', $removeDuplicates); @@ -31,9 +33,9 @@ public function getLocations($removeDuplicates = false) * Get all origin locations. Useful if you want to perform additional filtering. * * @param bool $removeDuplicates - * @return array|\Zmaglica\RickAndMortyApiWrapper\Api\AbstractApi + * @return AbstractApi */ - public function origins($removeDuplicates = false) + public function origins($removeDuplicates = false) : AbstractApi { $ids = $this->extractIdsFromResponseBasedOnKey('origin', $removeDuplicates); @@ -55,9 +57,9 @@ public function getOrigins($removeDuplicates = false) * Get all episodes. Useful if you want to perform additional filtering. * * @param bool $removeDuplicates - * @return \Zmaglica\RickAndMortyApiWrapper\Api\AbstractApi + * @return AbstractApi */ - public function episodes($removeDuplicates = false) + public function episodes($removeDuplicates = false) : AbstractApi { $ids = $this->extractIdsFromResponseBasedOnKey('episode', $removeDuplicates); @@ -80,9 +82,8 @@ public function getEpisodes($removeDuplicates = false) * @param boolean $removeDuplicates * @return array */ - private function extractIdsFromResponseBasedOnKey($key, $removeDuplicates) + private function extractIdsFromResponseBasedOnKey($key, $removeDuplicates) : array { - $ids = []; $urls = []; if ($this->info) { $urls = array_column($this->data['results'], $key); @@ -96,14 +97,6 @@ private function extractIdsFromResponseBasedOnKey($key, $removeDuplicates) $urls = array_unique($urls); } - foreach ($urls as $url) { - $ids[] = substr(strrchr($url, '/'), 1); - ; - } - if (!$ids) { - return []; - } - - return $ids; + return $this->parseIdsFromUrl($urls); } } diff --git a/src/Model/Episode.php b/src/Model/Episode.php index 9b643e0..4fa76d7 100644 --- a/src/Model/Episode.php +++ b/src/Model/Episode.php @@ -2,14 +2,16 @@ namespace Zmaglica\RickAndMortyApiWrapper\Model; +use Zmaglica\RickAndMortyApiWrapper\Api\AbstractApi; + class Episode extends AbstractModel { /** * Get all characters without running API call. Useful if you want to perform additional filtering. * @param bool $removeDuplicates - * @return \Zmaglica\RickAndMortyApiWrapper\Api\AbstractApi + * @return AbstractApi */ - public function characters($removeDuplicates = false) + public function characters($removeDuplicates = false): AbstractApi { $ids = $this->extractIdsFromResponseBasedOnKey('characters', $removeDuplicates); @@ -32,9 +34,8 @@ public function getCharacters($removeDuplicates = false) * @param $removeDuplicates * @return array */ - private function extractIdsFromResponseBasedOnKey($key, $removeDuplicates) + private function extractIdsFromResponseBasedOnKey($key, $removeDuplicates): array { - $ids = []; if ($this->info) { $urls = array_column($this->data['results'], $key); // flatten array to single one because there can be multiple residents per location @@ -51,11 +52,6 @@ private function extractIdsFromResponseBasedOnKey($key, $removeDuplicates) $urls = array_unique($urls); } - foreach ($urls as $url) { - $ids[] = substr(strrchr($url, '/'), 1); - ; - } - - return $ids; + return $this->parseIdsFromUrl($urls); } } diff --git a/src/Model/Location.php b/src/Model/Location.php index e89304e..22d4899 100644 --- a/src/Model/Location.php +++ b/src/Model/Location.php @@ -2,14 +2,16 @@ namespace Zmaglica\RickAndMortyApiWrapper\Model; +use Zmaglica\RickAndMortyApiWrapper\Api\AbstractApi; + class Location extends AbstractModel { /** * Get all location residents without running API call. Useful if you want to perform additional filtering. * @param bool $removeDuplicates - * @return \Zmaglica\RickAndMortyApiWrapper\Api\AbstractApi + * @return AbstractApi */ - public function residents($removeDuplicates = false) + public function residents($removeDuplicates = false): AbstractApi { $ids = $this->extractIdsFromResponseBasedOnKey('residents', $removeDuplicates); @@ -32,9 +34,8 @@ public function getResidents($removeDuplicates = false) * @param $removeDuplicates * @return array */ - private function extractIdsFromResponseBasedOnKey($key, $removeDuplicates) + private function extractIdsFromResponseBasedOnKey($key, $removeDuplicates): array { - $ids = []; if ($this->info) { $urls = array_column($this->data['results'], $key); // flatten array to single one because there can be multiple residents per location @@ -51,11 +52,6 @@ private function extractIdsFromResponseBasedOnKey($key, $removeDuplicates) $urls = array_unique($urls); } - foreach ($urls as $url) { - $ids[] = substr(strrchr($url, '/'), 1); - ; - } - - return $ids; + return $this->parseIdsFromUrl($urls); } } diff --git a/src/RickAndMortyApiWrapper.php b/src/RickAndMortyApiWrapper.php index bbe48e0..de1d2c6 100644 --- a/src/RickAndMortyApiWrapper.php +++ b/src/RickAndMortyApiWrapper.php @@ -21,6 +21,7 @@ class RickAndMortyApiWrapper */ private $options = [ 'base_uri' => 'https://rickandmortyapi.com/api/', + 'http_errors' => false, ]; /** @@ -45,7 +46,7 @@ public function getClient(): Client * @param Client $client * @return RickAndMortyApiWrapper */ - public function setClient(Client $client): RickAndMortyApiWrapper + public function setClient(Client $client): self { $this->client = $client; @@ -65,7 +66,7 @@ public function getOptions(): array * @param array $options * @return RickAndMortyApiWrapper */ - public function setOptions(array $options): RickAndMortyApiWrapper + public function setOptions(array $options): self { $this->options = $options; @@ -76,7 +77,7 @@ public function setOptions(array $options): RickAndMortyApiWrapper * Wrapper for Character API * @return Character */ - public function character() + public function character(): Character { return new Character($this->client); } @@ -85,7 +86,7 @@ public function character() * Wrapper for Location API * @return Location */ - public function location() + public function location(): Location { return new Location($this->client); } @@ -94,7 +95,7 @@ public function location() * Wrapper for Episode API * @return Episode */ - public function episode() + public function episode(): Episode { return new Episode($this->client); }