Passed
Push — feature/super-model ( 9eaa75...66e03d )
by axel
01:46
created

InfoModel::getCleanInfo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 2
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace MalScraper\Model\General;
4
5
use MalScraper\Helper\Helper;
6
use MalScraper\Model\MainModel;
7
8
/**
9
 * InfoModel class.
10
 */
11
class InfoModel extends MainModel
12
{
13
    /**
14
     * Type of info. Either anime or manga.
15
     *
16
     * @var string
17
     */
18
    private $_type;
19
20
    /**
21
     * Id of the anime or manga.
22
     *
23
     * @var string|int
24
     */
25
    private $_id;
26
27
    /**
28
     * Default constructor.
29
     *
30
     * @param string     $type
31
     * @param string|int $id
32
     * @param string     $parserArea
33
     *
34
     * @return void
35
     */
36
    public function __construct($type, $id, $parserArea = '#content')
37
    {
38
        $this->_type = $type;
39
        $this->_id = $id;
40
        $this->_url = $this->_myAnimeListUrl.'/'.$type.'/'.$id;
41
        $this->_parserArea = $parserArea;
42
43
        parent::errorCheck($this);
44
    }
45
46
    /**
47
     * Default call.
48
     *
49
     * @param string $method
50
     * @param array  $arguments
51
     *
52
     * @return array|string|int
53
     */
54
    public function __call($method, $arguments)
55
    {
56
        if ($this->_error) {
57
            return $this->_error;
58
        }
59
60
        return call_user_func_array([$this, $method], $arguments);
61
    }
62
63
    /**
64
     * Get anime/manga id.
65
     *
66
     * @return string
67
     */
68
    private function getId()
69
    {
70
        return $this->_id;
71
    }
72
73
    /**
74
     * Get anime/manga cover.
75
     *
76
     * @return string
77
     */
78
    private function getCover()
79
    {
80
        $anime_cover = $this->_parser->find('img.ac', 0);
81
82
        return $anime_cover ? $anime_cover->src : '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return $anime_cover ? $anime_cover->src : '' also could return the type boolean which is incompatible with the documented return type string.
Loading history...
83
    }
84
85
    /**
86
     * Get anime/manga title.
87
     *
88
     * @return string
89
     */
90
    private function getTitle()
91
    {
92
        $anime_cover = $this->_parser->find('img.ac', 0);
93
94
        return $anime_cover ? $anime_cover->alt : '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return $anime_cover ? $anime_cover->alt : '' also could return the type boolean which is incompatible with the documented return type string.
Loading history...
95
    }
96
97
    /**
98
     * Get anime/manga alternative title.
99
     *
100
     * @return array
101
     */
102
    private function getTitle2()
103
    {
104
        $title2 = [];
105
106
        $anime_info = $this->_parser->find('.js-scrollfix-bottom', 0);
107
108
        preg_match('/(English:<\/span>)([^<]*)/', $anime_info->innertext, $english);
109
        $title2['english'] = trim($english ? $english[2] : '');
110
111
        preg_match('/(Synonyms:<\/span>)([^<]*)/', $anime_info->innertext, $synonym);
112
        $title2['synonym'] = trim($synonym ? $synonym[2] : '');
113
114
        preg_match('/(Japanese:<\/span>)([^<]*)/', $anime_info->innertext, $japanese);
115
        $title2['japanese'] = trim($japanese ? $japanese[2] : '');
116
117
        return $title2;
118
    }
119
120
    /**
121
     * Get anime/manga synopsis.
122
     *
123
     * @return string
124
     */
125
    private function getSynopsis()
126
    {
127
        $synopsis = $this->_parser->find('span[itemprop=description]', 0);
128
        if ($synopsis) {
129
            $synopsis = $synopsis->plaintext;
130
131
            return trim(preg_replace('/\n[^\S\n]*/', "\n", $synopsis));
132
        } else {
133
            return;
134
        }
135
    }
136
137
    /**
138
     * Get anime/manga score.
139
     *
140
     * @return string
141
     */
142
    private function getScore()
143
    {
144
        $score = $this->_parser->find('div[class="fl-l score"]', 0)->plaintext;
145
        $score = trim($score);
146
147
        return $score != 'N/A' ? $score : null;
148
    }
149
150
    /**
151
     * Get number of user who give score.
152
     *
153
     * @return string
154
     */
155
    private function getVoter()
156
    {
157
        $voter = $this->_parser->find('div[class="fl-l score"]', 0)->getAttribute('data-user');
158
159
        return trim(str_replace(['users', 'user', ','], '', $voter));
160
    }
161
162
    /**
163
     * Get anime/manga rank.
164
     *
165
     * @return string
166
     */
167
    private function getRank()
168
    {
169
        $rank = $this->_parser->find('span[class="numbers ranked"] strong', 0)->plaintext;
170
        $rank = $rank != 'N/A' ? $rank : '';
171
172
        return str_replace('#', '', $rank);
173
    }
174
175
    /**
176
     * Get anime/manga popularity.
177
     *
178
     * @return string
179
     */
180
    private function getPopularity()
181
    {
182
        $popularity = $this->_parser->find('span[class="numbers popularity"] strong', 0)->plaintext;
183
184
        return str_replace('#', '', $popularity);
185
    }
186
187
    /**
188
     * Get number of user who watch/read the anime/manga.
189
     *
190
     * @return string
191
     */
192
    private function getMembers()
193
    {
194
        $member = $this->_parser->find('span[class="numbers members"] strong', 0)->plaintext;
195
196
        return str_replace(',', '', $member);
197
    }
198
199
    /**
200
     * Get number of user who favorite the anime/manga.
201
     *
202
     * @return string
203
     */
204
    private function getFavorite()
205
    {
206
        $favorite = $this->_parser->find('div[data-id=info2]', 0)->next_sibling()->next_sibling()->next_sibling();
207
        $favorite_title = $favorite->find('span', 0)->plaintext;
208
        $favorite = $favorite->plaintext;
209
        $favorite = trim(str_replace($favorite_title, '', $favorite));
210
        $favorite = str_replace(',', '', $favorite);
211
212
        return preg_replace("/([\s])+/", ' ', $favorite);
213
    }
214
215
    /**
216
     * Get anime/manga detail info.
217
     *
218
     * @return array
219
     */
220
    private function getOtherInfo()
221
    {
222
        $info = [];
223
224
        $anime_info = $this->_parser->find('.js-scrollfix-bottom', 0);
225
        $other_info = (count($anime_info->find('h2')) > 2) ? $anime_info->find('h2', 1) : $anime_info->find('h2', 0);
0 ignored issues
show
Bug introduced by
It seems like $anime_info->find('h2') can also be of type simplehtmldom_1_5\simple_html_dom_node; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

225
        $other_info = (count(/** @scrutinizer ignore-type */ $anime_info->find('h2')) > 2) ? $anime_info->find('h2', 1) : $anime_info->find('h2', 0);
Loading history...
226
        $next_info = $other_info->next_sibling();
0 ignored issues
show
Bug introduced by
The method next_sibling() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

226
        /** @scrutinizer ignore-call */ 
227
        $next_info = $other_info->next_sibling();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
227
        while (true) {
228
            $info_type = $next_info->find('span', 0)->plaintext;
229
230
            $clean_info_type = strtolower(str_replace(': ', '', $info_type));
231
            $clean_info_value = $this->getCleanInfo($info_type, $next_info);
232
            $clean_info_value = $this->getCleanerInfo1($clean_info_type, $clean_info_value);
233
            $clean_info_value = $this->getCleanerInfo2($next_info, $clean_info_type, $clean_info_value);
0 ignored issues
show
Bug introduced by
It seems like $clean_info_value can also be of type array; however, parameter $clean_info_value of MalScraper\Model\General...odel::getCleanerInfo2() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

233
            $clean_info_value = $this->getCleanerInfo2($next_info, $clean_info_type, /** @scrutinizer ignore-type */ $clean_info_value);
Loading history...
234
235
            $info[$clean_info_type] = $clean_info_value;
236
237
            $next_info = $next_info->next_sibling();
238
            if ($next_info->tag == 'h2' || $next_info->tag == 'br') {
239
                break;
240
            }
241
        }
242
243
        return $info;
244
    }
245
246
    /**
247
     * Get clean other info.
248
     *
249
     * @param string $info_type
250
     * @param \simplehtmldom_1_5\simple_html_dom $next_info
251
     *
252
     * @return string
253
     */
254
    private function getCleanInfo($info_type, $next_info)
255
    {
256
        $info_value = $next_info->plaintext;
257
        $clean_info_value = trim(str_replace($info_type, '', $info_value));
258
        $clean_info_value = preg_replace("/([\s])+/", ' ', $clean_info_value);
259
        return str_replace([', add some', '?', 'Not yet aired', 'Unknown'], '', $clean_info_value);
260
    }
261
262
    /**
263
     * Get cleaner other info.
264
     *
265
     * @param string $clean_info_type
266
     * @param string $clean_info_value
267
     *
268
     * @return string|array
269
     */
270
    private function getCleanerInfo1($clean_info_type, $clean_info_value)
271
    {
272
        if ($clean_info_type == 'published' || $clean_info_type == 'aired') {
273
            $start_air = $end_air = '';
274
            if ($clean_info_value != 'Not available') {
275
                $parsed_airing = explode(' to ', $clean_info_value);
276
                $start_air = ($parsed_airing[0] != '?') ? $parsed_airing[0] : '';
277
                if (count($parsed_airing) > 1) {
278
                    $end_air = ($parsed_airing[1] != '?') ? $parsed_airing[1] : '';
279
                }
280
            }
281
282
            $clean_info_value = [];
283
            $clean_info_value['start'] = $start_air;
284
            $clean_info_value['end'] = $end_air;
285
        }
286
        return $clean_info_value;
287
    }
288
289
    /**
290
     * Get cleaner other info.
291
     *
292
     * @param \simplehtmldom_1_5\simple_html_dom $next_info
293
     * @param string $clean_info_type
294
     * @param string $clean_info_value
295
     *
296
     * @return string|array
297
     */
298
    private function getCleanerInfo2($next_info, $clean_info_type, $clean_info_value)
299
    {
300
        if ($clean_info_type == 'producers'
301
            || $clean_info_type == 'licensors'
302
            || $clean_info_type == 'studios'
303
            || $clean_info_type == 'genres'
304
            || $clean_info_type == 'authors'
305
        ) {
306
            $info_temp = [];
307
            $info_temp_index = 0;
308
            if ($clean_info_value != 'None found') {
309
                foreach ($next_info->find('a') as $each_info) {
310
                    $temp_id = explode('/', $each_info->href);
311
                    $info_temp[$info_temp_index]['id'] = $clean_info_type == 'authors' ? $temp_id[2] : $temp_id[3];
312
                    $info_temp[$info_temp_index]['name'] = $each_info->plaintext;
313
                    $info_temp_index++;
314
                }
315
            }
316
            return $info_temp;
317
        }
318
        return $clean_info_value;
319
    }
320
321
    /**
322
     * Get anime/manga relation.
323
     *
324
     * @return array
325
     */
326
    private function getRelated()
327
    {
328
        $related = [];
329
        $related_area = $this->_parser->find('.anime_detail_related_anime', 0);
330
        if ($related_area) {
331
            foreach ($related_area->find('tr') as $rel) {
332
                $rel_type = $rel->find('td', 0)->plaintext;
333
                $rel_type = trim(strtolower(str_replace(':', '', $rel_type)));
334
335
                $each_rel = [];
336
                $each_rel_index = 0;
337
                $rel_anime = $rel->find('td', 1);
338
                foreach ($rel_anime->find('a') as $r) {
339
                    $each_rel[$each_rel_index] = $this->getRelatedDetail($r);
340
                    $each_rel_index++;
341
                }
342
343
                $related[$rel_type] = $each_rel;
344
            }
345
        }
346
347
        return $related;
348
    }
349
350
    /**
351
     * Get related detail.
352
     *
353
     * @param \simplehtmldom_1_5\simple_html_dom $r
354
     *
355
     * @return array
356
     */
357
    private function getRelatedDetail($r)
358
    {
359
        $related = [];
360
        $rel_anime_link = $r->href;
361
        $separated_anime_link = explode('/', $rel_anime_link);
362
363
        $related['id'] = $separated_anime_link[2];
364
        $related['title'] = $r->plaintext;
365
        $related['type'] = $separated_anime_link[1];
366
367
        return $related;
368
    }
369
370
    /**
371
     * Get anime/manga character and its va.
372
     *
373
     * @return array
374
     */
375
    private function getCharacter()
376
    {
377
        $character = [];
378
        $char_index = 0;
379
        $character_area = $this->_parser->find('div[class^=detail-characters-list]', 0);
380
        if ($character_area) {
381
            $character_list = [
382
                $character_area->find('div[class*=fl-l]', 0),
383
                $character_area->find('div[class*=fl-r]', 0),
384
            ];
385
            foreach ($character_list as $character_side) {
386
                if ($character_side) {
387
                    foreach ($character_side->find('table[width=100%]') as $each_char) {
388
                        $char = $each_char->find('tr td', 1);
389
                        $va = $each_char->find('table td', 0);
390
391
                        $character[$char_index]['id'] = $this->getStaffId($char);
392
                        $character[$char_index]['name'] = $this->getStaffName($char);
393
                        $character[$char_index]['role'] = $this->getStaffRole($char);
394
                        $character[$char_index]['image'] = $this->getStaffImage($each_char);
395
396
                        $character[$char_index]['va_id'] = $character[$char_index]['va_name'] = '';
397
                        $character[$char_index]['va_role'] = $character[$char_index]['va_image'] = '';
398
399
                        if ($va) {
400
                            $character[$char_index]['va_id'] = $this->getStaffId($va);
401
                            $character[$char_index]['va_name'] = $this->getStaffName($va, true);
402
                            $character[$char_index]['va_role'] = $this->getStaffRole($va);
403
                            $character[$char_index]['va_image'] = $this->getStaffImage($each_char, true);
404
                        }
405
406
                        $char_index++;
407
                    }
408
                }
409
            }
410
        }
411
412
        return $character;
413
    }
414
415
    /**
416
     * Get anime/manga staff involved.
417
     *
418
     * @return array
419
     */
420
    private function getStaff()
421
    {
422
        $staff = [];
423
        $staff_index = 0;
424
        $staff_area = $this->_parser->find('div[class^=detail-characters-list]', 1);
425
        if ($staff_area) {
426
            $staff_list = [
427
                $staff_area->find('div[class*=fl-l]', 0),
428
                $staff_area->find('div[class*=fl-r]', 0),
429
            ];
430
            foreach ($staff_list as $staff_side) {
431
                if ($staff_side) {
432
                    foreach ($staff_side->find('table[width=100%]') as $each_staff) {
433
                        $st = $each_staff->find('tr td', 1);
434
435
                        $staff[$staff_index]['id'] = $this->getStaffId($st);
436
                        $staff[$staff_index]['name'] = $this->getStaffName($st);
437
                        $staff[$staff_index]['role'] = $this->getStaffRole($st);
438
                        $staff[$staff_index]['image'] = $this->getStaffImage($each_staff);
439
440
                        $staff_index++;
441
                    }
442
                }
443
            }
444
        }
445
446
        return $staff;
447
    }
448
449
    /**
450
     * Get staff id.
451
     *
452
     * @param \simplehtmldom_1_5\simple_html_dom $st
453
     *
454
     * @return string
455
     */
456
    private function getStaffId($st)
457
    {
458
        $staff_id = $st->find('a', 0)->href;
459
        $staff_id = explode('/', $staff_id);
460
461
        return $staff_id[4];
462
    }
463
464
    /**
465
     * Get staff name.
466
     *
467
     * @param \simplehtmldom_1_5\simple_html_dom $st
468
     * @param bool                               $va (Optional)
469
     *
470
     * @return string
471
     */
472
    private function getStaffName($st, $va = false)
473
    {
474
        if ($va) {
475
            return $st->find('a', 0)->plaintext;
476
        }
477
478
        return trim(preg_replace('/\s+/', ' ', $st->find('a', 0)->plaintext));
479
    }
480
481
    /**
482
     * Get staff role.
483
     *
484
     * @param \simplehtmldom_1_5\simple_html_dom $st
485
     *
486
     * @return string
487
     */
488
    private function getStaffRole($st)
489
    {
490
        return trim($st->find('small', 0)->plaintext);
491
    }
492
493
    /**
494
     * Get staff image.
495
     *
496
     * @param \simplehtmldom_1_5\simple_html_dom $each_staff
497
     * @param bool                               $va         (Optional)
498
     *
499
     * @return string
500
     */
501
    private function getStaffImage($each_staff, $va = false)
502
    {
503
        if ($va) {
504
            $staff_image = $each_staff->find('table td', 1)->find('img', 0)->getAttribute('data-src');
505
        } else {
506
            $staff_image = $each_staff->find('tr td', 0)->find('img', 0)->getAttribute('data-src');
507
        }
508
509
        return Helper::imageUrlCleaner($staff_image);
510
    }
511
512
    /**
513
     * Get anime/manga opening and ending song.
514
     *
515
     * @return array
516
     */
517
    private function getSong()
518
    {
519
        $song = [];
520
        $song_area = $this->_parser->find('div[class*="theme-songs opnening"]', 0);
521
        if ($song_area) {
522
            foreach ($song_area->find('span.theme-song') as $each_song) {
523
                $each_song = trim(preg_replace('/#\d*:\s/', '', $each_song->plaintext));
524
                $song['opening'][] = $each_song;
525
            }
526
        }
527
528
        $song_area = $this->_parser->find('div[class*="theme-songs ending"]', 0);
529
        if ($song_area) {
530
            foreach ($song_area->find('span.theme-song') as $each_song) {
531
                $each_song = trim(preg_replace('/#\d*:\s/', '', $each_song->plaintext));
532
                $song['closing'][] = $each_song;
533
            }
534
        }
535
536
        return $song;
537
    }
538
539
    /**
540
     * Get anime/manga all information.
541
     *
542
     * @return array
543
     */
544
    private function getAllInfo()
545
    {
546
        $data = [
547
            'id'        => $this->getId(),
548
            'cover'     => $this->getCover(),
549
            'title'     => $this->getTitle(),
550
            'title2'    => $this->getTitle2(),
551
            'synopsis'  => $this->getSynopsis(),
552
            'score'     => $this->getScore(),
553
            'voter'     => $this->getVoter(),
554
            'rank'      => $this->getRank(),
555
            'popularity'=> $this->getPopularity(),
556
            'members'   => $this->getMembers(),
557
            'favorite'  => $this->getFavorite(),
558
        ];
559
560
        $data = array_merge($data, $this->getOtherInfo());
561
562
        $data2 = [
563
            'related'   => $this->getRelated(),
564
            'character' => $this->getCharacter(),
565
            'staff'     => $this->getStaff(),
566
            'song'      => $this->getSong(),
567
        ];
568
569
        $data = array_merge($data, $data2);
570
571
        return $data;
572
    }
573
}
574