Total Complexity | 57 |
Total Lines | 426 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like PopulateAniDB often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use PopulateAniDB, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
11 | class PopulateAniDB |
||
12 | { |
||
13 | private const CLIENT_VERSION = 2; |
||
14 | |||
15 | /** |
||
16 | * Whether to echo message output. |
||
17 | */ |
||
18 | public bool $echooutput; |
||
19 | |||
20 | /** |
||
21 | * The directory to store AniDB covers. |
||
22 | */ |
||
23 | public string $imgSavePath; |
||
24 | |||
25 | /** |
||
26 | * The name of the nZEDb client for AniDB lookups. |
||
27 | */ |
||
28 | private string $apiKey; |
||
29 | |||
30 | /** |
||
31 | * Whether AniDB thinks our client is banned. |
||
32 | */ |
||
33 | private bool $banned; |
||
34 | |||
35 | /** |
||
36 | * The last unixtime a full AniDB update was run. |
||
37 | */ |
||
38 | private string $lastUpdate; |
||
39 | |||
40 | /** |
||
41 | * The number of days between full AniDB updates. |
||
42 | */ |
||
43 | private string $updateInterval; |
||
44 | |||
45 | protected ColorCLI $colorCli; |
||
46 | |||
47 | /** |
||
48 | * @param array $options Class instances / Echo to cli. |
||
49 | * |
||
50 | * @throws \Exception |
||
51 | */ |
||
52 | public function __construct() |
||
53 | { |
||
54 | $this->echooutput = config('nntmux.echocli'); |
||
55 | $this->colorCli = new ColorCLI(); |
||
56 | |||
57 | $anidbupdint = Settings::settingValue('APIs.AniDB.max_update_frequency'); |
||
58 | $lastupdated = Settings::settingValue('APIs.AniDB.last_full_update'); |
||
59 | |||
60 | $this->imgSavePath = storage_path('covers/anime/'); |
||
61 | $this->apiKey = config('nntmux_api.anidb_api_key'); |
||
62 | |||
63 | $this->updateInterval = $anidbupdint ?? '7'; |
||
64 | $this->lastUpdate = $lastupdated ?? '0'; |
||
65 | $this->banned = false; |
||
66 | } |
||
67 | |||
68 | /** |
||
69 | * Main switch that initiates AniDB table population. |
||
70 | * |
||
71 | * |
||
72 | * @throws \Exception |
||
73 | */ |
||
74 | public function populateTable(string $type = '', int|string $aniDbId = ''): void |
||
75 | { |
||
76 | switch ($type) { |
||
77 | case 'full': |
||
78 | $this->populateMainTable(); |
||
79 | break; |
||
80 | case 'info': |
||
81 | $this->populateInfoTable($aniDbId); |
||
82 | break; |
||
83 | } |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * @return array|false |
||
88 | * |
||
89 | * @throws \Exception |
||
90 | */ |
||
91 | private function getAniDbAPI($aniDbId) |
||
163 | } |
||
164 | |||
165 | private function processAPIResponseElement(\SimpleXMLElement $element, ?string $property = null, bool $children = false): string |
||
178 | } |
||
179 | |||
180 | /** |
||
181 | * Requests and returns the API data from AniDB. |
||
182 | */ |
||
183 | private function getAniDbResponse($aniDbId): string |
||
184 | { |
||
185 | $curlString = sprintf( |
||
186 | 'http://api.anidb.net:9001/httpapi?request=anime&client=%s&clientver=%d&protover=1&aid=%d', |
||
187 | $this->apiKey, |
||
188 | self::CLIENT_VERSION, |
||
189 | $aniDbId |
||
190 | ); |
||
191 | |||
192 | $ch = curl_init($curlString); |
||
193 | |||
194 | $curlOpts = [ |
||
195 | CURLOPT_RETURNTRANSFER => 1, |
||
196 | CURLOPT_HEADER => 0, |
||
197 | CURLOPT_FAILONERROR => 1, |
||
198 | CURLOPT_ENCODING => 'gzip', |
||
199 | ]; |
||
200 | |||
201 | curl_setopt_array($ch, $curlOpts); |
||
202 | $apiResponse = curl_exec($ch); |
||
203 | curl_close($ch); |
||
204 | |||
205 | return $apiResponse; |
||
206 | } |
||
207 | |||
208 | /** |
||
209 | * Inserts new anime info from AniDB to anidb table. |
||
210 | * |
||
211 | * @param int $id The AniDB ID to be inserted |
||
212 | * @param string $type The title type |
||
213 | * @param string $lang The title language |
||
214 | * @param string $title The title of the Anime |
||
215 | */ |
||
216 | private function insertAniDb(int $id, string $type, string $lang, string $title): void |
||
217 | { |
||
218 | $check = AnidbTitle::query()->where(['anidbid' => $id, 'type' => $type, 'lang' => $lang, 'title' => $title])->first(); |
||
219 | |||
220 | if ($check === null) { |
||
221 | AnidbTitle::insertOrIgnore(['anidbid' => $id, 'type' => $type, 'lang' => $lang, 'title' => $title]); |
||
222 | } else { |
||
223 | $this->colorCli->warning("Duplicate: $id"); |
||
224 | } |
||
225 | } |
||
226 | |||
227 | private function insertAniDBInfoEps($aniDbId, array $AniDBInfoArray = []): string |
||
228 | { |
||
229 | AnidbInfo::query() |
||
230 | ->insert( |
||
231 | [ |
||
232 | 'anidbid' => $aniDbId, |
||
233 | 'type' => $AniDBInfoArray['type'], |
||
234 | 'startdate' => $AniDBInfoArray['startdate'], |
||
235 | 'enddate' => $AniDBInfoArray['enddate'], |
||
236 | 'related' => $AniDBInfoArray['enddate'], |
||
237 | 'similar' => $AniDBInfoArray['similar'], |
||
238 | 'creators' => $AniDBInfoArray['creators'], |
||
239 | 'description' => $AniDBInfoArray['description'], |
||
240 | 'rating' => $AniDBInfoArray['rating'], |
||
241 | 'picture' => $AniDBInfoArray['picture'], |
||
242 | 'categories' => $AniDBInfoArray['categories'], |
||
243 | 'characters' => $AniDBInfoArray['characters'], |
||
244 | 'updated' => now(), |
||
245 | ] |
||
246 | ); |
||
247 | if (! empty($AniDBInfoArray['epsarr'])) { |
||
248 | $this->insertAniDBEpisodes($aniDbId, $AniDBInfoArray['epsarr']); |
||
249 | } |
||
250 | |||
251 | return $AniDBInfoArray['picture']; |
||
252 | } |
||
253 | |||
254 | private function insertAniDBEpisodes($aniDbId, array $episodeArr = []): void |
||
255 | { |
||
256 | if (! empty($episodeArr)) { |
||
257 | foreach ($episodeArr as $episode) { |
||
258 | AnidbEpisode::insertOrIgnore( |
||
259 | [ |
||
260 | 'anidbid' => $aniDbId, |
||
261 | 'episodeid' => $episode['episode_id'], |
||
262 | 'episode_no' => $episode['episode_no'], |
||
263 | 'episode_title' => $episode['episode_title'], |
||
264 | 'airdate' => $episode['airdate'], |
||
265 | ] |
||
266 | ); |
||
267 | } |
||
268 | } |
||
269 | } |
||
270 | |||
271 | /** |
||
272 | * Grabs AniDB Full Dump XML and inserts it into anidb table. |
||
273 | */ |
||
274 | private function populateMainTable(): void |
||
329 | ); |
||
330 | } |
||
331 | } |
||
332 | |||
333 | /** |
||
334 | * Directs flow for populating the AniDB Info/Episodes table. |
||
335 | * |
||
336 | * |
||
337 | * @throws \Exception |
||
338 | */ |
||
339 | private function populateInfoTable(string $aniDbId = ''): void |
||
340 | { |
||
341 | if (empty($aniDbId)) { |
||
342 | $anidbIds = AnidbTitle::query() |
||
343 | ->selectRaw('DISTINCT anidb_titles.anidbid') |
||
344 | ->leftJoin('anidb_info as ai', 'ai.anidbid', '=', 'anidb_titles.anidbid') |
||
345 | ->whereNull('ai.updated') |
||
346 | ->get(); |
||
347 | |||
348 | foreach ($anidbIds as $anidb) { |
||
349 | $AniDBAPIArray = $this->getAniDbAPI($anidb['anidbid']); |
||
350 | |||
351 | if ($this->banned) { |
||
352 | $this->colorCli->error( |
||
353 | 'AniDB Banned, import will fail, please wait 24 hours before retrying.' |
||
354 | ); |
||
355 | exit; |
||
356 | } |
||
357 | |||
358 | if ($AniDBAPIArray === false && $this->echooutput) { |
||
359 | $this->colorCli->info( |
||
360 | 'Anime ID: '.$anidb['anidbid'].' not available for update yet.' |
||
361 | ); |
||
362 | } else { |
||
363 | $this->updateAniChildTables($anidb['anidbid'], $AniDBAPIArray); |
||
364 | } |
||
365 | sleep(random_int(120, 240)); |
||
366 | } |
||
367 | } else { |
||
368 | $AniDBAPIArray = $this->getAniDbAPI($aniDbId); |
||
369 | |||
370 | if ($this->banned) { |
||
371 | $this->colorCli->error( |
||
372 | 'AniDB Banned, import will fail, please wait 24 hours before retrying.' |
||
373 | ); |
||
374 | exit; |
||
375 | } |
||
376 | |||
377 | if ($AniDBAPIArray === false && $this->echooutput) { |
||
378 | $this->colorCli->info( |
||
379 | 'Anime ID: '.$aniDbId.' not available for update yet.' |
||
380 | ); |
||
381 | } else { |
||
382 | $this->updateAniChildTables($aniDbId, $AniDBAPIArray); |
||
383 | } |
||
384 | } |
||
385 | } |
||
386 | |||
387 | /** |
||
388 | * Sets the database time for last full AniDB update. |
||
389 | */ |
||
390 | private function setLastUpdated(): void |
||
393 | } |
||
394 | |||
395 | private function updateAniDBInfoEps($aniDbId, array $AniDBInfoArray = []): string |
||
420 | } |
||
421 | |||
422 | private function updateAniChildTables($aniDbId, array $AniDBInfoArray = []): void |
||
437 | ); |
||
438 | } |
||
439 | } |
||
440 | } |
||
441 |