Completed
Push — master ( 65f236...9f6b61 )
by Alex
11s
created

StreamController::getStringOutput()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.2559

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 3
cts 5
cp 0.6
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 2
crap 2.2559
1
<?php
2
3
namespace Debril\RssAtomBundle\Controller;
4
5
use Debril\RssAtomBundle\Protocol\FeedFormatter;
6
use Debril\RssAtomBundle\Protocol\FeedOutInterface;
7
use FeedIo\Feed;
8
use Symfony\Component\HttpFoundation\Response;
9
use Symfony\Component\HttpFoundation\Request;
10
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
11
use Debril\RssAtomBundle\Provider\FeedContentProviderInterface;
12
use Debril\RssAtomBundle\Exception\FeedException\FeedNotFoundException;
13
14
/**
15
 * Class StreamController.
16
 */
17
class StreamController extends Controller
18
{
19
    /**
20
     * default provider.
21
     */
22
    const DEFAULT_SOURCE = 'debril.provider.default';
23
24
    /**
25
     * parameter used to force refresh at every hit (skips 'If-Modified-Since' usage).
26
     * set it to true for debug purpose.
27
     */
28
    const FORCE_PARAM_NAME = 'force_refresh';
29
30
    /**
31
     * @var \DateTime
32
     */
33
    protected $since;
34
35
    /**
36
     * @param Request $request
37
     *
38
     * @return Response
39
     */
40 3
    public function indexAction(Request $request)
41
    {
42 3
        $options = $request->attributes->get('_route_params');
43 3
        $this->setModifiedSince($request);
44 3
        $options['Since'] = $this->getModifiedSince();
45
46 3
        return $this->createStreamResponse(
47 3
            $options,
48 3
            $request->get('format', 'rss'),
49 3
            $request->get('source', self::DEFAULT_SOURCE)
50 3
        );
51
    }
52
53
    /**
54
     * Extract the 'If-Modified-Since' value from the headers.
55
     *
56
     * @return \DateTime
57
     */
58 3
    protected function getModifiedSince()
59
    {
60 3
        if (is_null($this->since)) {
61
            $this->since = new \DateTime('@0');
62
        }
63
64 3
        return $this->since;
65
    }
66
67
    /**
68
     * @param Request $request
69
     *
70
     * @return $this
71
     */
72 3
    protected function setModifiedSince(Request $request)
73
    {
74 3
        $this->since = new \DateTime();
75 3
        if ($request->headers->has('If-Modified-Since')) {
76 1
            $string = $request->headers->get('If-Modified-Since');
77 1
            $this->since = \DateTime::createFromFormat(\DateTime::RSS, $string);
78 1
        } else {
79 3
            $this->since->setTimestamp(1);
80
        }
81
82 3
        return $this;
83
    }
84
85
    /**
86
     * Generate the HTTP response
87
     * 200 : a full body containing the stream
88
     * 304 : Not modified.
89
     *
90
     * @param array $options
91
     * @param $format
92
     * @param string $source
93
     *
94
     * @return Response
95
     *
96
     * @throws \Exception
97
     */
98 3
    protected function createStreamResponse(array $options, $format, $source = self::DEFAULT_SOURCE)
99
    {
100 3
        $content = $this->getContent($options, $source);
101
102 1
        if ($this->mustForceRefresh() || $content->getLastModified() > $this->getModifiedSince()) {
0 ignored issues
show
Deprecated Code introduced by
The method Debril\RssAtomBundle\Pro...face::getLastModified() has been deprecated with message: removed in version 3.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
103 1
            $response = new Response($this->getStringOutput($content, $format));
104 1
            $response->headers->set('Content-Type', 'application/xhtml+xml');
105
106 1
            if (! $this->container->getParameter('debril_rss_atom.private_feeds')) {
107 1
                $response->setPublic();
108 1
            }
109
110 1
            $response->setMaxAge(3600);
111 1
            $response->setLastModified($content->getLastModified());
0 ignored issues
show
Deprecated Code introduced by
The method Debril\RssAtomBundle\Pro...face::getLastModified() has been deprecated with message: removed in version 3.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
112 1
        } else {
113 1
            $response = new Response();
114 1
            $response->setNotModified();
115
        }
116
117 1
        return $response;
118
    }
119
120
    /**
121
     * @param $feed
122
     * @param $format
123
     * @return string
124
     * @throws \Exception
125
     */
126 1
    protected function getStringOutput($feed, $format)
127
    {
128 1
        if ( $feed instanceof Feed ) {
129 1
            return $this->getFeedIo()->format($feed, $format)->saveXML();
130
        }
131
132
        $formatter = $this->getFormatter($format);
133
        return $formatter->toString($feed);
0 ignored issues
show
Deprecated Code introduced by
The method Debril\RssAtomBundle\Pro...edFormatter::toString() has been deprecated with message: removed in version 3.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
134
    }
135
136
    /**
137
     * Get the Stream's content using a FeedContentProviderInterface
138
     * The FeedContentProviderInterface instance is provided as a service
139
     * default : debril.provider.service.
140
     *
141
     * @param array  $options
142
     * @param string $source
143
     *
144
     * @return FeedOutInterface
145
     *
146
     * @throws \Exception
147
     */
148 3
    protected function getContent(array $options, $source)
149
    {
150 3
        $provider = $this->get($source);
151
152 3
        if (!$provider instanceof FeedContentProviderInterface) {
153 1
            throw new \Exception('Provider is not a FeedContentProviderInterface instance');
154
        }
155
156
        try {
157 2
            return $provider->getFeedContent($options);
158 1
        } catch (FeedNotFoundException $e) {
159 1
            throw $this->createNotFoundException('feed not found');
160
        }
161
    }
162
163
    /**
164
     * Returns true if the controller must ignore the last modified date.
165
     *
166
     * @return bool
167
     */
168 1
    protected function mustForceRefresh()
169
    {
170 1
        if ($this->container->hasParameter(self::FORCE_PARAM_NAME)) {
171
            return $this->container->getParameter(self::FORCE_PARAM_NAME);
172
        }
173
174 1
        return false;
175
    }
176
177
    /**
178
     * Get the accurate formatter.
179
     *
180
     * @param string $format
181
     *
182
     * @throws \Exception
183
     *
184
     * @return FeedFormatter
185
     */
186
    protected function getFormatter($format)
187
    {
188
        $services = array(
189
            'rss' => 'debril.formatter.rss',
190
            'atom' => 'debril.formatter.atom',
191
        );
192
193
        if (!array_key_exists($format, $services)) {
194
            throw new \Exception("Unsupported format {$format}");
195
        }
196
197
        return $this->get($services[$format]);
198
    }
199
200
    /**
201
     * @return \FeedIo\FeedIo
202
     */
203 1
    protected function getFeedIo()
204
    {
205 1
        return $this->container->get('feedio');
206
    }
207
}
208