Passed
Pull Request — master (#4)
by Igor
04:25
created

DomParser::list()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 6
nc 1
nop 1
dl 0
loc 8
ccs 6
cts 6
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SomeWork\Minjust\Parser;
6
7
use PHPHtmlParser\Dom;
8
use PHPHtmlParser\Dom\Collection;
9
use PHPHtmlParser\Dom\HtmlNode;
10
use PHPHtmlParser\Exceptions\ChildNotFoundException;
11
use PHPHtmlParser\Exceptions\NotLoadedException;
12
use SomeWork\Minjust\Entity\DetailLawyer;
13
use SomeWork\Minjust\Entity\LawFormation;
14
use SomeWork\Minjust\Entity\Lawyer;
15
use SomeWork\Minjust\Exception\BlockNotFoundException;
16
use SomeWork\Minjust\Exception\RuntimeException;
17
use SomeWork\Minjust\FindResponse;
18
19
/**
20
 * @see \SomeWork\Minjust\Tests\Unit\DomParserTest
21
 */
22
class DomParser implements ParserInterface
23
{
24
    /**
25
     * @var string
26
     */
27
    protected const PAGINATION_BLOCK_SELECTOR = 'ul.pagination';
28
29
    /**
30
     * @var string
31
     */
32
    protected const CURRENT_PAGE_SELECTOR = 'li.active';
33
34
    /**
35
     * @var string
36
     */
37
    protected const PAGINATION_STEP_SELECTOR = 'li';
38
39
    /**
40
     * @var string
41
     */
42
    protected const LAWYERS_LIST_BLOCK_SELECTOR = 'table.persons > tbody > tr';
43
44
    /**
45
     * @var string
46
     */
47
    protected const LAWYER_DETAIL_SELECTOR = '.floating > p.row';
48
49
    /**
50
     * @var string
51
     */
52
    protected const LAWYER_DETAIL_NAME_FIELD = 'label';
53
54 5
    public function list(string $body): FindResponse
55
    {
56 5
        $dom = (new Dom())->loadStr($body);
57
58 5
        return (new FindResponse())
59 5
            ->setPage($this->getCurrentPage($dom))
60 5
            ->setTotalPage($this->getTotalPage($dom))
61 5
            ->setLawyers($this->getListLawyers($dom));
62
    }
63
64 5
    protected function getCurrentPage(Dom $dom): int
65
    {
66
        try {
67
            /**
68
             * @var HtmlNode|null $block
69
             */
70
            $block = $this
71 5
                ->getPagination($dom)
72 5
                ->find(static::CURRENT_PAGE_SELECTOR, 0);
73
        } catch (ChildNotFoundException $exception) {
74
            throw new RuntimeException($exception->getMessage(), $exception->getCode(), $exception);
75
        }
76
77 5
        if (null === $block) {
78
            throw new BlockNotFoundException(static::CURRENT_PAGE_SELECTOR);
79
        }
80
81
        try {
82 5
            return (int) $block->firstChild()->text();
83
        } catch (ChildNotFoundException $exception) {
84
            throw new RuntimeException($exception->getMessage(), $exception->getCode(), $exception);
85
        }
86
    }
87
88 4
    protected function getTotalPage(Dom $dom): int
89
    {
90
        try {
91
            /* @noinspection NullPointerExceptionInspection */
92
            $collection = $this
93 4
                ->getPagination($dom)
94 4
                ->find(static::PAGINATION_STEP_SELECTOR)
95 4
                ->toArray();
96
        } catch (ChildNotFoundException $exception) {
97
            throw new RuntimeException($exception->getMessage(), $exception->getCode(), $exception);
98
        }
99
100 4
        if (0 === count($collection)) {
101
            return 1;
102
        }
103
104
        /**
105
         * @var HtmlNode $last
106
         */
107 4
        $last = end($collection);
108
109
        try {
110
            /**
111
             * @var HtmlNode|null $link
112
             */
113 4
            $link = $last->find('a', 0);
114
        } catch (ChildNotFoundException $exception) {
115
            throw new RuntimeException($exception->getMessage(), $exception->getCode(), $exception);
116
        }
117
118 4
        if ($link) {
119 2
            $href = (string) $link->getAttribute('href');
0 ignored issues
show
Bug introduced by
Are you sure the usage of $link->getAttribute('href') targeting PHPHtmlParser\Dom\AbstractNode::getAttribute() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
120 2
            $matches = [];
121 2
            preg_match('/page=([\d]+)/', $href, $matches);
122
123 2
            return (int) $matches[1];
124
        }
125
126 2
        return $this->getCurrentPage($dom);
127
    }
128
129
    protected function getPagination(Dom $dom): HtmlNode
130
    {
131
        static $parsedDom = null;
132
        static $pagination = null;
133
        if ($dom !== $parsedDom) {
134
            $parsedDom = $dom;
135
136
            try {
137
                $pagination = $dom->find(static::PAGINATION_BLOCK_SELECTOR, 0);
138
            } catch (\Exception $exception) {
139
                throw new RuntimeException($exception->getMessage(), $exception->getCode(), $exception);
140
            }
141
142
            if (null === $pagination) {
143
                throw new BlockNotFoundException(static::PAGINATION_BLOCK_SELECTOR);
144
            }
145
        }
146
147
        return $pagination;
148
    }
149
150
    /**
151
     * @param \PHPHtmlParser\Dom $dom
152
     *
153
     * @return Lawyer[]
154
     * @throws ChildNotFoundException
155
     * @throws NotLoadedException
156
     */
157 5
    protected function getListLawyers(Dom $dom): array
158
    {
159 5
        $data = [];
160
        /**
161
         * @var Dom\HtmlNode[]|Collection $nodes
162
         */
163 5
        $nodes = $dom->find(static::LAWYERS_LIST_BLOCK_SELECTOR);
164 5
        foreach ($nodes as $node) {
165
            /**
166
             * @var Dom\HtmlNode[]|Collection $tds
167
             */
168 5
            $tds = $node->find('td');
169 5
            $data[] = (new Lawyer())
170 5
                ->setRegisterNumber($tds[0]->text())
171 5
                ->setFullName($tds[1]->text(true))
172 5
                ->setUrl($tds[1]->firstChild()->getAttribute('href'))
173 5
                ->setTerritorialSubject($tds[2]->text())
174 5
                ->setCertificateNumber($tds[3]->text())
175 5
                ->setStatus($tds[4]->text());
176
        }
177
178 5
        return $data;
179
    }
180
181 2
    public function detail(string $body): DetailLawyer
182
    {
183 2
        $dom = (new Dom())->loadStr($body);
184
185
        /**
186
         * @var Dom\HtmlNode[] $nodes
187
         */
188 2
        $nodes = $dom->find(static::LAWYER_DETAIL_SELECTOR)->toArray();
189
190
        $nodes = array_filter($nodes, static function (HtmlNode $htmlNode) {
191 2
            return strpos($htmlNode->getAttribute('class'), static::LAWYER_DETAIL_NAME_FIELD) === false;
0 ignored issues
show
Bug introduced by
Are you sure the usage of $htmlNode->getAttribute('class') targeting PHPHtmlParser\Dom\AbstractNode::getAttribute() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
192 2
        });
193
194 2
        $nodes = array_values($nodes);
195
196 2
        $lawyer = (new DetailLawyer())
197 2
            ->setChamberOfLaw(trim($nodes[2]->text()));
198
199 2
        if (($organizationForm = trim($nodes[3]->text())) !== '') {
200 1
            $lawyer->setLawFormation(
201 1
                (new LawFormation())
202 1
                    ->setOrganizationalForm($organizationForm)
203 1
                    ->setName(trim($nodes[4]->text()))
204 1
                    ->setAddress(trim($nodes[5]->text()))
205 1
                    ->setPhone(trim($nodes[6]->text()))
206 1
                    ->setEmail(trim($nodes[7]->text()))
207
            );
208
        }
209
210 2
        return $lawyer;
211
    }
212
}
213