Completed
Push — master ( 825c9b...9f04f3 )
by Florian
05:31
created

ApiController   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 189
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 33
eloc 66
dl 0
loc 189
rs 9.76
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A semestersAction() 0 5 1
A eventPrivateAction() 0 3 1
A activeEventAction() 0 16 4
A eventPublicAction() 0 3 2
A canGiveFeedback() 0 25 5
C answerAction() 0 51 16
A finishAction() 0 20 4
1
<?php
2
3
/*
4
 * This file is part of the feedback project.
5
 *
6
 * (c) Florian Moser <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace App\Controller;
13
14
use App\Controller\Base\BaseApiController;
15
use App\Entity\Answer;
16
use App\Entity\Event;
17
use App\Entity\Participant;
18
use App\Entity\Semester;
19
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
20
use Symfony\Component\HttpFoundation\JsonResponse;
21
use Symfony\Component\HttpFoundation\Request;
22
use Symfony\Component\Routing\Annotation\Route;
23
24
/**
25
 * @Route("/api")
26
 */
27
class ApiController extends BaseApiController
28
{
29
    /**
30
     * @Route("/active_event", name="api_active_event")
31
     *
32
     * @return JsonResponse
33
     */
34
    public function activeEventAction()
35
    {
36
        $now = new \DateTime();
37
        $today = $now->format('Y-m-d');
38
        $time = $now->format('H:i');
39
40
        $events = $this->getDoctrine()->getRepository(Event::class)->findBy(['date' => $today]);
41
        foreach ($events as $event) {
42
            if ($event->getFeedbackStartTime() < $time && $event->getFeedbackEndTime() > $time) {
43
                $event->loadTemplateIfSafe($this->getParameter('PUBLIC_DIR'));
44
45
                return $this->returnActiveEvent($event);
46
            }
47
        }
48
49
        return $this->returnActiveEvent(null);
50
    }
51
52
    /**
53
     * @Route("/semesters", name="api_semesters")
54
     *
55
     * @return JsonResponse
56
     */
57
    public function semestersAction()
58
    {
59
        $semesters = $this->getDoctrine()->getRepository(Semester::class)->findBy([], ['name' => 'DESC']);
60
61
        return $this->returnSemester($semesters);
62
    }
63
64
    /**
65
     * @Route("/{event}/public", name="api_event_public")
66
     *
67
     * @param Event $event
68
     *
69
     * @return JsonResponse
70
     */
71
    public function eventPublicAction(Event $event)
72
    {
73
        return $this->returnEventPublic($event->feedbackHasStarted() ? $event : null);
74
    }
75
76
    /**
77
     * @param Event $event
78
     *
79
     * @throws \Exception
80
     *
81
     * @return bool
82
     */
83
    private function canGiveFeedback(Event $event)
84
    {
85
        //prevent hand in too early
86
        if (!$event->feedbackHasStarted()) {
87
            return false;
88
        }
89
90
        //prevent hand in on other days
91
        $now = new \DateTime();
92
        $today = $now->format('Y-m-d');
93
        if ($today !== $event->getDate()) {
94
            return false;
95
        }
96
97
        //prevent hand in too late
98
        $currentTime = $now->format('H:i');
99
        $eventEndTime = \DateTime::createFromFormat('H:i', $event->getFeedbackEndTime());
100
        //allow additional 1 hour to hand in after the feedback has been closed
101
        $threshold = $eventEndTime->add(new \DateInterval('PT1H'))->format('H:i');
102
        //prevent if current time higher than threshold & threshold has not done a wrap around
103
        if ($currentTime > $threshold && $event->getFeedbackEndTime() < $threshold) {
104
            return false;
105
        }
106
107
        return true;
108
    }
109
110
    /**
111
     * @Route("/{event}/answer", name="api_event_answer")
112
     *
113
     * @param Request $request
114
     * @param Event $event
115
     *
116
     * @throws \Exception
117
     *
118
     * @return JsonResponse
119
     */
120
    public function answerAction(Request $request, Event $event)
121
    {
122
        if (!$this->canGiveFeedback($event)) {
123
            return $this->json(false);
124
        }
125
126
        //get request fields
127
        $identifier = $request->request->get('identifier');
128
        $questionNumber = $request->request->get('questionNumber');
129
        $value = $request->request->get('value');
130
        $private = $request->request->get('private') === 'true';
131
        $action = $request->request->get('action', 'override');
132
133
        //ensure all fields set
134
        if (!isset($identifier) || !isset($questionNumber) || !isset($value) || !isset($private) || !\in_array($action, ['override', 'ensure_value_exists', 'remove_value'], true)) {
135
            return $this->json(false);
136
        }
137
138
        //get participant or create a new one
139
        $participant = $this->getDoctrine()->getRepository(Participant::class)->findOneBy(['identifier' => $identifier, 'event' => $event->getId()]);
140
        if ($participant === null) {
141
            $participant = new Participant();
142
            $participant->setEvent($event);
143
            $participant->setIdentifier($identifier);
144
            $this->fastSave($participant);
145
        }
146
147
        //try to find existing answer
148
        $conditions = ['questionNumber' => $questionNumber, 'participant' => $participant->getId()];
149
        if ($action === 'ensure_value_exists' || $action === 'remove_value') {
150
            $conditions += ['value' => $value];
151
        }
152
        $answer = $this->getDoctrine()->getRepository(Answer::class)->findOneBy($conditions);
153
154
        //create new of not found && not want to remove anyways
155
        if ($answer === null && $action !== 'remove_value') {
156
            $answer = new Answer();
157
            $answer->setParticipant($participant);
158
            $answer->setPrivate($private);
159
            $answer->setQuestionNumber($questionNumber);
160
        }
161
        $answer->setValue($value);
162
163
        //process actions
164
        if ($action === 'override' || $action === 'ensure_value_exists') {
165
            $this->fastSave($answer);
166
        } elseif ($action === 'remove_value' && $answer !== null) {
167
            $this->fastRemove($answer);
168
        }
169
170
        return $this->json(true);
171
    }
172
173
    /**
174
     * @Route("/{event}/finish", name="api_event_finish")
175
     *
176
     * @param Request $request
177
     * @param Event $event
178
     *
179
     * @throws \Exception
180
     *
181
     * @return JsonResponse
182
     */
183
    public function finishAction(Request $request, Event $event)
184
    {
185
        if (!$this->canGiveFeedback($event)) {
186
            return $this->json(false);
187
        }
188
189
        //get request fields
190
        $identifier = $request->request->get('identifier');
191
        $timeNeededInMinutes = (int)$request->request->get('timeNeededInMinutes');
192
193
        $participant = $this->getDoctrine()->getRepository(Participant::class)->findOneBy(['identifier' => $identifier, 'event' => $event->getId()]);
194
        if ($participant === null || $participant->getTimeNeededInMinutes() !== null) {
195
            return $this->json(false);
196
        }
197
198
        //set time info
199
        $participant->setTimeNeededInMinutes($timeNeededInMinutes);
200
        $this->fastSave($participant);
201
202
        return $this->json(true);
203
    }
204
205
    /**
206
     * @Route("/{event}/private", name="api_event_private")
207
     * @Security("has_role('ROLE_ADMIN')")
208
     *
209
     * @param Event $event
210
     *
211
     * @return JsonResponse
212
     */
213
    public function eventPrivateAction(Event $event)
214
    {
215
        return $this->returnEventPrivate($event);
216
    }
217
}
218