Passed
Push — develop ( dfa246...179c36 )
by Francisco
02:27
created

ExchangeController::store()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 39
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 21
nc 3
nop 1
dl 0
loc 39
rs 8.8571
c 1
b 0
f 0
1
<?php
2
3
namespace App\Http\Controllers;
4
5
use Illuminate\Http\Request;
6
use App\Judite\Models\Exchange;
7
use App\Judite\Models\Enrollment;
8
use Illuminate\Support\Facades\DB;
9
use Illuminate\Support\Facades\Mail;
10
use App\Mail\DeclinedExchangeNotification;
11
use App\Mail\ConfirmedExchangeNotification;
12
use App\Http\Requests\Exchange\CreateRequest;
13
use App\Exceptions\MultipleEnrollmentExchangesException;
14
use App\Exceptions\ExchangeEnrollmentWithoutShiftException;
15
use App\Exceptions\ExchangeEnrollmentsOnDifferentCoursesException;
16
17
class ExchangeController extends Controller
18
{
19
    /**
20
     * Create a new controller instance.
21
     */
22
    public function __construct()
23
    {
24
        $this->middleware('can.exchange');
25
    }
26
27
    /**
28
     * Show the form for creating a new resource.
29
     *
30
     * @param int $enrollmentId
31
     *
32
     * @return \Illuminate\Http\Response
33
     */
34
    public function create($enrollmentId)
35
    {
36
        try {
37
            $data = DB::transaction(function () use ($enrollmentId) {
38
                $enrollment = Enrollment::findOrFail($enrollmentId);
39
                $this->authorize('exchange', $enrollment);
40
41
                if (is_null($enrollment->shift)) {
42
                    throw new \LogicException('Enrollments without associated shifts cannot be exchanged.');
43
                }
44
45
                $matchingEnrollments = Enrollment::similarEnrollments($enrollment)
46
                    ->orderByStudent()
47
                    ->get();
48
49
                return compact('enrollment', 'matchingEnrollments');
50
            });
51
52
            $data['matchingEnrollments'] = $data['matchingEnrollments']->map(function ($item) {
53
                return [
54
                    'id' => $item->id,
55
                    '_toString' => $item->present()->inlineToString(),
56
                ];
57
            });
58
59
            return view('exchanges.create', $data);
0 ignored issues
show
Bug Best Practice introduced by
The expression return view('exchanges.create', $data) returns the type Illuminate\View\View which is incompatible with the documented return type Illuminate\Http\Response.
Loading history...
60
        } catch (\LogicException $e) {
61
            flash($e->getMessage())->error();
62
63
            return redirect()->route('home');
0 ignored issues
show
Bug Best Practice introduced by
The expression return redirect()->route('home') returns the type Illuminate\Http\RedirectResponse which is incompatible with the documented return type Illuminate\Http\Response.
Loading history...
64
        }
65
    }
66
67
    /**
68
     * Store a newly created resource in storage.
69
     *
70
     * @param \App\Http\Requests\Exchange\CreateRequest $request
71
     *
72
     * @return \Illuminate\Http\Response
73
     */
74
    public function store(CreateRequest $request)
75
    {
76
        try {
77
            DB::transaction(function () use ($request) {
78
                $this->validate($request, [
79
                    'from_enrollment_id' => 'exists:enrollments,id',
80
                    'to_enrollment_id' => 'exists:enrollments,id',
81
                ]);
82
83
                $fromEnrollment = Enrollment::find($request->input('from_enrollment_id'));
84
                $toEnrollment = Enrollment::find($request->input('to_enrollment_id'));
85
                $this->authorize('exchange', $fromEnrollment);
86
87
                // Firstly check if the inverse exchange for the same enrollments
88
                // already exists. If the inverse record is found then we will
89
                // exchange and update both enrollments of this exchange.
90
                $exchange = Exchange::findMatchingExchange($fromEnrollment, $toEnrollment);
91
                if (! is_null($exchange)) {
92
                    return $exchange->perform();
93
                }
94
95
                // Otherwise, we create a new exchange between both enrollments
96
                // so the user that owns the target enrollment can confirm the
97
                // exchange and allow the other user to enroll on the shift.
98
                $exchange = Exchange::make();
99
                $exchange->setExchangeEnrollments($fromEnrollment, $toEnrollment);
100
                $exchange->save();
101
102
                return $exchange;
103
            });
104
105
            flash('The exchange was successfully proposed.')->success();
106
        } catch (MultipleEnrollmentExchangesException
107
            | ExchangeEnrollmentsOnDifferentCoursesException
108
            | ExchangeEnrollmentWithoutShiftException $e) {
109
            flash($e->getMessage())->error();
110
        }
111
112
        return redirect()->route('home');
0 ignored issues
show
Bug Best Practice introduced by
The expression return redirect()->route('home') returns the type Illuminate\Http\RedirectResponse which is incompatible with the documented return type Illuminate\Http\Response.
Loading history...
113
    }
114
115
    /**
116
     * Store a confirmation of an exchange in storage.
117
     *
118
     * @param \Illuminate\Http\Request $request
119
     *
120
     * @return \Illuminate\Http\Response
121
     */
122
    public function storeConfirmation(Request $request)
123
    {
124
        $exchange = DB::transaction(function () use ($request) {
125
            $this->validate($request, [
126
                'exchange_id' => 'exists:exchanges,id',
127
            ]);
128
129
            $exchange = Exchange::find($request->input('exchange_id'));
130
            $this->authorize('decide', $exchange);
131
132
            return $exchange->perform();
133
        });
134
135
        flash('The shift exchange request was successfully confirmed.')->success();
136
        Mail::to($exchange->fromStudent()->user)
137
            ->send(new ConfirmedExchangeNotification($exchange));
138
139
        return redirect()->back();
0 ignored issues
show
Bug Best Practice introduced by
The expression return redirect()->back() returns the type Illuminate\Http\RedirectResponse which is incompatible with the documented return type Illuminate\Http\Response.
Loading history...
140
    }
141
142
    /**
143
     * Store a decline of an exchange in storage.
144
     *
145
     * @param \Illuminate\Http\Request $request
146
     *
147
     * @return \Illuminate\Http\Response
148
     */
149
    public function storeDecline(Request $request)
150
    {
151
        $exchange = DB::transaction(function () use ($request) {
152
            $this->validate($request, [
153
                'exchange_id' => 'exists:exchanges,id',
154
            ]);
155
156
            $exchange = Exchange::find($request->input('exchange_id'));
157
            $this->authorize('decide', $exchange);
158
159
            $exchange->delete();
160
161
            return $exchange;
162
        });
163
164
        flash('The shift exchange request was successfully declined.')->success();
165
        Mail::to($exchange->fromStudent()->user)
166
            ->send(new DeclinedExchangeNotification($exchange));
167
168
        return redirect()->back();
0 ignored issues
show
Bug Best Practice introduced by
The expression return redirect()->back() returns the type Illuminate\Http\RedirectResponse which is incompatible with the documented return type Illuminate\Http\Response.
Loading history...
169
    }
170
171
    /**
172
     * Remove the specified resource from storage.
173
     *
174
     * @param \Illuminate\Http\Request $request
175
     *
176
     * @return \Illuminate\Http\Response
177
     */
178
    public function destroy(Request $request)
179
    {
180
        DB::transaction(function () use ($request) {
181
            $this->validate($request, [
182
                'exchange_id' => 'exists:exchanges,id',
183
            ]);
184
185
            $exchange = Exchange::find($request->input('exchange_id'));
186
            $this->authorize('delete', $exchange);
187
188
            $exchange->delete();
189
190
            return $exchange;
191
        });
192
193
        flash('The shift exchange request was successfully deleted.')->success();
194
195
        return redirect()->back();
0 ignored issues
show
Bug Best Practice introduced by
The expression return redirect()->back() returns the type Illuminate\Http\RedirectResponse which is incompatible with the documented return type Illuminate\Http\Response.
Loading history...
196
    }
197
}
198