Completed
Push — master ( ac2f13...c623e5 )
by Emmanuel
01:24
created

src/Controllers/TicketControllable.php (6 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
4
namespace RexlManu\LaravelTickets\Controllers;
5
6
7
use Illuminate\Http\JsonResponse;
8
use Illuminate\Http\RedirectResponse;
9
use Illuminate\Http\Request;
10
use Illuminate\Validation\Rule;
11
use Illuminate\View\View;
12
use RexlManu\LaravelTickets\Events\TicketCloseEvent;
13
use RexlManu\LaravelTickets\Events\TicketMessageEvent;
14
use RexlManu\LaravelTickets\Events\TicketOpenEvent;
15
use RexlManu\LaravelTickets\Models\Ticket;
16
use RexlManu\LaravelTickets\Models\TicketMessage;
17
use RexlManu\LaravelTickets\Models\TicketReference;
18
use RexlManu\LaravelTickets\Models\TicketUpload;
19
use RexlManu\LaravelTickets\Rule\TicketReferenceRule;
20
use Symfony\Component\HttpFoundation\BinaryFileResponse;
21
22
/**
23
 * Class TicketController
24
 *
25
 * The main logic of the ticket system. All actions are performed here.
26
 *
27
 * If the accept header is json, the response will be a json response
28
 *
29
 * @package RexlManu\LaravelTickets\Controllers
30
 */
31
trait TicketControllable
32
{
33
34
    /**
35
     * @link TicketControllable constructor
36
     */
37
    public function __construct()
38
    {
39
        if (! config('laravel-tickets.permission')) {
40
            return;
41
        }
42
43
        $this->middleware(config('laravel-tickets.permissions.list-ticket'))->only('index');
0 ignored issues
show
It seems like middleware() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
44
        $this->middleware(config('laravel-tickets.permissions.create-ticket'))->only('store', 'create');
0 ignored issues
show
It seems like middleware() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
45
        $this->middleware(config('laravel-tickets.permissions.close-ticket'))->only('close');
0 ignored issues
show
It seems like middleware() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
46
        $this->middleware(config('laravel-tickets.permissions.show-ticket'))->only('show');
0 ignored issues
show
It seems like middleware() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
47
        $this->middleware(config('laravel-tickets.permissions.message-ticket'))->only('message');
0 ignored issues
show
It seems like middleware() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
48
        $this->middleware(config('laravel-tickets.permissions.download-ticket'))->only('download');
0 ignored issues
show
It seems like middleware() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
49
    }
50
51
    /**
52
     * Show every @return View|JsonResponse
53
     *
54
     * @link Ticket that the user has created
55
     *
56
     * If the accept header is json, the response will be a json response
57
     *
58
     */
59
    public function index()
60
    {
61
        if (\request()->user()->can(config('laravel-tickets.permissions.all-ticket'))) {
62
            $tickets = Ticket::query();
63
        } else {
64
            $tickets = request()->user()->tickets();
65
        }
66
        $tickets = $tickets->orderBy('id', 'desc')->paginate(10);
67
68
        return request()->wantsJson() ?
69
            response()->json(compact('tickets')) :
70
            view('laravel-tickets::tickets.index',
71
                compact('tickets')
72
            );
73
    }
74
75
    /**
76
     * Show the create form
77
     *
78
     * @return View
79
     */
80
    public function create()
81
    {
82
        return view('laravel-tickets::tickets.create');
83
    }
84
85
    /**
86
     * Creates a @param Request $request the request
87
     *
88
     * @return View|JsonResponse|RedirectResponse
89
     * @link Ticket
90
     *
91
     */
92
    public function store(Request $request)
93
    {
94
        $rules = [
95
            'subject' => [ 'required', 'string', 'max:191' ],
96
            'priority' => [ 'required', Rule::in(config('laravel-tickets.priorities')) ],
97
            'message' => [ 'required', 'string' ],
98
            'files' => [ 'max:' . config('laravel-tickets.file.max-files') ],
99
            'files.*' => [
100
                'sometimes',
101
                'file',
102
                'max:' . config('laravel-tickets.file.size-limit'),
103
                'mimes:' . config('laravel-tickets.file.memes'),
104
            ],
105
        ];
106
        if (config('laravel-tickets.category')) {
107
            $rules[ 'category_id' ] = [
108
                'required',
109
                Rule::exists(config('laravel-tickets.database.ticket-categories-table'), 'id'),
110
            ];
111
        }
112
        if (config('laravel-tickets.references')) {
113
            $rules[ 'reference' ] = [
114
                config('laravel-tickets.references-nullable') ? 'nullable' : 'required',
115
                new TicketReferenceRule(),
116
            ];
117
        }
118
        $data = $request->validate($rules);
119
        if ($request->user()->tickets()->where('state', '!=', 'CLOSED')->count() >= config('laravel-tickets.maximal-open-tickets')) {
120
            $message = trans('You have reached the limit of open tickets');
121
            return \request()->wantsJson() ?
122
                response()->json(compact('message')) :
123
                back()->with(
124
                    'message',
125
                    $message
126
                );
127
        }
128
        $ticket = $request->user()->tickets()->create(
129
            $data
130
        );
131
132
        if (array_key_exists('reference', $data)) {
133
            $reference = explode(',', $data[ 'reference' ]);
134
            $ticketReference = new TicketReference();
135
            $ticketReference->ticket()->associate($ticket);
136
            $ticketReference->referenceable()->associate(
137
                resolve($reference[ 0 ])->find($reference[ 1 ])
138
            );
139
            $ticketReference->save();
140
        }
141
142
        $ticketMessage = new TicketMessage($data);
143
        $ticketMessage->user()->associate($request->user());
144
        $ticketMessage->ticket()->associate($ticket);
145
        $ticketMessage->save();
146
147
        $this->handleFiles($data[ 'files' ] ?? [], $ticketMessage);
148
149
        event(new TicketOpenEvent($ticket));
150
151
        $message = trans('The ticket was successfully created');
152
        return $request->wantsJson() ?
153
            response()->json(compact('message', 'ticket', 'ticketMessage')) :
154
            redirect(route(
155
                'laravel-tickets.tickets.show',
156
                compact('ticket')
157
            ))->with(
158
                'message',
159
                $message
160
            );
161
    }
162
163
    /**
164
     * Show detailed informations about the @param Ticket $ticket
165
     *
166
     * @return View|JsonResponse|RedirectResponse|void
167
     * @link Ticket and the informations
168
     *
169
     */
170
    public function show(Ticket $ticket)
171
    {
172 View Code Duplication
        if (! $ticket->user()->get()->contains(\request()->user()) &&
173
            ! request()->user()->can(config('laravel-tickets.permissions.all-ticket'))) {
174
            return abort(403);
175
        }
176
177
        $messages = $ticket->messages()->with('uploads')->orderBy('created_at', 'desc')->paginate(4);
178
179
        return \request()->wantsJson() ?
180
            response()->json(compact(
181
                'ticket',
182
                'messages'
183
            )) :
184
            view('laravel-tickets::tickets.show',
185
                compact(
186
                    'ticket',
187
                    'messages'
188
                )
189
            );
190
    }
191
192
    /**
193
     * Send a message to the @param Request $request
194
     *
195
     * @param Ticket $ticket
196
     *
197
     * @return JsonResponse|RedirectResponse|void
198
     * @link Ticket
199
     *
200
     */
201
    public function message(Request $request, Ticket $ticket)
202
    {
203 View Code Duplication
        if (! $ticket->user()->get()->contains(\request()->user()) &&
204
            ! request()->user()->can(config('laravel-tickets.permissions.all-ticket'))) {
205
            return abort(403);
206
        }
207
208 View Code Duplication
        if (! config('laravel-tickets.open-ticket-with-answer') && $ticket->state === 'CLOSED') {
209
            $message = trans('You cannot reply to a closed ticket');
210
            return \request()->wantsJson() ?
211
                response()->json(compact('message')) :
212
                back()->with(
213
                    'message',
214
                    $message
215
                );
216
        }
217
218
        $data = $request->validate([
219
            'message' => [ 'required', 'string' ],
220
            'files' => [ 'max:' . config('laravel-tickets.file.max-files') ],
221
            'files.*' => [
222
                'sometimes',
223
                'file',
224
                'max:' . config('laravel-tickets.file.size-limit'),
225
                'mimes:' . config('laravel-tickets.file.memes'),
226
            ]
227
        ]);
228
229
        $ticketMessage = new TicketMessage($data);
230
        $ticketMessage->user()->associate($request->user());
231
        $ticketMessage->ticket()->associate($ticket);
232
        $ticketMessage->save();
233
234
        $this->handleFiles($data[ 'files' ] ?? [], $ticketMessage);
235
236
        $ticket->update([ 'state' => 'OPEN' ]);
237
238
        event(new TicketMessageEvent($ticket, $ticketMessage));
239
240
        $message = trans('Your answer was sent successfully');
241
        return $request->wantsJson() ?
242
            response()->json(compact('message')) :
243
            back()->with(
244
                'message',
245
                $message
246
            );
247
    }
248
249
    /**
250
     * Declare the @param Ticket $ticket
251
     *
252
     * @return JsonResponse|RedirectResponse|void
253
     * @link Ticket as closed.
254
     *
255
     */
256
    public function close(Ticket $ticket)
257
    {
258 View Code Duplication
        if (! $ticket->user()->get()->contains(\request()->user()) &&
259
            ! request()->user()->can(config('laravel-tickets.permissions.all-ticket'))) {
260
            return abort(403);
261
        }
262 View Code Duplication
        if ($ticket->state === 'CLOSED') {
263
            $message = trans('The ticket is already closed');
264
            return \request()->wantsJson() ?
265
                response()->json(compact('message')) :
266
                back()->with(
267
                    'message',
268
                    $message
269
                );
270
        }
271
        $ticket->update([ 'state' => 'CLOSED' ]);
272
        event(new TicketCloseEvent($ticket));
273
274
        $message = trans('The ticket was successfully closed');
275
        return \request()->wantsJson() ?
276
            response()->json(compact('message')) :
277
            back()->with(
278
                'message',
279
                $message
280
            );
281
    }
282
283
    /**
284
     * Downloads the file from @param Ticket $ticket
285
     *
286
     * @param TicketUpload $ticketUpload
287
     *
288
     * @return BinaryFileResponse
289
     * @link TicketUpload
290
     *
291
     */
292
    public function download(Ticket $ticket, TicketUpload $ticketUpload)
293
    {
294 View Code Duplication
        if (! $ticket->user()->get()->contains(\request()->user()) &&
295
            ! request()->user()->can(config('laravel-tickets.permissions.all-ticket'))) {
296
            return abort(403);
297
        }
298
299
        $storagePath = storage_path('app/' . $ticketUpload->path);
300
        if (config('laravel-tickets.pdf-force-preview') && pathinfo($ticketUpload->path, PATHINFO_EXTENSION) === 'pdf') {
301
            return response()->file($storagePath);
302
        }
303
304
        return response()->download($storagePath);
305
    }
306
307
    /**
308
     * Handles the uploaded files for the @param $files array uploaded files
309
     *
310
     * @param TicketMessage $ticketMessage
311
     *
312
     * @link TicketMessage
313
     *
314
     */
315
    private function handleFiles($files, TicketMessage $ticketMessage)
316
    {
317
        if (! config('laravel-tickets.files') || $files === null) {
318
            return;
319
        }
320
        foreach ($files as $file) {
321
            $ticketMessage->uploads()->create([
322
                'path' => $file->storeAs(
323
                    config('laravel-tickets.file.path') . $ticketMessage->id,
324
                    $file->getClientOriginalName(),
325
                    config('laravel-tickets.file.driver')
326
                )
327
            ]);
328
        }
329
    }
330
331
}
332