Completed
Branch master (1afb45)
by Timothy
04:13
created

AnimeCollection::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 7
Bugs 2 Features 2
Metric Value
c 7
b 2
f 2
dl 0
loc 7
rs 9.4285
cc 1
eloc 3
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 Aviat\Ion\Json;
17
use Aviat\Ion\Di\ContainerInterface;
18
19
/**
20
 * Model for getting anime collection data
21
 */
22
class AnimeCollection extends Collection {
23
24
	/**
25
	 * Constructor
26
	 *
27
	 * @param ContainerInterface $container
28
	 */
29
	public function __construct(ContainerInterface $container)
30
	{
31
		parent::__construct($container);
32
33
		// Do an import if an import file exists
34
		$this->json_import();
35
	}
36
37
	/**
38
	 * Get collection from the database, and organize by media type
39
	 *
40
	 * @return array
41
	 */
42
	public function get_collection()
43
	{
44
		$raw_collection = $this->_get_collection();
45
46
		$collection = [];
47
48
		foreach ($raw_collection as $row)
49
		{
50
			if (array_key_exists($row['media'], $collection))
51
			{
52
				$collection[$row['media']][] = $row;
53
			}
54
			else
55
			{
56
				$collection[$row['media']] = [$row];
57
			}
58
		}
59
60
		return $collection;
61
	}
62
63
	/**
64
	 * Get list of media types
65
	 *
66
	 * @return array
67
	 */
68
	public function get_media_type_list()
69
	{
70
		$output = array();
71
72
		$query = $this->db->select('id, type')
73
			->from('media')
74
			->get();
75
76
		foreach ($query->fetchAll(\PDO::FETCH_ASSOC) as $row)
77
		{
78
			$output[$row['id']] = $row['type'];
79
		}
80
81
		return $output;
82
	}
83
84
	/**
85
	 * Get item from collection for editing
86
	 *
87
	 * @param int $id
88
	 * @return array
89
	 */
90
	public function get_collection_entry($id)
91
	{
92
		$query = $this->db->from('anime_set')
93
			->where('hummingbird_id', (int)$id)
94
			->get();
95
96
		return $query->fetch(\PDO::FETCH_ASSOC);
97
	}
98
99
	/**
100
	 * Get full collection from the database
101
	 *
102
	 * @return array
103
	 */
104
	private function _get_collection()
105
	{
106
		if ( ! $this->valid_database)
107
		{
108
			return [];
109
		}
110
111
		$query = $this->db->select('hummingbird_id, slug, title, alternate_title, show_type,
112
			 age_rating, episode_count, episode_length, cover_image, notes, media.type as media')
113
			->from('anime_set a')
114
			->join('media', 'media.id=a.media_id', 'inner')
115
			->order_by('media')
116
			->order_by('title')
117
			->get();
118
119
		return $query->fetchAll(\PDO::FETCH_ASSOC);
120
	}
121
122
	/**
123
	 * Add an item to the anime collection
124
	 *
125
	 * @param array $data
126
	 * @return void
127
	 */
128
	public function add($data)
129
	{
130
		$anime = (object)$this->anime_model->get_anime($data['id']);
131
132
		$this->db->set([
133
			'hummingbird_id' => $data['id'],
134
			'slug' => $anime->slug,
135
			'title' => $anime->title,
136
			'alternate_title' => $anime->alternate_title,
137
			'show_type' => $anime->show_type,
138
			'age_rating' => $anime->age_rating,
139
			'cover_image' => basename(
140
				$this->get_cached_image($anime->cover_image, $anime->slug, 'anime')
141
			),
142
			'episode_count' => $anime->episode_count,
143
			'episode_length' => $anime->episode_length,
144
			'media_id' => $data['media_id'],
145
			'notes' => $data['notes']
146
		])->insert('anime_set');
147
148
		$this->update_genre($data['id']);
149
	}
150
151
	/**
152
	 * Update a collection item
153
	 *
154
	 * @param array $data
155
	 * @return void
156
	 */
157
	public function update($data)
158
	{
159
		// If there's no id to update, don't update
160
		if ( ! array_key_exists('hummingbird_id', $data))
161
		{
162
			return;
163
		}
164
165
		$id = $data['hummingbird_id'];
166
		unset($data['hummingbird_id']);
167
168
		$this->db->set($data)
169
			->where('hummingbird_id', $id)
170
			->update('anime_set');
171
	}
172
173
	/**
174
	 * Remove a colleciton item
175
	 * 
176
	 * @param  array $data
177
	 * @return void
178
	 */
179
	public function delete($data)
180
	{
181
		// If there's no id to update, don't delete
182
		if ( ! array_key_exists('hummingbird_id', $data))
183
		{
184
			return;
185
		}
186
187
		$this->db->where('hummingbird_id', $data['hummingbird_id'])
188
			->delete('genre_anime_set_link');
189
190
		$this->db->where('hummingbird_id', $data['hummingbird_id'])
191
			->delete('anime_set');
192
	}
193
194
	/**
195
	 * Get the details of a collection item
196
	 *
197
	 * @param int $hummingbird_id
198
	 * @return array
199
	 */
200
	public function get($hummingbird_id)
201
	{
202
		$query = $this->db->from('anime_set')
203
			->where('hummingbird_id', $hummingbird_id)
204
			->get();
205
206
		return $query->fetch(\PDO::FETCH_ASSOC);
207
	}
208
209
	/**
210
	 * Import anime into collection from a json file
211
	 *
212
	 * @return void
213
	 */
214
	private function json_import()
215
	{
216
		if ( ! file_exists('import.json') || ! $this->valid_database)
217
		{
218
			return;
219
		}
220
221
		$anime = Json::decodeFile("import.json");
222
223
		foreach ($anime as $item)
224
		{
225
			$this->db->set([
226
				'hummingbird_id' => $item->id,
227
				'slug' => $item->slug,
228
				'title' => $item->title,
229
				'alternate_title' => $item->alternate_title,
230
				'show_type' => $item->show_type,
231
				'age_rating' => $item->age_rating,
232
				'cover_image' => basename(
233
					$this->get_cached_image($item->cover_image, $item->slug, 'anime')
234
				),
235
				'episode_count' => $item->episode_count,
236
				'episode_length' => $item->episode_length
237
			])->insert('anime_set');
238
		}
239
240
		// Delete the import file
241
		unlink('import.json');
242
243
		// Update genre info
244
		$this->update_genres();
245
	}
246
247
	/**
248
	 * Update genre information for selected anime
249
	 *
250
	 * @param int $anime_id The current anime
251
	 * @return void
252
	 */
253
	private function update_genre($anime_id)
254
	{
255
		$genre_info = $this->get_genre_data();
256
		extract($genre_info);
257
258
		// Get api information
259
		$anime = $this->anime_model->get_anime($anime_id);
260
261
		foreach ($anime['genres'] as $genre)
262
		{
263
			// Add genres that don't currently exist
264
			if ( ! in_array($genre['name'], $genres))
265
			{
266
				$this->db->set('genre', $genre['name'])
267
					->insert('genres');
268
269
				$genres[] = $genre['name'];
270
			}
271
272
			// Update link table
273
			// Get id of genre to put in link table
274
			$flipped_genres = array_flip($genres);
275
276
			$insert_array = [
277
				'hummingbird_id' => $anime['id'],
278
				'genre_id' => $flipped_genres[$genre['name']]
279
			];
280
281
			if (array_key_exists($anime['id'], $links))
282
			{
283
				if ( ! in_array($flipped_genres[$genre['name']], $links[$anime['id']]))
284
				{
285
					$this->db->set($insert_array)->insert('genre_anime_set_link');
286
				}
287
			}
288
			else
289
			{
290
				$this->db->set($insert_array)->insert('genre_anime_set_link');
291
			}
292
		}
293
	}
294
295
	/**
296
	 * Get list of existing genres
297
	 *
298
	 * @return array
299
	 */
300
	private function get_genre_data()
301
	{
302
		$genres = [];
303
		$links = [];
304
305
		// Get existing genres
306
		$query = $this->db->select('id, genre')
307
			->from('genres')
308
			->get();
309
		foreach ($query->fetchAll(\PDO::FETCH_ASSOC) as $genre)
310
		{
311
			$genres[$genre['id']] = $genre['genre'];
312
		}
313
314
		// Get existing link table entries
315
		$query = $this->db->select('hummingbird_id, genre_id')
316
			->from('genre_anime_set_link')
317
			->get();
318
		foreach ($query->fetchAll(\PDO::FETCH_ASSOC) as $link)
319
		{
320
			if (array_key_exists($link['hummingbird_id'], $links))
321
			{
322
				$links[$link['hummingbird_id']][] = $link['genre_id'];
323
			}
324
			else
325
			{
326
				$links[$link['hummingbird_id']] = [$link['genre_id']];
327
			}
328
		}
329
330
		return [
331
			'genres' => $genres,
332
			'links' => $links
333
		];
334
	}
335
336
	/**
337
	 * Update genre information for the entire collection
338
	 *
339
	 * @return void
340
	 */
341
	private function update_genres()
342
	{
343
		// Get the anime collection
344
		$collection = $this->_get_collection();
345
		foreach ($collection as $anime)
346
		{
347
			// Get api information
348
			$this->update_genre($anime['hummingbird_id']);
349
		}
350
	}
351
}
352
// End of AnimeCollectionModel.php