Completed
Push — issue/142 ( b58e40...a64245 )
by Alex
05:02
created

FeedIo::format()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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