Completed
Push — master ( 1bb378...803221 )
by Florian
04:44
created

ApiController   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 201
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 35
eloc 71
dl 0
loc 201
rs 9.6
c 0
b 0
f 0

7 Methods

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