Completed
Push — master ( f20937...d145ff )
by Alex
11s
created

StreamController::getModifiedSince()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 3
cts 4
cp 0.75
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 0
crap 2.0625
1
<?php
2
3
namespace Debril\RssAtomBundle\Controller;
4
5
use FeedIo\FeedIo;
6
use FeedIo\FeedInterface;
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
    /**
20
     * @var \DateTime
21
     */
22
    protected $since;
23
24
    /**
25
     * @param Request $request
26
     * @param FeedContentProviderInterface $provider
27
     * @param FeedIo $feedIo
28
     * @return Response
29
     * @throws \Exception
30
     */
31 5
    public function indexAction(Request $request, FeedContentProviderInterface $provider, FeedIo $feedIo)
32
    {
33 5
        $options = $request->attributes->get('_route_params');
34 5
        $this->setModifiedSince($request);
35 5
        $options['Since'] = $this->getModifiedSince();
36
37 5
        return $this->createStreamResponse(
38 5
            $options,
39 5
            $request->get('format', 'rss'),
40 5
            $provider,
41 5
            $feedIo
42
        );
43
    }
44
45
    /**
46
     * Extract the 'If-Modified-Since' value from the headers.
47
     *
48
     * @return \DateTime
49
     */
50 5
    protected function getModifiedSince()
51
    {
52 5
        if (is_null($this->since)) {
53
            $this->since = new \DateTime('@0');
54
        }
55
56 5
        return $this->since;
57
    }
58
59
    /**
60
     * @param Request $request
61
     *
62
     * @return $this
63
     */
64 5
    protected function setModifiedSince(Request $request)
65
    {
66 5
        $this->since = new \DateTime();
67 5
        if ($request->headers->has('If-Modified-Since')) {
68 1
            $string = $request->headers->get('If-Modified-Since');
69 1
            $this->since = \DateTime::createFromFormat(\DateTime::RSS, $string);
0 ignored issues
show
Documentation Bug introduced by
It seems like \DateTime::createFromFor...DateTime::RSS, $string) can also be of type false. However, the property $since is declared as type object<DateTime>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
70
        } else {
71 5
            $this->since->setTimestamp(1);
72
        }
73
74 5
        return $this;
75
    }
76
77
    /**
78
     * Generate the HTTP response
79
     * 200 : a full body containing the stream
80
     * 304 : Not modified.
81
     *
82
     * @param array $options
83
     * @param $format
84
     * @param FeedContentProviderInterface $provider
85
     * @param FeedIo $feedIo
86
     *
87
     * @return Response
88
     *
89
     * @throws \Exception
90
     */
91 5
    protected function createStreamResponse(array $options, $format, FeedContentProviderInterface $provider, FeedIo $feedIo)
92
    {
93 5
        $content = $this->getContent($options, $provider);
94
95 4
        if ($this->mustForceRefresh() || $content->getLastModified() > $this->getModifiedSince()) {
96 4
            $response = new Response($feedIo->format($content, $format));
97 4
            $this->setFeedHeaders($response, $content, $format);
98
99
        } else {
100 1
            $response = new Response();
101 1
            $response->setNotModified();
102
        }
103
104 4
        return $response;
105
    }
106
107
    /**
108
     * @param Response $response
109
     * @param FeedInterface $feed
110
     * @param string $format
111
     * @return $this
112
     */
113 4
    protected function setFeedHeaders(Response $response, FeedInterface $feed, $format)
114
    {
115 4
        $contentType = 'json' == $format ? 'application/json':'application/xhtml+xml';
116 4
        $response->headers->set('Content-Type', $contentType);
117 4
        if (! $this->isPrivate() ) {
118 4
            $response->setPublic();
119
        }
120
121 4
        $response->setMaxAge(3600);
122 4
        $response->setLastModified($feed->getLastModified());
123
124 4
        return $this;
125
    }
126
127
    /**
128
     * Get the Stream's content using a FeedContentProviderInterface
129
     * The FeedContentProviderInterface instance is provided as a service
130
     * default : debril.provider.service.
131
     *
132
     * @param array  $options
133
     * @param FeedContentProviderInterface $provider
134
     *
135
     * @return FeedInterface
136
     *
137
     * @throws \Exception
138
     */
139 5
    protected function getContent(array $options, $provider)
140
    {
141
        try {
142 5
            return $provider->getFeedContent($options);
143 1
        } catch (FeedNotFoundException $e) {
144 1
            throw $this->createNotFoundException('feed not found');
145
        }
146
    }
147
148
    /**
149
     * Returns true if the controller must ignore the last modified date.
150
     *
151
     * @return bool
152
     */
153 4
    protected function mustForceRefresh()
154
    {
155 4
        return $this->container->getParameter('debril_rss_atom.force_refresh');
156
    }
157
158
    /**
159
     * @return boolean true if the feed must be private
160
     */
161 4
    protected function isPrivate()
162
    {
163 4
        return $this->container->getParameter('debril_rss_atom.private_feeds');
164
    }
165
166
}
167