Completed
Pull Request — master (#158)
by Alex
06:05 queued 02:56
created

Reader::addParser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
ccs 1
cts 1
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
crap 1
1
<?php declare(strict_types=1);
2
/*
3
 * This file is part of the feed-io package.
4
 *
5
 * (c) Alexandre Debril <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace FeedIo;
12
13
use FeedIo\ParserAbstract;
14
use FeedIo\Adapter\ClientInterface;
15
use FeedIo\Adapter\ResponseInterface;
16
use FeedIo\Reader\Document;
17
use FeedIo\Reader\ReadErrorException;
18
use FeedIo\Reader\Result;
19
use FeedIo\Reader\NoAccurateParserException;
20
use Psr\Log\LoggerInterface;
21
22
/**
23
 * Consumes feeds and return corresponding Result instances
24
 *
25
 * Depends on :
26
 *  - FeedIo\Adapter\ClientInterface
27
 *  - Psr\Log\LoggerInterface
28
 *
29
 * A Reader instance MUST have at least one parser added with the addParser() method to read feeds
30
 * It will throw a NoAccurateParserException if it cannot find a suitable parser for the feed.
31
 */
32
class Reader
33
{
34
    /**
35
     * @var \FeedIo\Adapter\ClientInterface;
36
     */
37
    protected $client;
38
39
    /**
40
     * @var \Psr\Log\LoggerInterface
41
     */
42
    protected $logger;
43
44
    /**
45
     * @var array
46
     */
47
    protected $parsers = array();
48
49
    /**
50
     * @param ClientInterface $client
51
     * @param LoggerInterface $logger
52
     */
53 15
    public function __construct(ClientInterface $client, LoggerInterface $logger)
54
    {
55 15
        $this->client = $client;
56 15
        $this->logger = $logger;
57 15
    }
58
59
    /**
60
     * @return ClientInterface
61
     */
62
    public function getClient(): ClientInterface
63 14
    {
64
        return $this->client;
65 14
    }
66 14
67
    /**
68 14
     * @param  ParserAbstract $parser
69
     * @return Reader
70
     */
71
    public function addParser(ParserAbstract $parser) : Reader
72
    {
73
        $this->logger->debug("new parser added : ".get_class($parser->getStandard()));
74
        $this->parsers[] = $parser;
75
76
        return $this;
77 2
    }
78
79 2
    /**
80 2
     * adds a filter to every parsers
81 2
     *
82
     * @param \FeedIo\FilterInterface $filter
83 2
     * @return Reader
84
     */
85
    public function addFilter(FilterInterface $filter) : Reader
86
    {
87
        foreach ($this->parsers as $parser) {
88
            $parser->addFilter($filter);
89
        }
90 1
91
        return $this;
92 1
    }
93 1
94 1
    /**
95
     * Reset filters on every parsers
96 1
     * @return Reader
97
     */
98
    public function resetFilters() : Reader
99
    {
100
        foreach ($this->parsers as $parser) {
101
            $parser->resetFilters();
102
        }
103
104
        return $this;
105
    }
106 4
107
    /**
108 4
     * @param string                 $url
109 4
     * @param  FeedInterface         $feed
110 2
     * @param  \DateTime             $modifiedSince
111 2
     * @return \FeedIo\Reader\Result
112 2
     * @throws ReadErrorException
113
     */
114
    public function read(string $url, FeedInterface $feed, \DateTime $modifiedSince = null) : Result
115 4
    {
116 4
        $this->logger->debug("start reading {$url}");
117 3
        if (is_null($modifiedSince)) {
118
            $this->logger->notice("no 'modifiedSince' parameter given, setting it to 01/01/1970");
119 3
            $modifiedSince = new \DateTime('@0');
120 1
        }
121 1
122 1
        try {
123
            $this->logger->info("hitting {$url}");
124
            $response = $this->client->getResponse($url, $modifiedSince);
125
            $document = $this->handleResponse($response, $feed);
126
127
            return new Result($document, $feed, $modifiedSince, $response, $url);
128
        } catch (\Exception $e) {
129
            $this->logger->warning("{$url} read error : {$e->getMessage()}");
130
            throw new ReadErrorException($e->getMessage(), $e->getCode(), $e);
131 3
        }
132
    }
133 3
134 3
    /**
135
     * @param  ResponseInterface     $response
136 3
     * @param  FeedInterface         $feed
137 2
     * @return Document
138 2
     */
139 2
    public function handleResponse(ResponseInterface $response, FeedInterface $feed) : Document
140
    {
141 3
        $this->logger->debug("response ok, now turning it into a document");
142
        $document = new Document($response->getBody());
143
144
        if ($response->isModified()) {
145
            $this->logger->info("the stream is modified, parsing it");
146
            $this->parseDocument($document, $feed);
147
        }
148
149
        return $document;
150
    }
151 3
152
    /**
153 3
     * @param Document $document
154 3
     * @param FeedInterface $feed
155
     * @return FeedInterface
156 3
     * @throws Parser\UnsupportedFormatException
157
     * @throws Reader\NoAccurateParserException
158
     */
159
    public function parseDocument(Document $document, FeedInterface $feed) : FeedInterface
160
    {
161
        $parser = $this->getAccurateParser($document);
162
        $this->logger->debug("accurate parser : ".get_class($parser));
163
164 5
        return $parser->parse($document, $feed);
165
    }
166 5
167 4
    /**
168 4
     * @param  Document                     $document
169
     * @return ParserAbstract
170 2
     * @throws Reader\NoAccurateParserException
171
     */
172 1
    public function getAccurateParser(Document $document) : ParserAbstract
173 1
    {
174 1
        foreach ($this->parsers as $parser) {
175
            if ($parser->getStandard()->canHandle($document)) {
176
                return $parser;
177
            }
178
        }
179
180
        $message = 'No parser can handle this stream';
181
        $this->logger->error($message);
182
        throw new NoAccurateParserException($message);
183
    }
184
}
185