Passed
Push — master ( 803221...e6765d )
by Florian
03:53
created

ApiController::answerAction()   D

Complexity

Conditions 18
Paths 102

Size

Total Lines 62
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 36
dl 0
loc 62
rs 4.85
c 0
b 0
f 0
cc 18
nc 102
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
        $payload = json_decode($request->getContent());
106
        $requiredFields = ['identifier', 'questionIndex', 'value', 'action'];
107
        foreach ($requiredFields as $requiredField) {
108
            if (!property_exists($payload, $requiredField)) {
109
                return $this->json(false);
110
            }
111
        }
112
113
        //write fields
114
        $identifier = $payload->identifier;
115
        $questionIndex = $payload->questionIndex;
116
        $value = $payload->value;
117
        $action = $payload->action;
118
        $private = property_exists($payload, 'private') && $payload->private === 'true';
119
120
        //ensure all fields set & valid
121
        if (!isset($identifier) || !\is_int($questionIndex) || !isset($value) || !\in_array($action, ['override', 'ensure_value_exists', 'remove_value'], true)) {
122
            dump($request->getContent());
123
124
            return $this->json(3);
125
        }
126
127
        //get participant or create a new one
128
        $participant = $this->getDoctrine()->getRepository(Participant::class)->findOneBy(['identifier' => $identifier, 'event' => $event->getId()]);
129
        if ($participant === null) {
130
            $participant = new Participant();
131
            $participant->setEvent($event);
132
            $participant->setIdentifier($identifier);
133
            $this->fastSave($participant);
134
        }
135
136
        //try to find existing answer
137
        $conditions = ['questionIndex' => $questionIndex, 'participant' => $participant->getId()];
138
        if ($action === 'ensure_value_exists' || $action === 'remove_value') {
139
            $conditions += ['value' => $value];
140
        }
141
        $answer = $this->getDoctrine()->getRepository(Answer::class)->findOneBy($conditions);
142
143
        //create new of not found && not want to remove anyways
144
        if ($answer === null && $action !== 'remove_value') {
145
            $answer = new Answer();
146
            $answer->setParticipant($participant);
147
            $answer->setPrivate($private);
148
            $answer->setQuestionIndex($questionIndex);
149
        }
150
        $answer->setValue($value);
151
152
        //process actions
153
        if ($action === 'override' || $action === 'ensure_value_exists') {
154
            $this->fastSave($answer);
155
        } elseif ($action === 'remove_value' && $answer !== null) {
156
            $this->fastRemove($answer);
157
        }
158
159
        return $this->json(true);
160
    }
161
162
    /**
163
     * @Route("/{event}/finish", name="api_event_finish")
164
     *
165
     * @param Request $request
166
     * @param Event $event
167
     *
168
     * @throws \Exception
169
     *
170
     * @return JsonResponse
171
     */
172
    public function finishAction(Request $request, Event $event)
173
    {
174
        if (!$this->canGiveFeedback($event)) {
175
            return $this->json(false);
176
        }
177
178
        //get request fields
179
        $identifier = $request->request->get('identifier');
180
        $timeNeededInMinutes = (int)$request->request->get('timeNeededInMinutes');
181
182
        $participant = $this->getDoctrine()->getRepository(Participant::class)->findOneBy(['identifier' => $identifier, 'event' => $event->getId()]);
183
        if ($participant === null || $participant->getTimeNeededInMinutes() !== null) {
184
            return $this->json(false);
185
        }
186
187
        //set time info
188
        $participant->setTimeNeededInMinutes($timeNeededInMinutes);
189
        $this->fastSave($participant);
190
191
        return $this->json(true);
192
    }
193
194
    /**
195
     * @Route("/{event}", name="api_event")
196
     *
197
     * @param Event $event
198
     *
199
     * @return JsonResponse
200
     */
201
    public function eventPublicAction(Event $event)
202
    {
203
        return $this->returnEventPublic($event->feedbackHasStarted() ? $event : null);
204
    }
205
206
    /**
207
     * @param Event $event
208
     *
209
     * @throws \Exception
210
     *
211
     * @return bool
212
     */
213
    private function canGiveFeedback(Event $event)
214
    {
215
        //prevent hand in too early
216
        if (!$event->feedbackHasStarted()) {
217
            return false;
218
        }
219
220
        //prevent hand in on other days
221
        $now = new \DateTime();
222
        $today = $now->format('Y-m-d');
223
        if ($today !== $event->getDate()) {
224
            return false;
225
        }
226
227
        //prevent hand in too late
228
        $currentTime = $now->format('H:i');
229
        $eventEndTime = \DateTime::createFromFormat('H:i:s', $event->getFeedbackEndTime());
230
        //allow additional 1 hour to hand in after the feedback has been closed
231
        $threshold = $eventEndTime->add(new \DateInterval('PT1H'))->format('H:i');
232
        //prevent if current time higher than threshold & threshold has not done a wrap around
233
        if ($currentTime > $threshold && $event->getFeedbackEndTime() < $threshold) {
234
            return false;
235
        }
236
237
        return true;
238
    }
239
}
240