GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

AjaxController::saveTicketAction()   F
last analyzed

Complexity

Conditions 26
Paths 7824

Size

Total Lines 132
Code Lines 78

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 132
rs 2
cc 26
eloc 78
nc 7824
nop 1

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
 * Created by PhpStorm.
4
 * User: wechsler
5
 * Date: 28/01/2017
6
 * Time: 16:08
7
 */
8
9
namespace Phase\TakeATicketBundle\Controller;
10
11
use Phase\TakeATicket\Model\Instrument;
12
use Phase\TakeATicket\Model\Platform;
13
use Phase\TakeATicketBundle\Entity\User;
14
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
15
use Symfony\Component\HttpFoundation\JsonResponse;
16
use Symfony\Component\HttpFoundation\Request;
17
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
18
19
class AjaxController extends BaseController
20
{
21
    const MANAGER_REQUIRED_ROLE = 'ROLE_ADMIN';
22
    const BAND_IDENTIFIER_BAND_NAME = 1;
23
    const BAND_IDENTIFIER_PERFORMERS = 2;
24
25
    /**
26
     * @var int Whether to identify band by its name or a list of performers
27
     */
28
    protected $bandIdentifier = self::BAND_IDENTIFIER_PERFORMERS;
29
30
    /**
31
     * @return JsonResponse
32
     *
33
     * FIXME does not honour config.displayOptions.songInPreview - always shows track!
34
     */
35
    public function nextSongsAction()
36
    {
37
        //        $this->setJsonErrorHandler();
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
38
        //        $includePrivate = $this->app['security']->isGranted(self::MANAGER_REQUIRED_ROLE);
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
39
        $includePrivate = false;
40
        $next = $this->getDataStore()->fetchUpcomingTickets($includePrivate);
41
        if ($includePrivate) {
42
            $show = $next;
43
        } else {
44
            $show = [];
45
            foreach ($next as $k => $ticket) {
46
                $show[$k] = $ticket;
47
                if ($ticket['blocking']) {
48
                    break;
49
                }
50
            }
51
        }
52
53
        return new JsonResponse($show);
54
    }
55
56
    public function reloadPerformersAction()
57
    {
58
        $performers = $this->getDataStore()->generatePerformerStats();
59
        return new JsonResponse($performers);
60
    }
61
62
    public function songSearchAction(Request $request)
63
    {
64
        $searchString = $request->get('searchString');
65
        $searchCount = 10;
66
        if ($request->get('searchCount')) {
67
            $searchCount = $request->get('searchCount');
68
        }
69
        $dataStore = $this->getDataStore();
70
        $songs = $dataStore->findSongsBySearchString($searchString, $searchCount);
71
        // Need to add sources, instruments
72
        $hydrated = [];
73
74
        foreach ($songs as $song) {
75
            $song = $dataStore->expandSongData($song);
76
77
            $hydrated[] = $song;
78
        }
79
80
        $jsonResponse = new JsonResponse(['ok' => 'ok', 'searchString' => $searchString, 'songs' => $hydrated]);
81
82
        return $jsonResponse;
83
    }
84
85 View Code Duplication
    public function useTicketAction(Request $request)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
86
    {
87
        //        $this->setJsonErrorHandler();
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
88
89
        $this->denyAccessUnlessGranted(self::MANAGER_REQUIRED_ROLE);
90
91
        $id = $request->get('ticketId');
92
        $res = $this->getDataStore()->markTicketUsedById($id);
93
        //FIXME fetch ticket with extra data
94
        if ($res) {
95
            $jsonResponse = new JsonResponse(['ok' => 'ok']);
96
        } else {
97
            $jsonResponse = new JsonResponse(['ok' => 'fail'], 500);
98
        }
99
100
        return $jsonResponse;
101
    }
102
103
    public function remotesRedirectAction()
104
    {
105
        return new JsonResponse($this->getDataStore()->fetchSetting('remotesUrl'));
106
    }
107
108
    public function saveTicketAction(Request $request)
109
    {
110
        if (!$this->getDataStore()->fetchSetting('selfSubmission')) {
111
            $this->denyAccessUnlessGranted(self::MANAGER_REQUIRED_ROLE);
112
        }
113
114
        $title = $request->get('title');
115
        $songKey = $request->get('songId');
116
        $band = $request->get('band') ?: []; // band must be array even if null (as passed by AJAX if no performers)
117
        $private = $request->get('private') === 'true' ? 1 : 0;
118
        $blocking = $request->get('blocking') === 'true' ? 1 : 0;
119
        $existingTicketId = $request->get('existingTicketId');
120
        $submissionKey = trim($request->get('submissionKey'));
121
        $userId = null;
122
123
        if ($this->isGranted(self::MANAGER_REQUIRED_ROLE)) {
124
            $user = $this->getUser();
125
            /** @var User $user */
126
            $userId = $user->getId();
127
        } else {
128
            $blocking = 0;
129
            $private = 1;
130
            if ($existingTicketId) {
131
                throw new AccessDeniedException('Cannot modify existing tickets');
132
            }
133
134
            // Check song is unused, check no performers have more than 3 upcoming songs
135
            // Ensure that name format is valid
136
137
            $dataErrors = [];
138
            $fixableError = false;
139
140
            $ticketsForSong = $this->getDataStore()->getQueueEntriesForSongId($songKey);
141
142
            if (count($ticketsForSong)) {
143
                $dataErrors[] = 'The song is already taken';
144
            }
145
146
            $performerStats = $this->getDataStore()->generatePerformerStats();
147
148
            foreach ($band as $instrumentCandidates) {
149
                foreach ($instrumentCandidates as $candidate) {
150
                    $candidate = trim($candidate);
151
                    if ($candidate) {
152
                        if (preg_match('/\w+ \w+/', $candidate)) {
153
                            foreach ($performerStats as $performerStat) {
154
                                if (($performerStat['songsPending'] > 2) &&
155
                                    !strcasecmp($candidate, $performerStat['performerName'])
156
                                ) {
157
                                    $dataErrors[] = "$candidate has too many songs pending";
158
                                }
159
                            }
160
                        } else {
161
                            $dataErrors[] = "'$candidate' is not a valid name";
162
                        }
163
                    }
164
                }
165
            }
166
167
            if ($this->getDataStore()->fetchSetting('selfSubmissionKey') &&
168
                strcasecmp($submissionKey, $this->getDataStore()->fetchSetting('selfSubmissionKey'))
169
            ) {
170
                $dataErrors[] = 'Secret code wrong or missing';
171
                $fixableError = 'E_BAD_SECRET';
172
            }
173
174
            if ($dataErrors) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $dataErrors of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
175
                $responseData = [
176
                    'status' => 'error',
177
                    'message' => implode(', ', $dataErrors)
178
                ];
179
                if ($fixableError) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $fixableError of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
180
                    $responseData['error'] = $fixableError; // more than one error = faily death.
181
                }
182
                return new JsonResponse($responseData, 200);
183
            }
184
        }
