Completed
Push — master ( b86906...5e7e78 )
by Alex
03:01
created

Reader   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 153
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 95.83%

Importance

Changes 0
Metric Value
dl 0
loc 153
c 0
b 0
f 0
wmc 16
lcom 1
cbo 8
ccs 46
cts 48
cp 0.9583
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A getClient() 0 4 1
A addParser() 0 7 1
A addFilter() 0 8 2
A resetFilters() 0 8 2
A read() 0 19 3
A handleResponse() 0 12 2
A parseDocument() 0 7 1
A getAccurateParser() 0 12 3
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 19
    public function __construct(ClientInterface $client, LoggerInterface $logger)
54
    {
55 19
        $this->client = $client;
56 19
        $this->logger = $logger;
57 19
    }
58
59
    /**
60
     * @return ClientInterface
61
     */
62
    public function getClient(): ClientInterface
63
    {
64
        return $this->client;
65
    }
66
67
    /**
68
     * @param  ParserAbstract $parser
69
     * @return Reader
70
     */
71 18
    public function addParser(ParserAbstract $parser) : Reader
72
    {
73 18
        $this->logger->debug("new parser added : ".get_class($parser->getStandard()));
74 18
        $this->parsers[] = $parser;
75
76 18
        return $this;
77
    }
78
79
    /**
80
     * adds a filter to every parsers
81
     *
82
     * @param \FeedIo\FilterInterface $filter
83
     * @return Reader
84
     */
85 2
    public function addFilter(FilterInterface $filter) : Reader
86
    {
87 2
        foreach ($this->parsers as $parser) {
88 2
            $parser->addFilter($filter);
89
        }
90
91 2
        return $this;
92
    }
93
94
    /**
95
     * Reset filters on every parsers
96
     * @return Reader
97
     */
98 1
    public function resetFilters() : Reader
99
    {
100 1
        foreach ($this->parsers as $parser) {
101 1
            $parser->resetFilters();
102
        }
103
104 1
        return $this;
105
    }
106
107
    /**
108
     * @param string                 $url
109
     * @param  FeedInterface         $feed
110
     * @param  \DateTime             $modifiedSince
111
     * @return \FeedIo\Reader\Result
112
     * @throws ReadErrorException
113
     */
114 4
    public function read(string $url, FeedInterface $feed, \DateTime $modifiedSince = null) : Result
115
    {
116 4
        $this->logger->debug("start reading {$url}");
117 4
        if (is_null($modifiedSince)) {
118 2
            $this->logger->notice("no 'modifiedSince' parameter given, setting it to 01/01/1970");
119 2
            $modifiedSince = new \DateTime('@0');
120
        }
121
122
        try {
123 4
            $this->logger->info("hitting {$url}");
124 4
            $response = $this->client->getResponse($url, $modifiedSince);
125 3
            $document = $this->handleResponse($response, $feed);
126
127 3
            return new Result($document, $feed, $modifiedSince, $response, $url);
128 1
        } catch (\Exception $e) {
129 1
            $this->logger->warning("{$url} read error : {$e->getMessage()}");
130 1
            throw new ReadErrorException($e->getMessage(), $e->getCode(), $e);
131
        }
132
    }
133
134
    /**
135
     * @param  ResponseInterface     $response
136
     * @param  FeedInterface         $feed
137
     * @return Document
138
     */
139 5
    public function handleResponse(ResponseInterface $response, FeedInterface $feed) : Document
140
    {
141 5
        $this->logger->debug("response ok, now turning it into a document");
142 5
        $document = new Document($response->getBody());
143
144 5
        if ($response->isModified()) {
145 4
            $this->logger->info("the stream is modified, parsing it");
146 4
            $this->parseDocument($document, $feed);
147
        }
148
149 5
        return $document;
150
    }
151
152
    /**
153
     * @param Document $document
154
     * @param FeedInterface $feed
155
     * @return FeedInterface
156
     * @throws Parser\UnsupportedFormatException
157
     * @throws Reader\NoAccurateParserException
158
     */
159 5
    public function parseDocument(Document $document, FeedInterface $feed) : FeedInterface
160
    {
161 5
        $parser = $this->getAccurateParser($document);
162 5
        $this->logger->debug("accurate parser : ".get_class($parser));
163
164 5
        return $parser->parse($document, $feed);
165
    }
166
167
    /**
168
     * @param  Document                     $document
169
     * @return ParserAbstract
170
     * @throws Reader\NoAccurateParserException
171
     */
172 7
    public function getAccurateParser(Document $document) : ParserAbstract
173
    {
174 7
        foreach ($this->parsers as $parser) {
175 6
            if ($parser->getStandard()->canHandle($document)) {
176 6
                return $parser;
177
            }
178
        }
179
180 1
        $message = 'No parser can handle this stream';
181 1
        $this->logger->error($message);
182 1
        throw new NoAccurateParserException($message);
183
    }
184
}
185