Completed
Push — master ( bd5947...6becd7 )
by Alex
12s
created

StreamController   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 168
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 92.73%

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 11
dl 0
loc 168
ccs 51
cts 55
cp 0.9273
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getContent() 0 14 3
A mustForceRefresh() 0 8 2
A indexAction() 0 12 1
A getModifiedSince() 0 8 2
A setModifiedSince() 0 12 2
B createStreamResponse() 0 22 4
A getFormatter() 0 13 2
1
<?php
2
3
namespace Debril\RssAtomBundle\Controller;
4
5
use Debril\RssAtomBundle\Protocol\FeedFormatter;
6
use Debril\RssAtomBundle\Protocol\FeedOutInterface;
7
use Symfony\Component\HttpFoundation\Response;
8
use Symfony\Component\HttpFoundation\Request;
9
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
10
use Debril\RssAtomBundle\Provider\FeedContentProviderInterface;
11
use Debril\RssAtomBundle\Exception\FeedException\FeedNotFoundException;
12
13
/**
14
 * Class StreamController.
15
 */
16
class StreamController extends Controller
17
{
18
    /**
19
     * default provider.
20
     */
21
    const DEFAULT_SOURCE = 'debril.provider.default';
22
23
    /**
24
     * parameter used to force refresh at every hit (skips 'If-Modified-Since' usage).
25
     * set it to true for debug purpose.
26
     */
27
    const FORCE_PARAM_NAME = 'force_refresh';
28
29
    /**
30
     * @var \DateTime
31
     */
32
    protected $since;
33
34
    /**
35
     * @param Request $request
36
     *
37
     * @return Response
38
     */
39 3
    public function indexAction(Request $request)
40
    {
41 3
        $options = $request->attributes->get('_route_params');
42 3
        $this->setModifiedSince($request);
43 3
        $options['Since'] = $this->getModifiedSince();
44
45 3
        return $this->createStreamResponse(
46 3
            $options,
47 3
            $request->get('format', 'rss'),
48 3
            $request->get('source', self::DEFAULT_SOURCE)
49 3
        );
50
    }
51
52
    /**
53
     * Extract the 'If-Modified-Since' value from the headers.
54
     *
55
     * @return \DateTime
56
     */
57 3
    protected function getModifiedSince()
58
    {
59 3
        if (is_null($this->since)) {
60
            $this->since = new \DateTime('@0');
61
        }
62
63 3
        return $this->since;
64
    }
65
66
    /**
67
     * @param Request $request
68
     *
69
     * @return $this
70
     */
71 3
    protected function setModifiedSince(Request $request)
72
    {
73 3
        $this->since = new \DateTime();
74 3
        if ($request->headers->has('If-Modified-Since')) {
75 1
            $string = $request->headers->get('If-Modified-Since');
76 1
            $this->since = \DateTime::createFromFormat(\DateTime::RSS, $string);
77 1
        } else {
78 3
            $this->since->setTimestamp(1);
79
        }
80
81 3
        return $this;
82
    }
83
84
    /**
85
     * Generate the HTTP response
86
     * 200 : a full body containing the stream
87
     * 304 : Not modified.
88
     *
89
     * @param array $options
90
     * @param $format
91
     * @param string $source
92
     *
93
     * @return Response
94
     *
95
     * @throws \Exception
96
     */
97 3
    protected function createStreamResponse(array $options, $format, $source = self::DEFAULT_SOURCE)
98
    {
99 3
        $content = $this->getContent($options, $source);
100
101 1
        if ($this->mustForceRefresh() || $content->getLastModified() > $this->getModifiedSince()) {
102 1
            $formatter = $this->getFormatter($format);
103 1
            $response = new Response($formatter->toString($content));
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());
112 1
        } else {
113 1
            $response = new Response();
114 1
            $response->setNotModified();
115
        }
116
117 1
        return $response;
118
    }
119
120
    /**
121
     * Get the Stream's content using a FeedContentProviderInterface
122
     * The FeedContentProviderInterface instance is provided as a service
123
     * default : debril.provider.service.
124
     *
125
     * @param array  $options
126
     * @param string $source
127
     *
128
     * @return FeedOutInterface
129
     *
130
     * @throws \Exception
131
     */
132 3
    protected function getContent(array $options, $source)
133
    {
134 3
        $provider = $this->get($source);
135
136 3
        if (!$provider instanceof FeedContentProviderInterface) {
137 1
            throw new \Exception('Provider is not a FeedContentProviderInterface instance');
138
        }
139
140
        try {
141 2
            return $provider->getFeedContent($options);
142 1
        } catch (FeedNotFoundException $e) {
143 1
            throw $this->createNotFoundException('feed not found');
144
        }
145
    }
146
147
    /**
148
     * Returns true if the controller must ignore the last modified date.
149
     *
150
     * @return bool
151
     */
152 1
    protected function mustForceRefresh()
153
    {
154 1
        if ($this->container->hasParameter(self::FORCE_PARAM_NAME)) {
155
            return $this->container->getParameter(self::FORCE_PARAM_NAME);
156
        }
157
158 1
        return false;
159
    }
160
161
    /**
162
     * Get the accurate formatter.
163
     *
164
     * @param string $format
165
     *
166
     * @throws \Exception
167
     *
168
     * @return FeedFormatter
169
     */
170 1
    protected function getFormatter($format)
171
    {
172
        $services = array(
173 1
            'rss' => 'debril.formatter.rss',
174 1
            'atom' => 'debril.formatter.atom',
175 1
        );
176
177 1
        if (!array_key_exists($format, $services)) {
178
            throw new \Exception("Unsupported format {$format}");
179
        }
180
181 1
        return $this->get($services[$format]);
182
    }
183
}
184