Completed
Push — develop ( 49bd46...d746de )
by Timothy
03:17
created

Manga::add()   A

Complexity

Conditions 1
Paths 1

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.4285
cc 1
eloc 6
nc 1
nop 1
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 GuzzleHttp\Cookie\Cookiejar;
17
use GuzzleHttp\Cookie\SetCookie;
18
19
use Aviat\Ion\Json;
20
use Aviat\AnimeClient\Model\API;
21
use Aviat\AnimeClient\Hummingbird\Transformer;
22
use Aviat\AnimeClient\Hummingbird\Enum\MangaReadingStatus;
23
24
/**
25
 * Model for handling requests dealing with the manga list
26
 */
27
class Manga extends API {
28
29
	const READING = 'Reading';
30
	const PLAN_TO_READ = 'Plan to Read';
31
	const DROPPED = 'Dropped';
32
	const ON_HOLD = 'On Hold';
33
	const COMPLETED = 'Completed';
34
35
	/**
36
	 * Map API constants to display constants
37
	 * @var array
38
	 */
39
	protected $const_map = [
40
		MangaReadingStatus::READING => self::READING,
41
		MangaReadingStatus::PLAN_TO_READ => self::PLAN_TO_READ,
42
		MangaReadingStatus::ON_HOLD => self::ON_HOLD,
43
		MangaReadingStatus::DROPPED => self::DROPPED,
44
		MangaReadingStatus::COMPLETED => self::COMPLETED
45
	];
46
47
	/**
48
	 * The base url for api requests
49
	 * @var string
50
	 */
51
	protected $base_url = "https://hummingbird.me/";
52
53 View Code Duplication
	protected function _auth_json_call($type, $url, $json)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
54
	{
55
		$token = $this->container->get('auth')
56
			->get_auth_token();
57
58
		// Set the token cookie, with the authentication token
59
		// from the auth class.
60
		$cookieJar = $this->cookieJar;
61
		$cookie_data = new SetCookie([
62
			'Name' => 'token',
63
			'Value' => $token,
64
			'Domain' => 'hummingbird.me'
65
		]);
66
		$cookieJar->setCookie($cookie_data);
67
68
		$result = $this->client->request(strtoupper($type), $url, [
69
			'cookies' => $cookieJar,
70
			'json' => $json
71
		]);
72
73
		return [
74
			'statusCode' => $result->getStatusCode(),
75
			'body' => $result->getBody()
76
		];
77
	}
78
79
	/**
80
	 * Add a manga to the list
81
	 *
82
	 * @param array $data
83
	 */
84
	public function add($data)
85
	{
86
		$object = [
87
			'manga_library_entry' => [
88
				'status' => $data['status'],
89
				'manga_id' => $data['id']
90
			]
91
		];
92
93
		return $this->_auth_json_call('post', 'manga_library_entries', $object);
94
	}
95
96
	/**
97
	 * Update the selected manga
98
	 *
99
	 * @param array $data
100
	 * @return array
101
	 */
102
	public function update($data)
103
	{
104
		$id = $data['id'];
105
106
		return $this->_auth_json_call(
107
			'put',
108
			"manga_library_entries/{$id}",
109
			['manga_library_entry' => $data]
110
		);
111
	}
112
113
	/**
114
	 * Delete a manga entry
115
	 *
116
	 * @param  array $data
117
	 * @return array
118
	 */
119 View Code Duplication
	public function delete($data)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
120
	{
121
		$id = $data['id'];
122
123
		$token = $this->container->get('auth')
124
			->get_auth_token();
125
126
		// Set the token cookie, with the authentication token
127
		// from the auth class.
128
		$cookieJar = $this->cookieJar;
129
		$cookie_data = new SetCookie([
130
			'Name' => 'token',
131
			'Value' => $token,
132
			'Domain' => 'hummingbird.me'
133
		]);
134
		$cookieJar->setCookie($cookie_data);
135
136
		$result = $this->delete("manga_library_entries/{$id}", [
0 ignored issues
show
Unused Code introduced by
The call to Manga::delete() has too many arguments starting with array('cookies' => $cookieJar).

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
137
			'cookies' => $cookieJar,
138
		]);
139
140
		return [
141
			'statusCode' => $result->getStatusCode(),
142
			'body' => $result->getBody()
143
		];
144
	}
145
146
	/**
147
	 * Search for manga by name
148
	 *
149
	 * @param string $name
150
	 * @return array
151
	 */
152
	public function search($name)
153
	{
154
		$logger = $this->container->getLogger('default');
155
156
		$config = [
157
			'query' => [
158
				'scope' => 'manga',
159
				'depth' => 'full',
160
				'query' => $name
161
			]
162
		];
163
164
		$response = $this->get('search.json', $config);
165
166 View Code Duplication
		if ($response->getStatusCode() != 200)
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...
167
		{
168
			$logger->warning("Non 200 response for search api call");
169
			$logger->warning($response->getBody());
170
171
			throw new RuntimeException($response->getEffectiveUrl());
172
		}
173
174
		return Json::decode($response->getBody(), TRUE);
175
	}
176
177
	/**
178
	 * Get the full set of anime lists
179
	 *
180
	 * @return array
181
	 */
182
	public function get_all_lists()
183
	{
184
		$data = $this->_get_list_from_api();
185
186
		foreach ($data as &$val)
187
		{
188
			$this->sort_by_name($val, 'manga');
189
		}
190
191
		return $data;
192
	}
193
194
	/**
195
	 * Get a category out of the full list
196
	 *
197
	 * @param string $status
198
	 * @return array
199
	 */
200
	public function get_list($status)
201
	{
202
		$data = $this->_get_list_from_api($status);
203
		$this->sort_by_name($data, 'manga');
204
205
		return $data;
206
	}
207
208
	/**
209
	 * Retrieve the list from the hummingbird api
210
	 *
211
	 * @param  string $status
212
	 * @return array
213
	 */
214
	protected function _get_list_from_api($status = "All")
215
	{
216
		$config = [
217
			'query' => [
218
				'user_id' => $this->config->get('hummingbird_username')
219
			],
220
			'allow_redirects' => FALSE
221
		];
222
223
		$response = $this->get('manga_library_entries', $config);
224
		$data = $this->_check_cache($response);
225
		$output = $this->map_by_status($data);
226
227
		return (array_key_exists($status, $output))
228
			? $output[$status]
229
			: $output;
230
	}
231
232
	/**
233
	 * Check the status of the cache and return the appropriate response
234
	 *
235
	 * @param \GuzzleHttp\Message\Response $response
236
	 * @codeCoverageIgnore
237
	 * @return array
238
	 */
239
	private function _check_cache($response)
240
	{
241
		// Bail out early if there isn't any manga data
242
		$api_data = Json::decode($response->getBody(), TRUE);
243
		if ( ! array_key_exists('manga', $api_data))
244
		{
245
			return [];
246
		}
247
248
		$cache_file = _dir($this->config->get('data_cache_path'), 'manga.json');
249
		$transformed_cache_file = _dir(
250
			$this->config->get('data_cache_path'),
251
			'manga-transformed.json'
252
		);
253
254
		$cached_data = file_exists($cache_file)
255
			? Json::decodeFile($cache_file)
256
			: [];
257
258 View Code Duplication
		if ($cached_data === $api_data && 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...
259
		{
260
			return Json::decodeFile($transformed_cache_file);
261
		}
262
		else
263
		{
264
			Json::encodeFile($cache_file, $api_data);
265
266
			$zippered_data = $this->zipper_lists($api_data);
267
			$transformer = new Transformer\MangaListTransformer();
268
			$transformed_data = $transformer->transform_collection($zippered_data);
269
			Json::encodeFile($transformed_cache_file, $transformed_data);
270
			return $transformed_data;
271
		}
272
	}
273
274
	/**
275
	 * Map transformed anime data to be organized by reading status
276
	 *
277
	 * @param array $data
278
	 * @return array
279
	 */
280
	private function map_by_status($data)
281
	{
282
		$output = [
283
			self::READING => [],
284
			self::PLAN_TO_READ => [],
285
			self::ON_HOLD => [],
286
			self::DROPPED => [],
287
			self::COMPLETED => [],
288
		];
289
290
		foreach ($data as &$entry)
291
		{
292
			$entry['manga']['image'] = $this->get_cached_image(
293
				$entry['manga']['image'],
294
				$entry['manga']['slug'],
295
				'manga'
296
			);
297
			$key = $this->const_map[$entry['reading_status']];
298
			$output[$key][] = $entry;
299
		}
300
301
		return $output;
302
	}
303
304
	/**
305
	 * Combine the two manga lists into one
306
	 * @param  array $raw_data
307
	 * @return array
308
	 */
309
	private function zipper_lists($raw_data)
310
	{
311
		return (new Transformer\MangaListsZipper($raw_data))->transform();
312
	}
313
}
314
// End of MangaModel.php