Search::getTitle()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
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
10
namespace AnimeDb\Bundle\WorldArtFillerBundle\Service;
11
12
use AnimeDb\Bundle\CatalogBundle\Plugin\Fill\Search\Item as ItemSearch;
13
use AnimeDb\Bundle\CatalogBundle\Plugin\Fill\Search\Search as SearchPlugin;
14
use AnimeDb\Bundle\WorldArtFillerBundle\Form\Type\Search as SearchForm;
15
use Knp\Menu\ItemInterface;
16
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
17
18
class Search extends SearchPlugin
19
{
20
    /**
21
     * Name.
22
     *
23
     * @var string
24
     */
25
    const NAME = 'world-art';
26
27
    /**
28
     * Title.
29
     *
30
     * @var string
31
     */
32
    const TITLE = 'World-Art.ru';
33
34
    /**
35
     * Path for search.
36
     *
37
     * @var string
38
     */
39
    const SEARH_URL = '/search.php?public_search=#NAME#&global_sector=#SECTOR#';
40
41
    /**
42
     * XPath for list search items.
43
     *
44
     * @var string
45
     */
46
    const XPATH_FOR_LIST = '//center/table/tr/td/table/tr/td/table/tr/td';
47
48
    /**
49
     * Default sector.
50
     *
51
     * @var string
52
     */
53
    const DEFAULT_SECTOR = 'all';
54
55
    /**
56
     * Browser.
57
     *
58
     * @var \AnimeDb\Bundle\WorldArtFillerBundle\Service\Browser
59
     */
60
    private $browser;
61
62
    /**
63
     * Construct.
64
     *
65
     * @param \AnimeDb\Bundle\WorldArtFillerBundle\Service\Browser $browser
66
     */
67
    public function __construct(Browser $browser)
68
    {
69
        $this->browser = $browser;
70
    }
71
72
    /**
73
     * Get name.
74
     *
75
     * @return string
76
     */
77
    public function getName()
78
    {
79
        return self::NAME;
80
    }
81
82
    /**
83
     * Get title.
84
     *
85
     * @return string
86
     */
87
    public function getTitle()
88
    {
89
        return self::TITLE;
90
    }
91
92
    /**
93
     * Build menu for plugin.
94
     *
95
     * @param \Knp\Menu\ItemInterface $item
96
     *
97
     * @return \Knp\Menu\ItemInterface
98
     */
99
    public function buildMenu(ItemInterface $item)
100
    {
101
        return parent::buildMenu($item)
102
            ->setLinkAttribute('class', 'icon-label icon-label-plugin-world-art');
103
    }
104
105
    /**
106
     * Search source by name.
107
     *
108
     * Return structure
109
     * <code>
110
     * [
111
     *     \AnimeDb\Bundle\CatalogBundle\Plugin\Fill\Search\Item
112
     * ]
113
     * </code>
114
     *
115
     * @param array $data
116
     *
117
     * @return array
118
     */
119
    public function search(array $data)
120
    {
121
        $name = iconv('utf-8', 'cp1251', $data['name']);
122
        $url = str_replace('#NAME#', urlencode($name), self::SEARH_URL);
123
        $url = str_replace('#SECTOR#', (isset($data['type']) ? $data['type'] : self::DEFAULT_SECTOR), $url);
124
        // get list from xpath
125
        $dom = $this->browser->getDom($url);
126
        $xpath = new \DOMXPath($dom);
127
128
        // if for request is found only one result is produced forwarding
129
        $refresh = $xpath->query('//meta[@http-equiv="Refresh"]/@content');
130
        if ($refresh->length) {
131
            list(, $url) = explode('url=', $refresh->item(0)->nodeValue, 2);
132
            // add http if need
133
            if ($url[0] == '/') {
134
                $url = $this->browser->getHost().$url;
135
            }
136
            $name = iconv('cp1251', 'utf-8', $name);
137
            if (!preg_match('/id=(?<id>\d+)/', $url, $mat) || !($type = $this->filler->getItemType($url))) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface AnimeDb\Bundle\CatalogBu...\Filler\FillerInterface as the method getItemType() does only exist in the following implementations of said interface: AnimeDb\Bundle\WorldArtFillerBundle\Service\Filler.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
138
                throw new NotFoundHttpException('Incorrect URL for found item');
139
            }
140
141
            return [
142
                new ItemSearch(
143
                    $name,
144
                    $this->getLinkForFill($url),
145
                    $this->filler->getCoverUrl($mat['id'], $type),
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface AnimeDb\Bundle\CatalogBu...\Filler\FillerInterface as the method getCoverUrl() does only exist in the following implementations of said interface: AnimeDb\Bundle\WorldArtFillerBundle\Service\Filler.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
146
                    ''
147
                ),
148
            ];
149
        }
150
151
        $rows = $xpath->query(self::XPATH_FOR_LIST);
152
153
        $list = [];
154
        foreach ($rows as $el) {
155
            $link = $xpath->query('a', $el);
156
            // has link on source
157
            if ($link->length &&
158
                ($href = $link->item(0)->getAttribute('href')) &&
159
                ($name = $link->item(0)->nodeValue) &&
160
                preg_match('/id=(?<id>\d+)/', $href, $mat) &&
161
                ($type = $this->filler->getItemType($href))
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface AnimeDb\Bundle\CatalogBu...\Filler\FillerInterface as the method getItemType() does only exist in the following implementations of said interface: AnimeDb\Bundle\WorldArtFillerBundle\Service\Filler.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
162
            ) {
163
                $list[] = new ItemSearch(
164
                    str_replace(["\r\n", "\n"], ' ', $name),
165
                    $this->getLinkForFill($this->browser->getHost().'/'.$href),
166
                    $this->filler->getCoverUrl($mat['id'], $type),
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface AnimeDb\Bundle\CatalogBu...\Filler\FillerInterface as the method getCoverUrl() does only exist in the following implementations of said interface: AnimeDb\Bundle\WorldArtFillerBundle\Service\Filler.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
167
                    trim(str_replace($name, '', $el->nodeValue)),
168
                    $this->browser->getHost().'/'.$href
169
                );
170
            }
171
        }
172
173
        return $list;
174
    }
175
176
    /**
177
     * Get form.
178
     *
179
     * @return \AnimeDb\Bundle\WorldArtFillerBundle\Form\Type\Search
180
     */
181
    public function getForm()
182
    {
183
        return new SearchForm();
184
    }
185
}
186