Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Filler 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
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 Filler, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
23 | class Filler extends FillerPlugin |
||
24 | { |
||
25 | /** |
||
26 | * Name. |
||
27 | * |
||
28 | * @var string |
||
29 | */ |
||
30 | const NAME = 'world-art'; |
||
31 | |||
32 | /** |
||
33 | * Title. |
||
34 | * |
||
35 | * @var string |
||
36 | */ |
||
37 | const TITLE = 'World-Art.ru'; |
||
38 | |||
39 | /** |
||
40 | * XPath for fill item. |
||
41 | * |
||
42 | * @var string |
||
43 | */ |
||
44 | const XPATH_FOR_FILL = '//center/table[@height="58%"]/tr/td/table[1]/tr/td'; |
||
45 | |||
46 | /** |
||
47 | * Item type animation. |
||
48 | * |
||
49 | * @var string |
||
50 | */ |
||
51 | const ITEM_TYPE_ANIMATION = 'animation'; |
||
52 | |||
53 | /** |
||
54 | * Item type cinema. |
||
55 | * |
||
56 | * @var string |
||
57 | */ |
||
58 | const ITEM_TYPE_CINEMA = 'cinema'; |
||
59 | |||
60 | /** |
||
61 | * Browser. |
||
62 | * |
||
63 | * @var \AnimeDb\Bundle\WorldArtFillerBundle\Service\Browser |
||
64 | */ |
||
65 | protected $browser; |
||
66 | |||
67 | /** |
||
68 | * Doctrine. |
||
69 | * |
||
70 | * @var \Doctrine\Bundle\DoctrineBundle\Registry |
||
71 | */ |
||
72 | protected $doctrine; |
||
73 | |||
74 | /** |
||
75 | * Downloader. |
||
76 | * |
||
77 | * @var \AnimeDb\Bundle\AppBundle\Service\Downloader |
||
78 | */ |
||
79 | protected $downloader; |
||
80 | |||
81 | /** |
||
82 | * World-Art genres. |
||
83 | * |
||
84 | * @var array |
||
85 | */ |
||
86 | protected $genres = [ |
||
87 | 'боевик' => 'Action', |
||
88 | 'фильм действия' => 'Action', |
||
89 | 'боевые искусства' => 'Martial arts', |
||
90 | 'вампиры' => 'Vampire', |
||
91 | 'война' => 'War', |
||
92 | 'детектив' => 'Detective', |
||
93 | 'для детей' => 'Kids', |
||
94 | 'дзёсэй' => 'Josei', |
||
95 | 'драма' => 'Drama', |
||
96 | 'история' => 'History', |
||
97 | 'киберпанк' => 'Cyberpunk', |
||
98 | 'комедия' => 'Comedy', |
||
99 | 'махо-сёдзё' => 'Mahoe shoujo', |
||
100 | 'меха' => 'Mecha', |
||
101 | 'мистерия' => 'Mystery', |
||
102 | 'мистика' => 'Mystery', |
||
103 | 'музыкальный' => 'Music', |
||
104 | 'образовательный' => 'Educational', |
||
105 | 'пародия' => 'Parody', |
||
106 | 'cтимпанк' => 'Steampunk', |
||
107 | 'паропанк' => 'Steampunk', |
||
108 | 'повседневность' => 'Slice of life', |
||
109 | 'полиция' => 'Police', |
||
110 | 'постапокалиптика' => 'Apocalyptic fiction', |
||
111 | 'приключения' => 'Adventure', |
||
112 | 'приключенческий фильм' => 'Adventure', |
||
113 | 'психология' => 'Psychological', |
||
114 | 'романтика' => 'Romance', |
||
115 | 'самурайский боевик' => 'Samurai', |
||
116 | 'сёдзё' => 'Shoujo', |
||
117 | 'сёдзё-ай' => 'Shoujo-ai', |
||
118 | 'сёнэн' => 'Shounen', |
||
119 | 'сёнэн-ай' => 'Shounen-ai', |
||
120 | 'сказка' => 'Fable', |
||
121 | 'спорт' => 'Sport', |
||
122 | 'сэйнэн' => 'Senen', |
||
123 | 'триллер' => 'Thriller', |
||
124 | 'школа' => 'School', |
||
125 | 'фантастика' => 'Sci-fi', |
||
126 | 'кинофантазия' => 'Fantastic', |
||
127 | 'фэнтези' => 'Fantasy', |
||
128 | 'эротика' => 'Erotica', |
||
129 | 'этти' => 'Ecchi', |
||
130 | 'ужасы' => 'Horror', |
||
131 | 'хентай' => 'Hentai', |
||
132 | 'юри' => 'Yuri', |
||
133 | 'яой' => 'Yaoi', |
||
134 | ]; |
||
135 | |||
136 | /** |
||
137 | * World-Art types. |
||
138 | * |
||
139 | * @var array |
||
140 | */ |
||
141 | protected $types = [ |
||
142 | 'ТВ' => 'tv', |
||
143 | 'ТВ-спэшл' => 'special', |
||
144 | 'OVA' => 'ova', |
||
145 | 'ONA' => 'ona', |
||
146 | 'OAV' => 'ova', |
||
147 | 'полнометражный фильм' => 'feature', |
||
148 | 'короткометражный фильм' => 'featurette', |
||
149 | 'музыкальное видео' => 'music', |
||
150 | 'рекламный ролик' => 'commercial', |
||
151 | ]; |
||
152 | |||
153 | /** |
||
154 | * World-Art studios. |
||
155 | * |
||
156 | * @var array |
||
157 | */ |
||
158 | protected $studios = [ |
||
159 | 1 => 'Studio Ghibli', |
||
160 | 3 => 'Gainax', |
||
161 | 4 => 'AIC', |
||
162 | 6 => 'KSS', |
||
163 | 14 => 'TMS Entertainment', |
||
164 | 20 => 'Bones', |
||
165 | 21 => 'Clamp', |
||
166 | 22 => 'Studio DEEN', |
||
167 | 24 => 'J.C.Staff', |
||
168 | 25 => 'Madhouse', |
||
169 | 26 => 'animate', |
||
170 | 29 => 'OLM, Inc.', |
||
171 | 30 => 'Tezuka Productions', |
||
172 | 31 => 'Production I.G', |
||
173 | 32 => 'Gonzo', |
||
174 | 34 => 'Sunrise', |
||
175 | 37 => 'Agent 21', |
||
176 | 41 => 'Toei Animation', |
||
177 | 44 => 'APPP', |
||
178 | 54 => 'Radix', |
||
179 | 56 => 'Pierrot', |
||
180 | 59 => 'XEBEC', |
||
181 | 64 => 'Satelight', |
||
182 | 74 => 'Oh! Production', |
||
183 | 78 => 'Triangle Staff', |
||
184 | 82 => 'Bee Train', |
||
185 | 84 => 'Animax', |
||
186 | 87 => 'Daume', |
||
187 | 89 => 'Kitty Films', |
||
188 | 92 => 'Ajia-do', |
||
189 | 96 => 'Studio 4°C', |
||
190 | 106 => 'CoMix Wave Inc.', |
||
191 | 116 => 'Fox Animation Studios', |
||
192 | 117 => 'Blue Sky Studios', |
||
193 | 118 => 'Pacific Data Images', |
||
194 | 120 => 'Pixar', |
||
195 | 152 => 'Mushi Production', |
||
196 | 154 => 'Aardman Animations', |
||
197 | 159 => 'DR Movie', |
||
198 | 171 => 'Tatsunoko Productions', |
||
199 | 178 => 'Paramount Animation', |
||
200 | 193 => 'Hal Film Maker', |
||
201 | 198 => 'Studio Fantasia', |
||
202 | 210 => 'Arms Corporation', |
||
203 | 212 => 'Green Bunny', |
||
204 | 236 => 'Pink Pineapple', |
||
205 | 244 => 'Production Reed', |
||
206 | // reverse links |
||
207 | 250 => 'Melnitsa Animation Studio', |
||
208 | 252 => 'Nippon Animation', |
||
209 | 255 => 'Artland', |
||
210 | 267 => 'SHAFT', |
||
211 | 278 => 'March Entertainment', |
||
212 | 296 => 'Gallop', |
||
213 | 315 => 'DreamWorks Animation', |
||
214 | 351 => 'TNK', |
||
215 | 398 => 'A.C.G.T.', |
||
216 | 436 => 'Kyoto Animation', |
||
217 | 439 => 'Studio Comet', |
||
218 | 463 => 'Magic Bus', |
||
219 | 639 => 'Industrial Light & Magic', |
||
220 | 689 => 'ZEXCS', |
||
221 | 724 => 'Six Point Harness', |
||
222 | 753 => 'Pentamedia Graphics', |
||
223 | 795 => 'Rough Draft Studios', |
||
224 | 802 => 'Shin-Ei Animation', |
||
225 | 821 => 'Warner Bros. Animation', |
||
226 | 1066 => 'Animal Logic', |
||
227 | 1161 => 'Marvel Animation Studios', |
||
228 | 1168 => 'Klasky Csupo', |
||
229 | 1654 => 'Digital Frontier', |
||
230 | 1663 => 'Mac Guff', |
||
231 | 1689 => 'Manglobe', |
||
232 | 1778 => 'CinéGroupe', |
||
233 | 1889 => 'Film Roman, Inc.', |
||
234 | 1890 => 'AKOM', |
||
235 | 1901 => 'Brain\'s Base', |
||
236 | 1961 => 'feel.', |
||
237 | 2058 => 'Eiken', |
||
238 | 2229 => 'Studio Hibari', |
||
239 | 2370 => 'IMAGIN', |
||
240 | 2379 => 'Folimage', |
||
241 | 2381 => 'DisneyToon Studios', |
||
242 | 2491 => 'ufotable', |
||
243 | 3058 => 'Asahi Production', |
||
244 | 3096 => 'Mook Animation', |
||
245 | 3113 => 'Walt Disney Television Animation', |
||
246 | 3420 => 'Metro-Goldwyn-Mayer Animation', |
||
247 | 3530 => 'Seven Arcs', |
||
248 | 3742 => 'Nomad', |
||
249 | 3748 => 'Dygra Films', |
||
250 | 3773 => 'Dogakobo', |
||
251 | 3816 => 'EMation', |
||
252 | 4013 => 'Toon City', |
||
253 | 5423 => 'O Entertainment/Omation Animation Studio', |
||
254 | 6081 => 'Sony Pictures Animation', |
||
255 | 6474 => 'Wang Film Productions', |
||
256 | 6475 => 'Creative Capers Entertainment', |
||
257 | 6701 => 'Arc Productions', |
||
258 | 7092 => 'Millimages', |
||
259 | 7194 => 'Mondo TV', |
||
260 | 7298 => 'A-1 Pictures Inc.', |
||
261 | 7372 => 'Diomedea', |
||
262 | 7388 => 'Williams Street Studios', |
||
263 | 7801 => 'National Film Board of Canada', |
||
264 | 7933 => 'Titmouse', |
||
265 | 8590 => 'Rhythm and Hues Studios', |
||
266 | 8639 => 'Bagdasarian Productions', |
||
267 | 9298 => 'Toonz', |
||
268 | 9900 => 'Savage Studios Ltd.', |
||
269 | 10664 => 'A. Film', |
||
270 | 11077 => 'Vanguard Animation', |
||
271 | 11213 => 'bolexbrothers', |
||
272 | 11827 => 'Zinkia Entertainment', |
||
273 | 12209 => 'P.A. Works', |
||
274 | 12268 => 'Universal Animation Studios', |
||
275 | 12280 => 'Reel FX', |
||
276 | 12281 => 'Walt Disney Animation Studios', |
||
277 | 12299 => 'LAIKA', |
||
278 | 12825 => 'White Fox', |
||
279 | 13269 => 'David Production', |
||
280 | 13301 => 'Silver Link', |
||
281 | 13329 => 'Kinema Citrus', |
||
282 | 13906 => 'GoHands', |
||
283 | 13957 => 'Khara', |
||
284 | 14617 => 'Ordet', |
||
285 | 15102 => 'TYO Animations', |
||
286 | 15334 => 'Dong Woo Animation', |
||
287 | 16112 => 'Studio Gokumi', |
||
288 | 16433 => 'Nickelodeon Animation Studios', |
||
289 | 16961 => 'Renegade Animation', |
||
290 | 17049 => 'Curious Pictures', |
||
291 | 17235 => 'Trigger', |
||
292 | 17322 => 'Wit Studio', |
||
293 | ]; |
||
294 | |||
295 | /** |
||
296 | * Construct. |
||
297 | * |
||
298 | * @param \AnimeDb\Bundle\WorldArtFillerBundle\Service\Browser $browser |
||
299 | * @param \Doctrine\Bundle\DoctrineBundle\Registry $doctrine |
||
300 | * @param \AnimeDb\Bundle\AppBundle\Service\Downloader $downloader |
||
301 | */ |
||
302 | public function __construct(Browser $browser, Registry $doctrine, Downloader $downloader) |
||
308 | |||
309 | /** |
||
310 | * Get name. |
||
311 | * |
||
312 | * @return string |
||
313 | */ |
||
314 | public function getName() |
||
318 | |||
319 | /** |
||
320 | * Get title. |
||
321 | * |
||
322 | * @return string |
||
323 | */ |
||
324 | public function getTitle() |
||
328 | |||
329 | /** |
||
330 | * Get form. |
||
331 | * |
||
332 | * @return \AnimeDb\Bundle\WorldArtFillerBundle\Form\Type\Filler |
||
333 | */ |
||
334 | public function getForm() |
||
338 | |||
339 | /** |
||
340 | * Build menu for plugin. |
||
341 | * |
||
342 | * @param \Knp\Menu\ItemInterface $item |
||
343 | * |
||
344 | * @return \Knp\Menu\ItemInterface |
||
345 | */ |
||
346 | public function buildMenu(ItemInterface $item) |
||
351 | |||
352 | /** |
||
353 | * Fill item from source. |
||
354 | * |
||
355 | * @param array $data |
||
356 | * |
||
357 | * @return \AnimeDb\Bundle\CatalogBundle\Entity\Item|null |
||
358 | */ |
||
359 | public function fill(array $data) |
||
439 | |||
440 | /** |
||
441 | * Get element attributes as array. |
||
442 | * |
||
443 | * @param \DOMElement $element |
||
444 | * |
||
445 | * @return array |
||
446 | */ |
||
447 | private function getAttrAsArray(\DOMElement $element) |
||
448 | { |
||
449 | $return = []; |
||
450 | for ($i = 0; $i < $element->attributes->length; ++$i) { |
||
451 | $return[$element->attributes->item($i)->nodeName] = $element->attributes->item($i)->nodeValue; |
||
452 | } |
||
453 | |||
454 | return $return; |
||
455 | } |
||
456 | |||
457 | /** |
||
458 | * Get cover from source id. |
||
459 | * |
||
460 | * @param \AnimeDb\Bundle\CatalogBundle\Entity\Item $item |
||
461 | * @param string $id |
||
462 | * @param string $type |
||
463 | * |
||
464 | * @return bool |
||
465 | */ |
||
466 | private function setCover(Item $item, $id, $type) |
||
467 | { |
||
468 | $item->setCover(self::NAME.'/'.$id.'/1.jpg'); |
||
469 | |||
470 | return $this->uploadImage($this->getCoverUrl($id, $type), $item); |
||
471 | } |
||
472 | |||
473 | /** |
||
474 | * Fill head data. |
||
475 | * |
||
476 | * @param \AnimeDb\Bundle\CatalogBundle\Entity\Item $item |
||
477 | * @param \DOMXPath $xpath |
||
478 | * @param \DOMElement $head |
||
479 | * |
||
480 | * @return \AnimeDb\Bundle\CatalogBundle\Entity\Item |
||
481 | */ |
||
482 | private function fillHeadData(Item $item, \DOMXPath $xpath, \DOMElement $head) |
||
483 | { |
||
484 | /* @var $data \DOMElement */ |
||
485 | $data = $xpath->query('font', $head)->item(0); |
||
486 | $length = $data->childNodes->length; |
||
487 | for ($i = 0; $i < $length; ++$i) { |
||
488 | if ($data->childNodes->item($i)->nodeName == 'b') { |
||
489 | switch ($data->childNodes->item($i)->nodeValue) { |
||
490 | // set country |
||
491 | case 'Производство': |
||
492 | $j = 1; |
||
493 | do { |
||
494 | if ($data->childNodes->item($i + $j)->nodeName == 'a') { |
||
495 | $country_name = trim($data->childNodes->item($i + $j)->nodeValue); |
||
496 | if ($country_name && $country = $this->getCountryByName($country_name)) { |
||
497 | $item->setCountry($country); |
||
498 | } |
||
499 | break; |
||
500 | } |
||
501 | ++$j; |
||
502 | } while ($data->childNodes->item($i + $j)->nodeName != 'br'); |
||
503 | $i += $j; |
||
504 | break; |
||
505 | // add genre |
||
506 | case 'Жанр': |
||
507 | $j = 2; |
||
508 | do { |
||
509 | if ($data->childNodes->item($i + $j)->nodeName == 'a' && |
||
510 | ($genre = $this->getGenreByName($data->childNodes->item($i + $j)->nodeValue)) |
||
511 | ) { |
||
512 | $item->addGenre($genre); |
||
513 | } |
||
514 | ++$j; |
||
515 | } while ($data->childNodes->item($i + $j)->nodeName != 'br'); |
||
516 | $i += $j; |
||
517 | break; |
||
518 | // set type and add file info |
||
519 | case 'Тип': |
||
520 | $type = $data->childNodes->item($i + 1)->nodeValue; |
||
521 | if (preg_match('/(?<type>[\w\s]+)(?: \((?:(?<episodes_number>>?\d+) эп.)?(?<file_info>.*)\))?(, (?<duration>\d{1,3}) мин\.)?$/u', $type, $match)) { |
||
522 | // add type |
||
523 | if ($type = $this->getTypeByName(trim($match['type']))) { |
||
524 | $item->setType($type); |
||
525 | } |
||
526 | // add duration |
||
527 | if (!empty($match['duration'])) { |
||
528 | $item->setDuration((int) $match['duration']); |
||
529 | } |
||
530 | // add number of episodes |
||
531 | if (!empty($match['episodes_number'])) { |
||
532 | if ($match['episodes_number'][0] == '>') { |
||
533 | $item->setEpisodesNumber(substr($match['episodes_number'], 1).'+'); |
||
534 | } else { |
||
535 | $item->setEpisodesNumber((int) $match['episodes_number']); |
||
536 | } |
||
537 | } elseif ($item->getType()->getId() != 'tv') { |
||
538 | // everything except the TV series consist of a single episode |
||
539 | $item->setEpisodesNumber(1); |
||
540 | } |
||
541 | // add file info |
||
542 | if (!empty($match['file_info'])) { |
||
543 | $file_info = $item->getFileInfo(); |
||
544 | $item->setFileInfo(($file_info ? $file_info."\n" : '').trim($match['file_info'])); |
||
545 | } |
||
546 | } |
||
547 | ++$i; |
||
548 | break; |
||
549 | // set date premiere and date end if exists |
||
550 | case 'Премьера': |
||
551 | case 'Выпуск': |
||
552 | $j = 1; |
||
553 | $date = ''; |
||
554 | do { |
||
555 | $date .= $data->childNodes->item($i + $j)->nodeValue; |
||
556 | ++$j; |
||
557 | } while ($length > $i + $j && $data->childNodes->item($i + $j)->nodeName != 'br'); |
||
558 | $i += $j; |
||
559 | |||
560 | $reg = '/(?<start>(?:(?:\d{2})|(?:\?\?)).\d{2}.\d{4})'. |
||
561 | '(?:.*(?<end>(?:(?:\d{2})|(?:\?\?)).\d{2}.\d{4}))?/'; |
||
562 | if (preg_match($reg, $date, $match)) { |
||
563 | $item->setDatePremiere(new \DateTime(str_replace('??', '01', $match['start']))); |
||
564 | if (isset($match['end'])) { |
||
565 | $item->setDateEnd(new \DateTime($match['end'])); |
||
566 | } |
||
567 | } |
||
568 | break; |
||
569 | case 'Хронометраж': |
||
570 | if (preg_match('/(?<duration>\d+)/', $data->childNodes->item($i + 1)->nodeValue, $match)) { |
||
571 | $item->setDuration((int) $match['duration']); |
||
572 | } |
||
573 | break; |
||
574 | case 'Кол-во серий': |
||
575 | $number = trim($data->childNodes->item($i + 1)->nodeValue, ' :'); |
||
576 | if (strpos($number, '>') !== false) { |
||
577 | $number = str_replace('>', '', $number).'+'; |
||
578 | } |
||
579 | $item->setEpisodesNumber($number); |
||
580 | break; |
||
581 | } |
||
582 | } |
||
583 | } |
||
584 | } |
||
585 | |||
586 | /** |
||
587 | * Fill body data. |
||
588 | * |
||
589 | * @param \AnimeDb\Bundle\CatalogBundle\Entity\Item $item |
||
590 | * @param \DOMXPath $xpath |
||
591 | * @param \DOMElement $body |
||
592 | * @param int $id |
||
593 | * @param bool $frames |
||
594 | * @param string $type |
||
595 | * |
||
596 | * @return \AnimeDb\Bundle\CatalogBundle\Entity\Item |
||
597 | */ |
||
598 | private function fillBodyData(Item $item, \DOMXPath $xpath, \DOMElement $body, $id, $frames, $type) |
||
599 | { |
||
600 | for ($i = 0; $i < $body->childNodes->length; ++$i) { |
||
601 | if ($value = trim($body->childNodes->item($i)->nodeValue)) { |
||
602 | switch ($value) { |
||
603 | // get summary |
||
604 | case 'Краткое содержание:': |
||
605 | $summary = $xpath->query('tr/td/p[1]', $body->childNodes->item($i + 2)); |
||
606 | if ($summary->length) { |
||
607 | $item->setSummary($this->getNodeValueAsText($summary->item(0))); |
||
608 | } |
||
609 | $i += 2; |
||
610 | break; |
||
611 | // get episodes |
||
612 | case 'Эпизоды:': |
||
613 | if (!trim($body->childNodes->item($i + 1)->nodeValue)) { // simple list |
||
614 | $item->setEpisodes($this->getNodeValueAsText($body->childNodes->item($i + 2))); |
||
615 | $i += 2; |
||
616 | } else { // episodes in table |
||
617 | $rows = $xpath->query('tr/td[2]', $body->childNodes->item($i + 1)); |
||
618 | $episodes = ''; |
||
619 | for ($j = 1; $j < $rows->length; ++$j) { |
||
620 | $episode = $xpath->query('font', $rows->item($j)); |
||
621 | $episodes .= $j.'. '.$episode->item(0)->nodeValue; |
||
622 | if ($rows->length > 1) { |
||
623 | $episodes .= ' ('.$episode->item(1)->nodeValue.')'; |
||
624 | } |
||
625 | $episodes .= "\n"; |
||
626 | } |
||
627 | $item->setEpisodes($episodes); |
||
628 | ++$i; |
||
629 | } |
||
630 | break; |
||
631 | // get date premiere |
||
632 | case 'Даты премьер и релизов': |
||
633 | $rows = $xpath->query('tr/td/table/tr/td[3]', $body->childNodes->item($i + 1)); |
||
634 | foreach ($rows as $row) { |
||
635 | if (preg_match('/\d{4}\.\d{2}\.\d{2}/', $row->nodeValue, $match)) { |
||
636 | $date = new \DateTime(str_replace('.', '-', $match[0])); |
||
637 | if (!$item->getDatePremiere() || $item->getDatePremiere() > $date) { |
||
638 | $item->setDatePremiere($date); |
||
639 | } |
||
640 | } |
||
641 | } |
||
642 | break; |
||
643 | default: |
||
644 | // get frames |
||
645 | if ( |
||
646 | ( |
||
647 | strpos($value, 'кадры из аниме') !== false || |
||
648 | strpos($value, 'Кадры из фильма') !== false |
||
649 | ) && $id && $frames |
||
650 | ) { |
||
651 | foreach ($this->getFrames($id, $type) as $frame) { |
||
652 | $item->addImage($frame); |
||
653 | } |
||
654 | } |
||
655 | } |
||
656 | } |
||
657 | } |
||
658 | } |
||
659 | |||
660 | /** |
||
661 | * Upload image from url. |
||
662 | * |
||
663 | * @param string $url |
||
664 | * @param \AnimeDb\Bundle\AppBundle\Service\Downloader\Entity\EntityInterface $entity |
||
665 | * |
||
666 | * @return bool |
||
667 | */ |
||
668 | public function uploadImage($url, EntityInterface $entity) |
||
669 | { |
||
670 | return $this->downloader->image($url, $this->downloader->getRoot().$entity->getWebPath()); |
||
671 | } |
||
672 | |||
673 | /** |
||
674 | * Get real country by name. |
||
675 | * |
||
676 | * @param string $name |
||
677 | * |
||
678 | * @return \AnimeDb\Bundle\CatalogBundle\Entity\Country|null |
||
679 | */ |
||
680 | private function getCountryByName($name) |
||
681 | { |
||
682 | $name = str_replace('Южная Корея', 'Республика Корея', $name); |
||
683 | $rep = $this->doctrine->getRepository('AnimeDbCatalogBundle:CountryTranslation'); |
||
684 | if ($country = $rep->findOneBy(['locale' => 'ru', 'content' => $name])) { |
||
685 | return $country->getObject(); |
||
686 | } |
||
687 | } |
||
688 | |||
689 | /** |
||
690 | * Get real genre by name. |
||
691 | * |
||
692 | * @param string $name |
||
693 | * |
||
694 | * @return \AnimeDb\Bundle\CatalogBundle\Entity\Genre|null |
||
695 | */ |
||
696 | private function getGenreByName($name) |
||
697 | { |
||
698 | if (isset($this->genres[$name])) { |
||
699 | return $this->doctrine |
||
700 | ->getRepository('AnimeDbCatalogBundle:Genre') |
||
701 | ->findOneByName($this->genres[$name]); |
||
702 | } |
||
703 | } |
||
704 | |||
705 | /** |
||
706 | * Get real type by name. |
||
707 | * |
||
708 | * @param string $name |
||
709 | * |
||
710 | * @return \AnimeDb\Bundle\CatalogBundle\Entity\Type|null |
||
711 | */ |
||
712 | private function getTypeByName($name) |
||
720 | |||
721 | /** |
||
722 | * Get item frames. |
||
723 | * |
||
724 | * @param int $id |
||
725 | * @param string $type |
||
726 | * |
||
727 | * @return array |
||
728 | */ |
||
729 | public function getFrames($id, $type) |
||
762 | |||
763 | /** |
||
764 | * Get node value as text. |
||
765 | * |
||
766 | * @param \DOMNode $node |
||
767 | * |
||
768 | * @return string |
||
769 | */ |
||
770 | private function getNodeValueAsText(\DOMNode $node) |
||
777 | |||
778 | /** |
||
779 | * Get item studio. |
||
780 | * |
||
781 | * @param \DOMXPath $xpath |
||
782 | * @param \DOMNode $body |
||
783 | * |
||
784 | * @return \AnimeDb\Bundle\CatalogBundle\Entity\Studio|null |
||
785 | */ |
||
786 | private function getStudio(\DOMXPath $xpath, \DOMNode $body) |
||
800 | |||
801 | /** |
||
802 | * Get item type by URL. |
||
803 | * |
||
804 | * @param string $url |
||
805 | * |
||
806 | * @return string |
||
807 | */ |
||
808 | public function getItemType($url) |
||
818 | |||
819 | /** |
||
820 | * Fill names for Animation type. |
||
821 | * |
||
822 | * @param \AnimeDb\Bundle\CatalogBundle\Entity\Item $item |
||
823 | * @param \DOMXPath $xpath |
||
824 | * @param \DOMElement $head |
||
825 | * |
||
826 | * @return \AnimeDb\Bundle\CatalogBundle\Entity\Item |
||
827 | */ |
||
828 | protected function fillAnimationNames(Item $item, \DOMXPath $xpath, \DOMElement $head) |
||
849 | |||
850 | /** |
||
851 | * Fill names for Cinema type. |
||
852 | * |
||
853 | * @param \AnimeDb\Bundle\CatalogBundle\Entity\Item $item |
||
854 | * @param \DOMXPath $xpath |
||
855 | * @param \DOMElement $head |
||
856 | * |
||
857 | * @return \AnimeDb\Bundle\CatalogBundle\Entity\Item |
||
858 | */ |
||
859 | protected function fillCinemaNames(Item $item, \DOMXPath $xpath, \DOMElement $head) |
||
881 | |||
882 | /** |
||
883 | * Get cover URL. |
||
884 | * |
||
885 | * @param string $id |
||
886 | * @param string $type |
||
887 | * |
||
888 | * @return string|null |
||
889 | */ |
||
890 | public function getCoverUrl($id, $type) |
||
901 | |||
902 | /** |
||
903 | * Is supported URL. |
||
904 | * |
||
905 | * @param string $url |
||
906 | * |
||
907 | * @return bool |
||
908 | */ |
||
909 | public function isSupportedUrl($url) |
||
913 | } |
||
914 |
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.
Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.