Completed
Push — master ( 645554...205c7a )
by Timothy
05:48
created

Anime::get_library_anime()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 11
rs 9.4286
cc 2
eloc 6
nc 2
nop 2
1
<?php
2
/**
3
 * Hummingbird Anime Client
4
 *
5
 * An API client for Hummingbird to manage anime and manga watch lists
6
 *
7
 * @package     HummingbirdAnimeClient
8
 * @author      Timothy J. Warren
9
 * @copyright   Copyright (c) 2015 - 2016
10
 * @link        https://github.com/timw4mail/HummingBirdAnimeClient
11
 * @license     MIT
12
 */
13
14
namespace Aviat\AnimeClient\Model;
15
16
use Aviat\AnimeClient\Hummingbird\Enum\AnimeWatchingStatus;
17
use Aviat\AnimeClient\Hummingbird\Transformer\AnimeListTransformer;
18
19
/**
20
 * Model for handling requests dealing with the anime list
21
 */
22
class Anime extends API {
23
24
	// Display constants
25
	const WATCHING = 'Watching';
26
	const PLAN_TO_WATCH = 'Plan to Watch';
27
	const DROPPED = 'Dropped';
28
	const ON_HOLD = 'On Hold';
29
	const COMPLETED = 'Completed';
30
31
	/**
32
	 * The base url for api requests
33
	 * @var string $base_url
34
	 */
35
	protected $base_url = "https://hummingbird.me/api/v1/";
36
37
	/**
38
	 * Map of API status constants to display constants
39
	 * @var array
40
	 */
41
	protected $const_map = [
42
		AnimeWatchingStatus::WATCHING => self::WATCHING,
43
		AnimeWatchingStatus::PLAN_TO_WATCH => self::PLAN_TO_WATCH,
44
		AnimeWatchingStatus::ON_HOLD => self::ON_HOLD,
45
		AnimeWatchingStatus::DROPPED => self::DROPPED,
46
		AnimeWatchingStatus::COMPLETED => self::COMPLETED,
47
	];
48
49
	/**
50
	 * Update the selected anime
51
	 *
52
	 * @param array $data
53
	 * @return array|false
54
	 */
55
	public function update($data)
56
	{
57
		$auth = $this->container->get('auth');
58
		if ( ! $auth->is_authenticated() || ! array_key_exists('id', $data))
59
		{
60
			return FALSE;
61
		}
62
63
		$id = $data['id'];
64
		$data['auth_token'] = $auth->get_auth_token();
65
66
		$response = $this->client->post("libraries/{$id}", [
67
			'form_params' => $data
68
		]);
69
70
		$output = [
71
			'statusCode' => $response->getStatusCode(),
72
			'body' => json_decode($response->getBody(), TRUE)
73
		];
74
75
		return $output;
76
	}
77
78
	/**
79
	 * Get the full set of anime lists
80
	 *
81
	 * @return array
82
	 */
83
	public function get_all_lists()
84
	{
85
		$output = [
86
			self::WATCHING => [],
87
			self::PLAN_TO_WATCH => [],
88
			self::ON_HOLD => [],
89
			self::DROPPED => [],
90
			self::COMPLETED => [],
91
		];
92
93
		$data = $this->_get_list_from_api();
94
95
		foreach ($data as $datum)
96
		{
97
			$output[$this->const_map[$datum['watching_status']]][] = $datum;
98
		}
99
100
		// Sort anime by name
101
		foreach ($output as &$status_list)
102
		{
103
			$this->sort_by_name($status_list, 'anime');
104
		}
105
106
		return $output;
107
	}
108
109
	/**
110
	 * Get a category out of the full list
111
	 *
112
	 * @param string $status
113
	 * @return array
114
	 */
115
	public function get_list($status)
116
	{
117
		$data = $this->_get_list_from_api($status);
118
		$this->sort_by_name($data, 'anime');
119
120
		$output = [];
121
		$output[$this->const_map[$status]] = $data;
122
123
		return $output;
124
	}
125
126
	/**
127
	 * Get information about an anime from its id
128
	 *
129
	 * @param string $anime_id
130
	 * @return array
131
	 */
132
	public function get_anime($anime_id)
133
	{
134
		$config = [
135
			'query' => [
136
				'id' => $anime_id
137
			]
138
		];
139
140
		$response = $this->client->get("anime/{$anime_id}", $config);
141
142
		return json_decode($response->getBody(), TRUE);
143
	}
144
145
	/**
146
	 * Search for anime by name
147
	 *
148
	 * @param string $name
149
	 * @return array
150
	 */
151
	public function search($name)
152
	{
153
		$errorHandler = $this->container->get('error-handler');
154
155
		$config = [
156
			'query' => [
157
				'query' => $name
158
			]
159
		];
160
161
		$response = $this->get('search/anime', $config);
162
		$errorHandler->addDataTable('anime_search_response', (array)$response);
163
164
		if ($response->getStatusCode() != 200)
165
		{
166
			throw new RuntimeException($response->getEffectiveUrl());
167
		}
168
169
		return json_decode($response->getBody(), TRUE);
170
	}
171
172
	/**
173
	 * Retrieve data from the api
174
	 *
175
	 * @codeCoverageIgnore
176
	 * @param string $status
177
	 * @return array
178
	 */
179
	protected function _get_list_from_api($status = "all")
180
	{
181
		$config = [
182
			'allow_redirects' => FALSE
183
		];
184
185
		if ($status != "all")
186
		{
187
			$config['query']['status'] = $status;
188
		}
189
190
		$username = $this->config->get('hummingbird_username');
191
		$auth = $this->container->get('auth');
192
		if ($auth->is_authenticated())
193
		{
194
			$config['query']['auth_token'] = $auth->get_auth_token();
195
		}
196
197
		$response = $this->get("users/{$username}/library", $config);
198
		$output = $this->_check_cache($status, $response);
199
200
		foreach ($output as &$row)
201
		{
202
			$row['anime']['image'] = $this->get_cached_image($row['anime']['image'], $row['anime']['slug'], 'anime');
203
		}
204
205
		return $output;
206
	}
207
208
	/**
209
	 * Handle caching of transformed api data
210
	 *
211
	 * @codeCoverageIgnore
212
	 * @param string $status
213
	 * @param \GuzzleHttp\Message\Response
214
	 * @return array
215
	 */
216
	protected function _check_cache($status, $response)
217
	{
218
		$cache_file = _dir($this->config->get('data_cache_path'), "anime-{$status}.json");
219
		$transformed_cache_file = _dir($this->config->get('data_cache_path'), "anime-{$status}-transformed.json");
220
221
		$cached = (file_exists($cache_file))
222
			? json_decode(file_get_contents($cache_file), TRUE)
223
			: [];
224
		$api_data = json_decode($response->getBody(), TRUE);
225
226 View Code Duplication
		if ($api_data === $cached && file_exists($transformed_cache_file))
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...
227
		{
228
			return json_decode(file_get_contents($transformed_cache_file), TRUE);
229
		}
230
		else
231
		{
232
			file_put_contents($cache_file, json_encode($api_data));
233
			$transformer = new AnimeListTransformer();
234
			$transformed = $transformer->transform_collection($api_data);
235
			file_put_contents($transformed_cache_file, json_encode($transformed));
236
			return $transformed;
237
		}
238
	}
239
}
240
// End of AnimeModel.php