Passed
Push — master ( fe617e...bc2c58 )
by Carlos C
14:43 queued 11s
created

ScrapingReviewer::gateway()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpCfdi\SatCatalogosPopulate\Origins;
6
7
use LogicException;
8
use RuntimeException;
9
use Symfony\Component\DomCrawler\Crawler;
10
11
class ScrapingReviewer implements ReviewerInterface
12
{
13
    /** @var ResourcesGatewayInterface */
14
    private $gateway;
15
16
    public function __construct(ResourcesGatewayInterface $gateway)
17
    {
18
        $this->gateway = $gateway;
19
    }
20
21
    public function gateway(): ResourcesGatewayInterface
22
    {
23
        return $this->gateway;
24
    }
25
26
    public function accepts(OriginInterface $origin): bool
27
    {
28
        return ($origin instanceof ScrapingOrigin);
29
    }
30
31
    public function review(OriginInterface $origin): Review
32
    {
33
        if (! $origin instanceof ScrapingOrigin) {
34
            throw new LogicException('This reviewer can only handle ScrapingOrigin objects');
35
        }
36
37
        if (! $origin->hasDownloadUrl()) {
38
            try {
39
                $origin = $this->resolveOrigin($origin);
40
            } catch (RuntimeException $exception) {
41
                return new Review($origin, ReviewStatus::notFound());
42
            }
43
        }
44
45
        $response = $this->gateway->headers($origin->downloadUrl());
46
47
        // si no se pudo obtener el recurso
48
        if (! $response->isSuccess()) {
49
            return new Review($origin, ReviewStatus::notFound());
50
        }
51
52
        // si el recurso no coincide con la última versión
53
        if (! $origin->hasLastVersion() || ! $response->dateMatch($origin->lastVersion())) {
54
            return new Review($origin, ReviewStatus::notUpdated());
55
        }
56
57
        // entonces el recurso coincide
58
        return new Review($origin, ReviewStatus::uptodate());
59
    }
60
61
    public function resolveOrigin(ScrapingOrigin $origin): ScrapingOrigin
62
    {
63
        $baseResource = $this->gateway->get($origin->url(), '');
64
        $downloadUrl = $this->resolveHtmlToLink($baseResource, $origin->linkText());
65
        return $origin->withDownloadUrl($downloadUrl);
66
    }
67
68
    public function resolveHtmlToLink(UrlResponse $response, string $linkText): string
69
    {
70
        if (empty($response->body())) {
71
            throw new RuntimeException('Content is empty');
72
        }
73
        $crawler = new Crawler($response->body(), $response->url());
74
        $link = $crawler->selectLink($linkText)->link();
75
        $downloadUrl = $link->getUri();
76
        if (empty($downloadUrl)) {
77
            throw new RuntimeException('The link was found but it does not contains the url to download');
78
        }
79
80
        return $downloadUrl;
81
    }
82
}
83