Completed
Push — master ( 471a2c...9baf90 )
by Alex
14s
created

FeedIo::readAsync()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 4
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 3
crap 2
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\Filter\ModifiedSince;
14
use FeedIo\Reader\Result;
15
use FeedIo\Reader\FixerSet;
16
use FeedIo\Reader\FixerAbstract;
17
use FeedIo\Rule\DateTimeBuilder;
18
use FeedIo\Adapter\ClientInterface;
19
use FeedIo\Standard\Loader;
20
use FeedIo\Async\Reader as AsyncReader;
21
use FeedIo\Async\CallbackInterface;
22
use FeedIo\FeedInterface;
23
use Psr\Log\LoggerInterface;
24
use FeedIo\Http\ResponseBuilder;
25
use Psr\Http\Message\ResponseInterface;
26
27
/**
28
 * This class acts as a facade. It provides methods to access feed-io main features
29
 *
30
 * <code>
31
 *   // $client is a \FeedIo\Adapter\ClientInterface instance, $logger a \Psr\Log\LoggerInterface
32
 *   $feedIo = new FeedIo($client, $logger);
33
 *
34
 *   // read a feed. Output is a Result instance
35
 *   $result = $feedIo->read('http://somefeed.org/feed.rss');
36
 *
37
 *   // use the feed
38
 *   $feed = $result->getFeed();
39
 *   echo $feed->getTitle();
40
 *
41
 *   // and its items
42
 *   foreach ( $feed as $item ) {
43
 *       echo $item->getTitle();
44
 *       echo $item->getDescription();
45
 *   }
46
 *
47
 * </code>
48
 *
49
 * <code>
50
 *   // build the feed to publish
51
 *   $feed = new \FeedIo\Feed;
52
 *   $feed->setTitle('title');
53
 *   // ...
54
 *
55
 *   // add items to it
56
 *   $item = new \FeedIo\Feed\Item
57
 *   $item->setTitle('my great post');
58
 *
59
 *   // want to publish a media ? no problem
60
 *   $media = new \FeedIo\Feed\Item\Media
61
 *   $media->setUrl('http://yourdomain.tld/medias/some-podcast.mp3');
62
 *   $media->setType('audio/mpeg');
63
 *
64
 *   // add it to the item
65
 *   $item->addMedia($media);
66
 *
67
 *   // add the item to the feed (almost there)
68
 *   $feed->add($item);
69
 *
70
 *   // format it in atom
71
 *   $feedIo->toAtom($feed);
72
 * </code>
73
 *
74
 */