185
186
        $song = null;
187
        $songId = null;
188
189
        if (preg_match('/^[a-f0-9]{6}$/i', $songKey)) {
190
            $song = $this->getDataStore()->fetchSongByKey($songKey);
191
        } elseif (preg_match('/^\d+$/', $songKey)) {
192
            $song = $this->getDataStore()->fetchSongRowById($songKey);
193
        }
194
195
        if ($song) {
196
            $songId = $song['id'];
197
        }
198
199
        if (!$title) {
200
            $title = null;
201
        }
202
203
        if ($existingTicketId) {
204
            $ticketId = $existingTicketId;
205
        } else {
206
            $ticketId = $this->getDataStore()->storeNewTicket($title, $songId, $userId);
207
        }
208
209
        // update even new tickets so that we can add any new columns easily
210
        $updated = ['title' => $title, 'songId' => $songId, 'blocking' => $blocking, 'private' => $private];
211
212
        $this->getDataStore()->updateTicketById(
213
            $ticketId,
214
            $updated
215
        );
216
217
        // think this is legacy?
218
        if ($this->bandIdentifier === self::BAND_IDENTIFIER_PERFORMERS) {
219
            $this->getDataStore()->storeBandToTicket($ticketId, $band);
220
        }
221
222
        $ticket = $this->getDataStore()->fetchTicketById($ticketId);
223
224
        $ticket = $this->getDataStore()->expandTicketData($ticket);
225
226
        $responseData = [
227
            'ticket' => $ticket,
228
            'performers' => $this->getDataStore()->generatePerformerStats(),
229
            'status' => 'ok'
230
        ];
231
232
        if ($ticketId) {
233
            $jsonResponse = new JsonResponse($responseData);
234
        } else {
235
            $jsonResponse = new JsonResponse($responseData, 500);
236
        }
237
238
        return $jsonResponse;
239
    }
240
241 View Code Duplication
    public function deleteTicketAction(Request $request)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
242
    {
243
        $this->denyAccessUnlessGranted(self::MANAGER_REQUIRED_ROLE);
244
245
        $id = $request->get('ticketId');
246
        $res = $this->getDataStore()->deleteTicketById($id);
247
        if ($res) {
248
            $jsonResponse = new JsonResponse(['ok' => 'ok']);
249
        } else {
250
            $jsonResponse = new JsonResponse(['ok' => 'fail'], 500);
251
        }
252
253
        return $jsonResponse;
254
    }
255
256
    /**
257
     * Opaque hash that changes when new tickets are added (may cover further changes in future)
258
     *
259
     * @return JsonResponse
260
     * @throws \Doctrine\DBAL\DBALException
261
     */
262
    public function lastUpdateHashAction()
263
    {
264
        return new JsonResponse(['hash' => count($this->getDataStore()->fetchUndeletedTickets())]);
265
    }
266
267
    public function newTicketOrderAction(Request $request)
268
    {
269
        $this->denyAccessUnlessGranted(self::MANAGER_REQUIRED_ROLE);
270
271
        $idOrder = $request->get('idOrder');
272
273
        if (!is_array($idOrder)) {
274
            throw new \InvalidArgumentException('Order must be array!');
275
        }
276
277
        $res = true;
278
        foreach ($idOrder as $offset => $id) {
279
            $res = $res && $this->getDataStore()->updateTicketOffsetById($id, $offset);
280
        }
281
        if ($res) {
282
            $jsonResponse = new JsonResponse(['ok' => 'ok']);
283
        } else {
284
            $jsonResponse = new JsonResponse(['ok' => 'fail', 'message' => 'Failed to store new sort order'], 500);
285
        }
286
287
        return $jsonResponse;
288
    }
289
}
290