Passed
Push — master ( b2f78d...25098a )
by Thomas
07:15
created

EnrollmentCrudController::setupListOperation()   F

Complexity

Conditions 14
Paths 768

Size

Total Lines 202
Code Lines 117

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 14
eloc 117
c 2
b 1
f 0
nc 768
nop 0
dl 0
loc 202
rs 1.9377

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
namespace App\Http\Controllers\Admin;
4
5
use App\Models\Course;
6
use App\Models\Enrollment;
7
use App\Models\EnrollmentStatusType;
8
use App\Models\Invoice;
9
use App\Models\Paymentmethod;
10
use App\Models\Period;
11
use App\Models\PhoneNumber;
12
use App\Models\ScheduledPayment;
13
use App\Models\Scholarship;
14
use Backpack\CRUD\app\Http\Controllers\CrudController;
15
use Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
16
use Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
17
use Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
18
use Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
19
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
20
use Backpack\CRUD\app\Library\Widget;
21
use Illuminate\Support\Facades\Gate;
22
use Illuminate\Support\Facades\Log;
23
24
/**
25
 * Class EnrollmentCrudController
26
 * This controller is used to view enrollments only.
27
 * No enrollments may be created or updated from here.
28
 */
29
class EnrollmentCrudController extends CrudController
30
{
31
    use ListOperation;
0 ignored issues
show
introduced by
The trait Backpack\CRUD\app\Http\C...perations\ListOperation requires some properties which are not provided by App\Http\Controllers\Adm...nrollmentCrudController: $model, $query, $entity_name_plural
Loading history...
32
    use ShowOperation { show as traitShow; }
0 ignored issues
show
introduced by
The trait Backpack\CRUD\app\Http\C...perations\ShowOperation requires some properties which are not provided by App\Http\Controllers\Adm...nrollmentCrudController: $route, $entity_name
Loading history...
33
    use UpdateOperation { update as traitUpdate; }
0 ignored issues
show
introduced by
The trait Backpack\CRUD\app\Http\C...rations\UpdateOperation requires some properties which are not provided by App\Http\Controllers\Adm...nrollmentCrudController: $entity_name, $model
Loading history...
34
    use DeleteOperation;
35
36
    protected string $mode = 'global';
37
38
    protected ?Course $course = null;
39
40
    public function __construct()
41
    {
42
        parent::__construct();
43
        $this->middleware(['permission:enrollments.view']);
44
        $this->middleware('permission:enrollments.delete', ['only' => ['destroy']]);
45
    }
46
47
    public function setup()
48
    {
49
        CRUD::setModel(Enrollment::class);
50
        CRUD::setRoute(config('backpack.base.route_prefix').'/enrollment');
51
        CRUD::setEntityNameStrings(__('enrollment'), __('enrollments'));
52
    }
53
54
    /*
55
    |--------------------------------------------------------------------------
56
    | CrudPanel Configuration
57
    |--------------------------------------------------------------------------
58
    */
59
60
    public function setupListOperation()
61
    {
62
63
        if ($this->crud->getRequest()->has('course_id')) {
64
            $this->mode = 'course';
65
            $this->course = Course::findOrFail($this->crud->getRequest()->course_id);
66
67
            if (Gate::forUser(backpack_user())->denies('view-course', $this->course)) {
68
                abort(403);
69
            }
70
            CRUD::addClause('course', $this->course->id);
71
        }
72
73
        if ($this->mode === 'course') {
74
            CRUD::denyAccess(['create', 'update', 'delete']);
75
        }
76
77
        if (backpack_user()->hasRole('admin')) {
0 ignored issues
show
Bug introduced by
The method hasRole() does not exist on Illuminate\Contracts\Auth\Authenticatable. It seems like you code against a sub-type of Illuminate\Contracts\Auth\Authenticatable such as Illuminate\Foundation\Auth\User. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

77
        if (backpack_user()->/** @scrutinizer ignore-call */ hasRole('admin')) {
Loading history...
78
            CRUD::enableExportButtons();
79
        }
80
81
        if ($this->mode === 'global' && $this->crud->getOperation() === 'list') {
82
            $pendingBalance = Enrollment::pending()->sum('balance');
83
84
            Widget::add()->type('view')->view('enrollments.total_balance_widget')->value($pendingBalance)->to('before_content');
85
//            Widget::add()->type('view')->view('enrollments.total_income_widget')->value($periodIncome)->to('before_content');
86
        }
87
88
        if ($this->mode === 'course') {
89
            Widget::add(['type' => 'view', 'view' => 'partials.course_info', 'course' => $this->course])->to('before_content');
90
91
            CRUD::denyAccess(['show']);
92
            CRUD::addButtonFromView('line', 'showStudent', 'showStudentForEnrollment');
93
94
            CRUD::addButtonFromView('top', 'enroll-student-in-course', 'enroll-student-in-course', 'end');
95
            CRUD::addButtonFromView('top', 'switch-to-photo-roster', 'switch-to-photo-roster', 'end');
96
        }
97
        
98
        if (config('app.currency_position') === 'before') {
99
            $currency = ['prefix' => config('app.currency_symbol')];
100
        } else {
101
            $currency = ['suffix' => config('app.currency_symbol')];
102
        }
103
104
        CRUD::addColumns([
105
106
            [
107
                'name' => 'id',
108
                'label' => 'ID',
109
            ],
110
111
            [
112
                'label' => __('ID number'),
113
                'type' => 'text',
114
                'name' => 'student.idnumber',
115
            ],
116
117
            [
118
                'name' => 'user',
119
                'key'       => 'user_lastname',
120
                'attribute' => 'lastname',
121
                'label' => __('Last Name'),
122
                'type' => 'relationship',
123
                'searchLogic' => function ($query, $column, $searchTerm) {
124
                    $query->orWhereHas('student', function ($q) use ($searchTerm) {
125
                        $q->whereHas('user', function ($q) use ($searchTerm) {
126
                            $q->where('lastname', 'like', '%'.$searchTerm.'%');
127
                        });
128
                    });
129
                },
130
            ],
131
132
            [
133
                'name' => 'user',
134
                'key'       => 'user_firstname',
135
                'attribute' => 'firstname',
136
                'label' => __('First Name'),
137
                'type' => 'relationship',
138
                'searchLogic' => function ($query, $column, $searchTerm) {
139
                    $query->orWhereHas('student', function ($q) use ($searchTerm) {
140
                        $q->whereHas('user', function ($q) use ($searchTerm) {
141
                            $q->where('firstname', 'like', '%'.$searchTerm.'%');
142
                        });
143
                    });
144
                },
145
            ],
146
147
            [
148
                'label' => __('Age'),
149
                'name' => 'student_age',
150
            ],
151
152
            [
153
                'label' => __('Birthdate'),
154
                'name' => 'student_birthdate',
155
            ],
156
        ]);
157
158
        if ($this->mode === 'global') {
159
            CRUD::addColumns([[// COURSE NAME
160
                'label' => __('Course'), // Table column heading
161
                'type' => 'select', 'name' => 'course_id', // the column that contains the ID of that connected entity;
162
                'entity' => 'course', // the method that defines the relationship in your Model
163
                'attribute' => 'name', // foreign key attribute that is shown to user
164
                'model' => Course::class, // foreign key model
165
            ],
166
167
                ['type' => 'relationship', 'name' => 'course.period', 'label' => __('Period'), 'attribute' => 'name'], ]);
168
        }
169
170
        CRUD::addColumns([
171
            [
172
                // STATUS
173
                'label' => __('Status'), // Table column heading
174
                'type' => 'select',
175
                'name' => 'status_id', // the column that contains the ID of that connected entity;
176
                'entity' => 'enrollmentStatus', // the method that defines the relationship in your Model
177
                'attribute' => 'name', // foreign key attribute that is shown to user
178
                'model' => EnrollmentStatusType::class, // foreign key model
179
            ],
180
181
            array_merge([
182
                'name' => 'balance',
183
                'label' => __('Balance'),
184
                'type' => 'number',
185
            ],
186
            $currency),
187
        ]);
188
189
        if (config('invoicing.allow_scheduled_payments')) {
190
            CRUD::addColumn([
191
                'name' => 'scheduledPayments', // name of relationship method in the model
192
                'type' => 'relationship', 'label' => __('Scheduled Payments'), // OPTIONAL
193
                'attribute' => 'date', 'model' => ScheduledPayment::class, // foreign key model
194
            ]);
195
        }
196
197
        CRUD::addColumns([
198
199
            [
200
                // any type of relationship
201
                'name'         => 'scholarships', // name of relationship method in the model
202
                'type'         => 'relationship',
203
                'label'        => __('Scholarship'),
204
                // OPTIONAL
205
                // 'entity'    => 'tags', // the method that defines the relationship in your Model
206
                'attribute' => 'name', // foreign key attribute that is shown to user
207
                'model'     => Scholarship::class, // foreign key model
208
            ],
209
210
            [
211
                'label'     => __('Email'), // Table column heading
212
                'name' => 'user',
213
                'attribute' => 'email',
214
                'type' => 'relationship',
215
            ],
216
217
            [
218
                'label'     => __('Phone number'), // Table column heading
219
                'type'      => 'select_multiple',
220
                'name'      => 'student.phone', // the method that defines the relationship in your Model
221
                'attribute' => 'phone_number', // foreign key attribute that is shown to user
222
                'model' => PhoneNumber::class, // foreign key model
223
            ],
224
225
        ]);
226
227
        if ($this->mode === 'global') {
228
            CRUD::addFilter([
229
                'name' => 'status_id',
230
                'type' => 'select2_multiple',
231
                'label'=> __('Status'),
232
            ], fn () => EnrollmentStatusType::all()->pluck('name', 'id')->toArray(),
233
            function ($values) {
234
                // if the filter is active
235
                foreach (json_decode($values, null, 512, JSON_THROW_ON_ERROR) as $value) {
236
                    CRUD::addClause('orWhere', 'status_id', $value);
237
                }
238
            });
239
240
            CRUD::addFilter([
241
                'name' => 'period_id',
242
                'type' => 'select2',
243
                'label'=> __('Period'),
244
            ], fn () => Period::all()->pluck('name', 'id')->toArray(), function ($value) {
245
                // if the filter is active
246
                CRUD::addClause('period', $value);
247
            });
248
249
            CRUD::addFilter(
250
                [
251
                    'name' => 'scholarship',
252
                    'type' => 'select2',
253
                    'label'=> __('Scholarship'),
254
                ],
255
                fn () => Scholarship::all()->pluck('name', 'id')->toArray(),
256
                function ($value) { // if the filter is active
257
                    if ($value == 'all') {
258
                        CRUD::addClause('whereHas', 'scholarships');
259
                    } else {
260
                        CRUD::addClause('whereHas', 'scholarships', function ($q) use ($value) {
261
                            $q->where('scholarships.id', $value);
262
                        });
263
                    }
264
                }
265
            );
266
        }
267
    }
268
269
    public function show($enrollment)
270
    {
271
        // if mode is global, display enrollment
272
        $enrollment = Enrollment::findOrFail($enrollment);
273
274
        // load the products from the invoice tables
275
        $products = $enrollment->invoices()
276
            ->with('invoiceDetails')
277
            ->get();
278
279
        // get related comments
280
        $comments = $enrollment->invoices->map(fn (Invoice $invoice) => $invoice->comments)->flatten()->concat($enrollment->comments);
281
282
        $scholarships = Scholarship::all();
283
284
        $availablePaymentMethods = Paymentmethod::all();
285
286
        //$enrollment->load('invoices')->load('invoices.payments');
287
288
        $writeaccess = $enrollment->status_id !== 2 && backpack_user()->can('enrollments.edit');
289
290
        // then load the page
291
        return view('enrollments.show', compact('enrollment', 'products', 'comments', 'scholarships', 'availablePaymentMethods', 'writeaccess'));
292
    }
293
294
    protected function setupUpdateOperation()
295
    {
296
        if (config('app.currency_position') === 'before') {
297
            $currency = ['prefix' => config('app.currency_symbol')];
298
        } else {
299
            $currency = ['suffix' => config('app.currency_symbol')];
300
        }
301
302
        CRUD::addField([
303
            'label'     => __('Course'),
304
            'type'      => 'select2',
305
            'name'      => 'course_id', // the db column for the foreign key
306
307
            'entity'    => 'course', // the method that defines the relationship in your Model
308
            'model'     => \App\Models\Course::class, // foreign key model
309
            'attribute' => 'name', // foreign key attribute that is shown to user
310
311
            'options'   => (fn ($query) => $query->orderBy('level_id', 'ASC')->where('period_id', $this->crud->getCurrentEntry()->course->period_id)->get()),
0 ignored issues
show
Bug introduced by
The property period_id does not seem to exist on Illuminate\Database\Eloquent\Relations\Relation.
Loading history...
312
        ]);
313
314
        CRUD::addField(array_merge([
315
            'name' => 'price', // The db column name
316
            'label' => __('Price'), // Table column heading
317
            'type' => 'number',
318
        ], $currency));
319
320
        if (config('invoicing.allow_scheduled_payments')) {
321
            CRUD::addField(['name' => 'scheduledPayments', 'label' => __('Scheduled Payments'), 'type' => 'repeatable', 'fields' => [['name' => 'date', 'type' => 'date', 'label' => __('Date'), 'wrapper' => ['class' => 'form-group col-md-4']], array_merge(['name' => 'value', 'type' => 'number', 'attributes' => ['step' => 0.01, 'min' => 0], 'label' => __('Value'), 'wrapper' => ['class' => 'form-group col-md-4']], $currency), ['name' => 'status', 'type' => 'radio', 'label' => __('Status'), 'wrapper' => ['class' => 'form-group col-md-4'], 'options' => [1 => __('Pending'), 2 => __('Paid')], 'inline' => true]]]);
322
        }
323
324
        CRUD::addField([
325
            'label'     => __('Status'),
326
            'type'      => 'select',
327
            'name'      => 'status_id', // the db column for the foreign key
328
329
            // optional
330
            // 'entity' should point to the method that defines the relationship in your Model
331
            // defining entity will make Backpack guess 'model' and 'attribute'
332
            'entity'    => 'enrollmentStatus',
333
334
            // optional - manually specify the related model and attribute
335
            'model'     => \App\Models\EnrollmentStatusType::class, // related model
336
            'attribute' => 'name', // foreign key attribute that is shown to user
337
        ]);
338
    }
339
340
    public function update()
341
    {
342
        $enrollment = $this->crud->getCurrentEntry();
343
        if ($this->crud->getRequest()->has('scheduledPayments')) {
344
            $newScheduledPayments = collect(json_decode($this->crud->getRequest()->input('scheduledPayments'), null, 512, JSON_THROW_ON_ERROR));
345
            $enrollment->saveScheduledPayments($newScheduledPayments);
346
        }
347
        $response = $this->traitUpdate();
348
349
        return $response;
350
    }
351
352
    public function destroy($enrollment)
353
    {
354
        $enrollment = Enrollment::findOrFail($enrollment);
355
        $enrollment->cancel();
356
357
        Log::notice('Enrollment canceled by user '.backpack_user()->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
358
    }
359
}
360