75
class FeedIo
76
{
77
78
    /**
79
     * @var \FeedIo\Reader
80
     */
81
    protected $reader;
82
83
    /**
84
     * @var \FeedIo\Rule\DateTimeBuilder
85
     */
86
    protected $dateTimeBuilder;
87
88
    /**
89
     * @var \Psr\Log\LoggerInterface
90
     */
91
    protected $logger;
92
93
    /**
94
     * @var array
95
     */
96
    protected $standards;
97
98
    /**
99
     * @var \FeedIo\Reader\FixerSet
100
     */
101
    protected $fixerSet;
102
103
    /**
104
     * @param \FeedIo\Adapter\ClientInterface $client
105
     * @param \Psr\Log\LoggerInterface        $logger
106
     */
107 12
    public function __construct(ClientInterface $client, LoggerInterface $logger)
108
    {
109 12
        $this->logger = $logger;
110 12
        $this->dateTimeBuilder = new DateTimeBuilder($logger);
111 12
        $this->setReader(new Reader($client, $logger));
112 12
        $this->loadCommonStandards();
113 12
        $this->loadFixerSet();
114 12
    }
115
116
    /**
117
     * Loads main standards (RSS, RDF, Atom) in current object's attributes
118
     *
119
     * @return FeedIo
120
     */
121 12
    protected function loadCommonStandards() : FeedIo
122
    {
123 12
        $standards = $this->getCommonStandards();
124 12
        foreach ($standards as $name => $standard) {
125 12
            $this->addStandard($name, $standard);
126
        }
127
128 12
        return $this;
129
    }
130
131
    /**
132
     * adds a filter to the reader
133
     *
134
     * @param \FeedIo\FilterInterface $filter
135
     * @return FeedIo
136
     */
137 2
    public function addFilter(FilterInterface $filter) : FeedIo
138
    {
139 2
        $this->getReader()->addFilter($filter);
140
141 2
        return $this;
142
    }
143
144
    /**
145
     * Returns main standards
146
     *
147
     * @return array
148
     */
149 12
    public function getCommonStandards() : array
150
    {
151 12
        $loader = new Loader();
152
153 12
        return $loader->getCommonStandards($this->getDateTimeBuilder());
154
    }
155
156
    /**
157
     * @param  string                   $name
158
     * @param  \FeedIo\StandardAbstract $standard
159
     * @return FeedIo
160
     */
161 12
    public function addStandard(string $name, StandardAbstract $standard) : FeedIo
162
    {
163 12
        $name = strtolower($name);
164 12
        $this->standards[$name] = $standard;
165 12
        $parser = $this->newParser($standard->getSyntaxFormat(), $standard);
166 12
        $this->reader->addParser($parser);
167
168 12
        return $this;
169
    }
170
171
    /**
172
     * @param string $format
173
     * @param StandardAbstract $standard
174
     * @return ParserAbstract
175
     */
176 11
    public function newParser(string $format, StandardAbstract $standard) : ParserAbstract
177
    {
178 11
        $reflection = new \ReflectionClass("FeedIo\\Parser\\{$format}Parser");
179
180 11
        if (! $reflection->isSubclassOf('FeedIo\ParserAbstract')) {
181
            throw new \InvalidArgumentException();
182
        }
183
184 11
        return $reflection->newInstanceArgs([$standard, $this->logger]);
185
    }
186
187
    /**
188
     * @return \FeedIo\Reader\FixerSet
189
     */
190 1
    public function getFixerSet() : FixerSet
191
    {
192 1
        return $this->fixerSet;
193
    }
194
195
    /**
196
     * @return FeedIo
197
     */
198 11
    protected function loadFixerSet() : FeedIo
199
    {
200 11
        $this->fixerSet = new FixerSet();
201 11
        $fixers = $this->getBaseFixers();
202
203 11
        foreach ($fixers as $fixer) {
204 11
            $this->addFixer($fixer);
205
        }
206
207 11
        return $this;
208
    }
209
210
    /**
211
     * @param  FixerAbstract $fixer
212
     * @return FeedIo
213
     */
214 11
    public function addFixer(FixerAbstract $fixer) : FeedIo
215
    {
216 11
        $fixer->setLogger($this->logger);
217 11
        $this->fixerSet->add($fixer);
218
219 11
        return $this;
220
    }
221
222
    /**
223
     * @return array
224
     */
225 11
    public function getBaseFixers() : array
226
    {
227
        return array(
228 11
            new Reader\Fixer\LastModified(),
229 11
            new Reader\Fixer\PublicId(),
230
        );
231
    }
232
233
    /**
234
     * @param array $formats
235
     * @return FeedIo
236
     */
237 1
    public function addDateFormats(array $formats) : FeedIo
238
    {
239 1
        foreach ($formats as $format) {
240 1
            $this->getDateTimeBuilder()->addDateFormat($format);
241
        }
242
243 1
        return $this;
244
    }
245
246
    /**
247
     * @return \FeedIo\Rule\DateTimeBuilder
248
     */
249 12
    public function getDateTimeBuilder() : DateTimeBuilder
250
    {
251 12
        return $this->dateTimeBuilder;
252
    }
253
254
    /**
255
     * @return \FeedIo\Reader
256
     */
257 4
    public function getReader() : Reader
258
    {
259 4
        return $this->reader;
260
    }
261
262
    /**
263
     * @param \FeedIo\Reader $reader
264
     * @return FeedIo
265
     */
266 12
    public function setReader(Reader $reader) : FeedIo
267
    {
268 12
        $this->reader = $reader;
269
270 12
        return $this;
271
    }
272
273
    /**
274
     * @param iterable $requests
275
     * @param CallbackInterface $callback
276
     * @param string $feedClass
277
     */
278
    public function readAsync(iterable $requests, CallbackInterface $callback, string $feedClass = '\FeedIo\Feed') : void
279
    {
280
        $reader = new AsyncReader($this->reader, $callback, $feedClass);
281
282
        $reader->process($requests);
283
    }
284
285
    /**
286
     * @param  string                $url
287
     * @param  FeedInterface         $feed
288
     * @param  \DateTime             $modifiedSince
289
     * @return \FeedIo\Reader\Result
290
     */
291 2
    public function read(string $url, FeedInterface $feed = null, \DateTime $modifiedSince = null) : Result
292
    {
293 2
        if (is_null($feed)) {
294 1
            $feed = new Feed();
295
        }
296
297 2
        if ($modifiedSince instanceof \DateTime) {
298 1
            $this->addFilter(new ModifiedSince($modifiedSince));
299
        }
300
301 2
        $this->logAction($feed, "read access : $url into a feed instance");
302 2
        $result = $this->reader->read($url, $feed, $modifiedSince);
303
304 2
        $this->fixerSet->correct($result->getFeed());
305
306 2
        return $result;
307
    }
308
309
    /**
310
     * @param  string                $url
311
     * @param  \DateTime             $modifiedSince
312
     * @return \FeedIo\Reader\Result
313
     */
314 1
    public function readSince(string $url, \DateTime $modifiedSince) : Result
315
    {
316 1
        return $this->read($url, new Feed(), $modifiedSince);
317
    }
318
319
    /**
320
     * @return FeedIo
321
     */
322 1
    public function resetFilters() : FeedIo
323
    {
324 1
        $this->getReader()->resetFilters();
325
326 1
        return $this;
327
    }
328
329
    /**
330
     * Get a PSR-7 compliant response for the given feed
331
     *
332
     * @param \FeedIo\FeedInterface $feed
333
     * @param string $standard
334
     * @param int $maxAge
335
     * @param bool $public
336
     * @return ResponseInterface
337
     */
338 1
    public function getPsrResponse(FeedInterface $feed, string $standard, int $maxAge = 600, bool $public = true) : ResponseInterface
339
    {
340 1
        $this->logAction($feed, "creating a PSR 7 Response in $standard format");
341
342 1
        $formatter = $this->getStandard($standard)->getFormatter();
343 1
        $responseBuilder = new ResponseBuilder($maxAge, $public);
344
345 1
        return $responseBuilder->createResponse($standard, $formatter, $feed);
346
    }
347
348
    /**
349
     * @param  FeedInterface $feed
350
     * @param  string        $standard Standard's name
351
     * @return string
352
     */
353 1
    public function format(FeedInterface $feed, string $standard) : string
354
    {
355 1
        $this->logAction($feed, "formatting a feed in $standard format");
356
357 1
        $formatter = $this->getStandard($standard)->getFormatter();
358
359 1
        return $formatter->toString($feed);
360
    }
361
362
    /**
363
     * @param  \FeedIo\FeedInterface $feed
364
     * @return string
365
     */
366 1
    public function toRss(FeedInterface $feed) : string
367
    {
368 1
        return $this->format($feed, 'rss');
369
    }
370
371
    /**
372
     * @param  \FeedIo\FeedInterface $feed
373
     * @return string
374
     */
375 1
    public function toAtom(FeedInterface $feed) : string
376
    {
377 1
        return $this->format($feed, 'atom');
378
    }
379
380
    /**
381
     * @param  \FeedIo\FeedInterface $feed
382
     * @return string
383
     */
384 1
    public function toJson(FeedInterface $feed) : string
385
    {
386 1
        return $this->format($feed, 'json');
387
    }
388
389
390
    /**
391
     * @param  string                   $name
392
     * @return \FeedIo\StandardAbstract
393
     * @throws \OutOfBoundsException
394
     */
395 3
    public function getStandard(string $name) : StandardAbstract
396
    {
397 3
        $name = strtolower($name);
398 3
        if (array_key_exists($name, $this->standards)) {
399 2
            return $this->standards[$name];
400
        }
401
402 1
        throw new \OutOfBoundsException("no standard found for $name");
403
    }
404
405
    /**
406
     * @param  \FeedIo\FeedInterface $feed
407
     * @param  string                $message
408
     * @return FeedIo
409
     */
410 3
    protected function logAction(FeedInterface $feed, string $message) : FeedIo
411
    {
412 3
        $class = get_class($feed);
413 3
        $this->logger->debug("$message (feed class : $class)");
414
415 3
        return $this;
416
    }
417
}
418