Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
8 / 8
CRAP
98.39% covered (success)
98.39%
61 / 62
DefaultController
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
8 / 8
13
100.00% covered (success)
100.00%
60 / 60
 __construct
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 indexAction
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
14 / 14
 getVariables
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
6 / 6
 getTweetsVars
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
13 / 13
 getLastTweetIdFromCookie
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
3 / 3
 createCookie
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
7 / 7
 resetCookieAction
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
5 / 5
 deleteLessThanAction
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
10 / 10
1<?php
2
3namespace AlexisLefebvre\Bundle\AsyncTweetsBundle\Controller;
4
5use AlexisLefebvre\Bundle\AsyncTweetsBundle\Entity\Tweet;
6use AlexisLefebvre\Bundle\AsyncTweetsBundle\Entity\TweetRepository;
7use Doctrine\ORM\EntityManagerInterface;
8use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as BaseController;
9use Symfony\Component\HttpFoundation\Cookie;
10use Symfony\Component\HttpFoundation\RedirectResponse;
11use Symfony\Component\HttpFoundation\Request;
12use Symfony\Component\HttpFoundation\Response;
13use Symfony\Component\HttpFoundation\Session\Session;
14
15// Compatibility layer for Symfony 3.4
16if (!class_exists('Symfony\Bundle\FrameworkBundle\Controller\Controller')) {
17    class_alias('Symfony\Bundle\FrameworkBundle\Controller\Controller', 'Symfony\Bundle\FrameworkBundle\Controller\AbstractController');
18}
19
20class DefaultController extends BaseController
21{
22    /** @var EntityManagerInterface */
23    private $entityManager;
24
25    /** @var TweetRepository */
26    private $tweetRepository;
27
28    public function __construct(EntityManagerInterface $entityManager)
29    {
30        $this->entityManager = $entityManager;
31    }
32
33    public function indexAction(Request $request, ?int $firstTweetId): Response
34    {
35        /** @var TweetRepository $tweetRepository */
36        $tweetRepository = $this->entityManager
37            ->getRepository(Tweet::class);
38
39        $this->tweetRepository = $tweetRepository;
40
41        $tweets = $this->tweetRepository
42            ->getWithUsersAndMedias($firstTweetId);
43
44        $variables = $this->getVariables($request, $tweets, $firstTweetId);
45
46        $response = $this->render(
47            '@AsyncTweets/Default/index.html.twig',
48            [
49                'tweets' => $tweets,
50                'vars'   => $variables,
51            ]
52        );
53
54        if (!is_null($variables['cookie'])) {
55            /** @var Cookie $cookie */
56            $cookie = $variables['cookie'];
57            $response->headers->setCookie($cookie);
58        }
59
60        return $response;
61    }
62
63    /**
64     * @param array<Tweet> $tweets
65     *
66     * @return array<Cookie|int|string|null>
67     */
68    private function getVariables(Request $request, array $tweets, ?int $firstTweetId): array
69    {
70        $vars = [
71            'first'    => $firstTweetId,
72            'previous' => null,
73            'next'     => null,
74            'number'   => 0,
75            'cookieId' => $this->getLastTweetIdFromCookie($request),
76            // No cookie by default
77            'cookie' => null,
78        ];
79
80        if (count($tweets) > 0) {
81            $vars = $this->getTweetsVars($tweets, $vars);
82        }
83
84        return $vars;
85    }
86
87    /**
88     * If a Tweet is displayed, fetch data from repository.
89     *
90     * @param array<Tweet>                  $tweets
91     * @param array<Cookie|int|string|null> $vars
92     *
93     * @return array<Cookie|int|string|null>
94     */
95    private function getTweetsVars(array $tweets, array $vars): array
96    {
97        /** @var int $firstTweetId */
98        $firstTweetId = $tweets[0]->getId();
99
100        $vars['previous'] = $this->tweetRepository
101            ->getPreviousTweetId($firstTweetId);
102        $vars['next'] = $this->tweetRepository
103            ->getNextTweetId($firstTweetId);
104
105        // Only update the cookie if the last Tweet Id is bigger than
106        //  the one in the cookie
107        if ($firstTweetId > $vars['cookieId']) {
108            $vars['cookie'] = $this->createCookie($firstTweetId);
109            $vars['cookieId'] = $firstTweetId;
110        }
111
112        /** @var int */
113        $cookieId = $vars['cookieId'];
114        $vars['number'] = $this->tweetRepository
115            ->countPendingTweets($cookieId);
116
117        $vars['first'] = $firstTweetId;
118
119        return $vars;
120    }
121
122    private function getLastTweetIdFromCookie(Request $request): ?int
123    {
124        if ($request->cookies->has('lastTweetId')) {
125            return (int) $request->cookies->get('lastTweetId');
126        }
127
128        return null;
129    }
130
131    private function createCookie(int $firstTweetId): Cookie
132    {
133        $nextYear = new \DateTime('now');
134        $nextYear->add(new \DateInterval('P1Y'));
135
136        // Set last Tweet Id
137        $cookie = new Cookie(
138            'lastTweetId',
139            (string) $firstTweetId,
140            $nextYear->format('U')
141        );
142
143        return $cookie;
144    }
145
146    public function resetCookieAction(): RedirectResponse
147    {
148        /* @see http://www.craftitonline.com/2011/07/symfony2-how-to-set-a-cookie/ */
149        $response = new RedirectResponse(
150            $this->generateUrl('asynctweets_homepage')
151        );
152
153        // Reset last Tweet Id
154        $cookie = new Cookie('lastTweetId', null);
155        $response->headers->setCookie($cookie);
156
157        return $response;
158    }
159
160    public function deleteLessThanAction(Request $request): RedirectResponse
161    {
162        $lastTweetId = $this->getLastTweetIdFromCookie($request);
163
164        if (!is_null($lastTweetId)) {
165            /** @var TweetRepository $tweetRepository */
166            $tweetRepository = $this->entityManager
167                ->getRepository(Tweet::class);
168
169            $count = $tweetRepository
170                ->deleteAndHideTweetsLessThanId($lastTweetId);
171
172            /** @var Session<int> $session */
173            $session = $this->get('session');
174
175            $session->getFlashBag()->add(
176                'message',
177                sprintf('%s tweets deleted.', $count)
178            );
179        }
180
181        return $this->redirect($this->generateUrl('asynctweets_homepage'));
182    }
183}