Refiller   B
last analyzed

Complexity

Total Complexity 39

Size/Duplication

Total Lines 270
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 39
lcom 1
cbo 10
dl 0
loc 270
c 0
b 0
f 0
ccs 0
cts 140
cp 0
rs 8.2857

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A getName() 0 4 1
A getTitle() 0 4 1
A isCanRefill() 0 4 2
C refill() 0 50 14
B isCanSearch() 0 17 6
C search() 0 49 9
A refillFromSearchResult() 0 11 2
A getSourceForFill() 0 11 3
1
<?php
2
/**
3
 * AnimeDb package.
4
 *
5
 * @author    Peter Gribanov <[email protected]>
6
 * @copyright Copyright (c) 2011, Peter Gribanov
7
 * @license   http://opensource.org/licenses/GPL-3.0 GPL v3
8
 */
9
namespace AnimeDb\Bundle\AniDbFillerBundle\Service;
10
11
use AnimeDb\Bundle\CatalogBundle\Plugin\Fill\Refiller\RefillerInterface;
12
use AnimeDb\Bundle\AniDbBrowserBundle\Service\Browser;
13
use AnimeDb\Bundle\CatalogBundle\Plugin\Fill\Refiller\Item as ItemRefiller;
14
use AnimeDb\Bundle\CatalogBundle\Entity\Item;
15
use AnimeDb\Bundle\CatalogBundle\Entity\Source;
16
use AnimeDb\Bundle\CatalogBundle\Entity\Name;
17
18
class Refiller implements RefillerInterface
19
{
20
    /**
21
     * @var string
22
     */
23
    const NAME = 'anidb';
24
25
    /**
26
     * @var string
27
     */
28
    const TITLE = 'AniDB.net';
29
30
    /**
31
     * List of supported fields.
32
     *
33
     * @var array
34
     */
35
    protected $supported_fields = [
36
        self::FIELD_DATE_END,
37
        self::FIELD_DATE_PREMIERE,
38
        self::FIELD_EPISODES,
39
        self::FIELD_EPISODES_NUMBER,
40
        self::FIELD_GENRES,
41
        self::FIELD_NAMES,
42
        self::FIELD_SOURCES,
43
        self::FIELD_SUMMARY,
44
    ];
45
46
    /**
47
     * @var Browser
48
     */
49
    private $browser;
50
51
    /**
52
     * @var Filler
53
     */
54
    protected $filler;
55
56
    /**
57
     * @var Search
58
     */
59
    protected $search;
60
61
    /**
62
     * @var SummaryCleaner
63
     */
64
    protected $cleaner;
65
66
    /**
67
     * @param Browser $browser
68
     * @param Filler $filler
69
     * @param Search $search
70
     * @param SummaryCleaner $cleaner
71
     */
72
    public function __construct(Browser $browser, Filler $filler, Search $search, SummaryCleaner $cleaner)
73
    {
74
        $this->browser = $browser;
75
        $this->filler = $filler;
76
        $this->search = $search;
77
        $this->cleaner = $cleaner;
78
    }
79
80
    /**
81
     * @return string
82
     */
83
    public function getName()
84
    {
85
        return self::NAME;
86
    }
87
88
    /**
89
     * @return string
90
     */
91
    public function getTitle()
92
    {
93
        return self::TITLE;
94
    }
95
96
    /**
97
     * Is can refill item from source.
98
     *
99
     * @param Item $item
100
     * @param string $field
101
     *
102
     * @return bool
103
     */
104
    public function isCanRefill(Item $item, $field)
105
    {
106
        return in_array($field, $this->supported_fields) && $this->getSourceForFill($item);
107
    }
108
109
    /**
110
     * Refill item field from source.
111
     *
112
     * @param Item $item
113
     * @param string $field
114
     *
115
     * @return Item
116
     */
117
    public function refill(Item $item, $field)
118
    {
119
        $url = $this->getSourceForFill($item);
120
        if (!$url || !preg_match(Filler::REG_ITEM_ID, $url, $match)) {
121
            return $item;
122
        }
123
124
        // get data
125
        $body = $this->browser->get('anime', ['aid' => $match['id']]);
126
127
        switch ($field) {
128
            case self::FIELD_DATE_END:
129
                $item->setDateEnd(new \DateTime($body->filter('enddate')->text()));
130
                break;
131
            case self::FIELD_DATE_PREMIERE:
132
                $item->setDatePremiere(new \DateTime($body->filter('startdate')->text()));
133
                break;
134
            case self::FIELD_EPISODES:
135
                $this->filler->setEpisodes($item, $body);
136
                break;
137
            case self::FIELD_EPISODES_NUMBER:
138
                $item->setEpisodesNumber($body->filter('episodecount')->text());
139
                break;
140
            case self::FIELD_GENRES:
141
                $new_item = $this->filler->setGenres(new Item(), $body);
142
                foreach ($new_item->getGenres() as $new_genre) {
143
                    $item->addGenre($new_genre);
144
                }
145
                break;
146
            case self::FIELD_NAMES:
147
                $new_item = $this->filler->setNames(new Item(), $body);
148
                // set main name in top of names list
149
                $new_names = $new_item->getNames()->toArray();
150
                array_unshift($new_names, (new Name())->setName($new_item->getName()));
151
                foreach ($new_names as $new_name) {
152
                    $item->addName($new_name);
153
                }
154
                break;
155
            case self::FIELD_SOURCES:
156
                if ($url = $body->filter('url')->text()) {
157
                    $item->addSource((new Source())->setUrl($url));
158
                }
159
                break;
160
            case self::FIELD_SUMMARY:
161
                $item->setSummary($this->cleaner->clean($body->filter('description')->text()));
162
                break;
163
        }
164
165
        return $item;
166
    }
167
168
    /**
169
     * @param Item $item
170
     * @param string $field
171
     *
172
     * @return bool
173
     */
174
    public function isCanSearch(Item $item, $field)
175
    {
176
        if (!in_array($field, $this->supported_fields)) {
177
            return false;
178
        }
179
        if ($this->isCanRefill($item, $field) || $item->getName()) {
180
            return true;
181
        }
182
        /* @var $name Name */
183
        foreach ($item->getNames() as $name) {
184
            if ($name->getName()) {
185
                return true;
186
            }
187
        }
188
189
        return false;
190
    }
191
192
    /**
193
     * Search items for refill.
194
     *
195
     * @param Item $item
196
     * @param string $field
197
     *
198
     * @return ItemRefiller[]
199
     */
200
    public function search(Item $item, $field)
201
    {
202
        $url = $this->getSourceForFill($item);
203
        // can refill from source. not need search
204
        if ($url) {
205
            return [
206
                new ItemRefiller(
207
                    $item->getName(),
208
                    ['url' => $url],
209
                    $url,
210
                    $item->getCover(),
211
                    $item->getSummary()
212
                ),
213
            ];
214
        }
215
216
        // get name for search
217
        if (!($name = $item->getName())) {
218
            foreach ($item->getNames() as $name) {
219
                if ($name) {
220
                    break;
221
                }
222
            }
223
        }
224
225
        $result = [];
226
        // do search
227
        if ($name) {
228
            $result = $this->search->search(['name' => $name]);
229
            foreach ($result as $key => $item) {
230
                // get real url from search result
231
                if ($query = parse_url($item->getLink(), PHP_URL_QUERY)) {
0 ignored issues
show
Bug introduced by
The method getLink does only exist in AnimeDb\Bundle\CatalogBu...Plugin\Fill\Search\Item, but not in AnimeDb\Bundle\CatalogBu...ugin\Fill\Refiller\Item.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
232
                    parse_str($query, $query);
233
                    $query = array_values($query);
234
                    if (!empty($query[0]['url'])) {
235
                        $result[$key] = new ItemRefiller(
236
                            $item->getName(),
237
                            ['url' => $query[0]['url']],
238
                            $query[0]['url'],
239
                            $item->getImage(),
240
                            $item->getDescription()
241
                        );
242
                    }
243
                }
244
            }
245
        }
246
247
        return $result;
248
    }
249
250
    /**
251
     * Refill item field from search result.
252
     *
253
     * @param Item $item
254
     * @param string $field
255
     * @param array $data
256
     *
257
     * @return Item
258
     */
259
    public function refillFromSearchResult(Item $item, $field, array $data)
260
    {
261
        if (!empty($data['url'])) {
262
            $source = new Source();
263
            $source->setUrl($data['url']);
264
            $item->addSource($source);
265
            $item = $this->refill($item, $field);
266
        }
267
268
        return $item;
269
    }
270
271
    /**
272
     * @param Item $item
273
     *
274
     * @return string
275
     */
276
    public function getSourceForFill(Item $item)
277
    {
278
        /* @var $source Source */
279
        foreach ($item->getSources() as $source) {
280
            if (strpos($source->getUrl(), $this->browser->getHost()) === 0) {
281
                return $source->getUrl();
282
            }
283
        }
284
285
        return '';
286
    }
287
}
288