Passed
Push — master ( 26caeb...0e28f7 )
by Thomas
11:18
created

EnrollmentCrudController::setup()   B

Complexity

Conditions 8
Paths 48

Size

Total Lines 40
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 22
c 0
b 0
f 0
nc 48
nop 0
dl 0
loc 40
rs 8.4444
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\Paymentmethod;
9
use App\Models\Period;
10
use App\Models\PhoneNumber;
11
use App\Models\ScheduledPayment;
12
use App\Models\Scholarship;
13
use Backpack\CRUD\app\Http\Controllers\CrudController;
14
use Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
15
use Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
16
use Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
17
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
18
use Backpack\CRUD\app\Library\Widget;
19
use Illuminate\Support\Facades\Gate;
20
use Illuminate\Support\Facades\Log;
21
22
/**
23
 * Class EnrollmentCrudController
24
 * This controller is used to view enrollments only.
25
 * No enrollments may be created or updated from here.
26
 */
27
class EnrollmentCrudController extends CrudController
28
{
29
    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...
30
    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...
31
    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...
32
33
    protected string $mode = 'global';
34
35
    protected ?Course $course = null;
36
37
    public function __construct()
38
    {
39
        parent::__construct();
40
        $this->middleware(['permission:enrollments.view']);
41
        $this->middleware('permission:enrollments.delete', ['only' => ['destroy']]);
42
    }
43
44
    public function setup()
45
    {
46
        CRUD::setModel(Enrollment::class);
47
        CRUD::setRoute(config('backpack.base.route_prefix').'/enrollment');
48
        CRUD::setEntityNameStrings(__('enrollment'), __('enrollments'));
0 ignored issues
show
Bug introduced by
It seems like __('enrollment') can also be of type array and array; however, parameter $singular of Backpack\CRUD\app\Librar...:setEntityNameStrings() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

48
        CRUD::setEntityNameStrings(/** @scrutinizer ignore-type */ __('enrollment'), __('enrollments'));
Loading history...
Bug introduced by
It seems like __('enrollments') can also be of type array and array; however, parameter $plural of Backpack\CRUD\app\Librar...:setEntityNameStrings() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

48
        CRUD::setEntityNameStrings(__('enrollment'), /** @scrutinizer ignore-type */ __('enrollments'));
Loading history...
49
50
        if ($this->crud->getRequest()->has('course_id')) {
0 ignored issues
show
Bug introduced by
The method has() does not exist on Illuminate\Http\Request. ( Ignorable by Annotation )

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

50
        if ($this->crud->getRequest()->/** @scrutinizer ignore-call */ has('course_id')) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
51
            $this->mode = 'course';
52
            $this->course = Course::findOrFail($this->crud->getRequest()->course_id);
0 ignored issues
show
Bug introduced by
The property course_id does not seem to exist on Illuminate\Http\Request.
Loading history...
53
54
            if (Gate::forUser(backpack_user())->denies('view-course', $this->course)) {
55
                abort(403);
56
            }
57
58
            CRUD::addClause('course', $this->course->id);
0 ignored issues
show
Unused Code introduced by
The call to Backpack\CRUD\app\Librar...anelFacade::addClause() has too many arguments starting with $this->course->id. ( Ignorable by Annotation )

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

58
            CRUD::/** @scrutinizer ignore-call */ 
59
                  addClause('course', $this->course->id);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
59
        }
60
61
        if ($this->mode === 'course') {
62
            CRUD::denyAccess(['create', 'update', 'delete']);
63
        }
64
65
        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

65
        if (backpack_user()->/** @scrutinizer ignore-call */ hasRole('admin')) {
Loading history...
66
            CRUD::enableExportButtons();
67
        }
68
69
        if ($this->mode === 'global' && $this->crud->getOperation() === 'list') {
70
            $pendingBalance = Enrollment::pending()->sum('balance');
71
72
            Widget::add()->type('view')->view('enrollments.total_balance_widget')->value($pendingBalance)->to('before_content');
0 ignored issues
show
Bug introduced by
The method add() does not exist on Backpack\CRUD\app\Library\Widget. ( Ignorable by Annotation )

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

72
            Widget::/** @scrutinizer ignore-call */ 
73
                    add()->type('view')->view('enrollments.total_balance_widget')->value($pendingBalance)->to('before_content');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
73
//            Widget::add()->type('view')->view('enrollments.total_income_widget')->value($periodIncome)->to('before_content');
74
        }
75
76
        if ($this->mode === 'course') {
77
            Widget::add(['type' => 'view', 'view' => 'partials.course_info', 'course' => $this->course])->to('before_content');
78
79
            CRUD::denyAccess(['show']);
80
            CRUD::addButtonFromView('line', 'showStudent', 'showStudentForEnrollment');
81
82
            CRUD::addButtonFromView('top', 'enroll-student-in-course', 'enroll-student-in-course', 'end');
83
            CRUD::addButtonFromView('top', 'switch-to-photo-roster', 'switch-to-photo-roster', 'end');
84
        }
85
    }
86
87
    /*
88
    |--------------------------------------------------------------------------
89
    | CrudPanel Configuration
90
    |--------------------------------------------------------------------------
91
    */
92
93
    public function setupListOperation()
94
    {
95
        if (config('app.currency_position') === 'before') {
96
            $currency = ['prefix' => config('app.currency_symbol')];
97
        } else {
98
            $currency = ['suffix' => config('app.currency_symbol')];
99
        }
100
101
        CRUD::addColumns([
102
103
            [
104
                'name' => 'id',
105
                'label' => 'ID',
106
            ],
107
108
            [
109
                'label' => __('ID number'),
110
                'type' => 'text',
111
                'name' => 'student.idnumber',
112
            ],
113
114
            [
115
                'name' => 'user',
116
                'key'       => 'user_lastname',
117
                'attribute' => 'lastname',
118
                'label' => __('Last Name'),
119
                'type' => 'relationship',
120
                'searchLogic' => function ($query, $column, $searchTerm) {
121
                    $query->orWhereHas('student', function ($q) use ($searchTerm) {
122
                        $q->whereHas('user', function ($q) use ($searchTerm) {
123
                            $q->where('lastname', 'like', '%'.$searchTerm.'%');
124
                        });
125
                    });
126
                },
127
            ],
128
129
            [
130
                'name' => 'user',
131
                'key'       => 'user_firstname',
132
                'attribute' => 'firstname',
133
                'label' => __('First Name'),
134
                'type' => 'relationship',
135
                'searchLogic' => function ($query, $column, $searchTerm) {
136
                    $query->orWhereHas('student', function ($q) use ($searchTerm) {
137
                        $q->whereHas('user', function ($q) use ($searchTerm) {
138
                            $q->where('firstname', 'like', '%'.$searchTerm.'%');
139
                        });
140
                    });
141
                },
142
            ],
143
144
            [
145
                'label' => __('Age'),
146
                'name' => 'student_age',
147
            ],
148
149
            [
150
                'label' => __('Birthdate'),
151
                'name' => 'student_birthdate',
152
            ],
153
        ]);
154
155
        if ($this->mode === 'global') {
156
            CRUD::addColumns([[// COURSE NAME
157
                'label' => __('Course'), // Table column heading
158
                'type' => 'select', 'name' => 'course_id', // the column that contains the ID of that connected entity;
159
                'entity' => 'course', // the method that defines the relationship in your Model
160
                'attribute' => 'name', // foreign key attribute that is shown to user
161
                'model' => Course::class, // foreign key model
162
            ],
163
164
                ['type' => 'relationship', 'name' => 'course.period', 'label' => __('Period'), 'attribute' => 'name'], ]);
165
        }
166
167
        CRUD::addColumns([
168
            [
169
                // STATUS
170
                'label' => __('Status'), // Table column heading
171
                'type' => 'select',
172
                'name' => 'status_id', // the column that contains the ID of that connected entity;
173
                'entity' => 'enrollmentStatus', // the method that defines the relationship in your Model
174
                'attribute' => 'name', // foreign key attribute that is shown to user
175
                'model' => EnrollmentStatusType::class, // foreign key model
176
            ],
177
178
            array_merge([
179
                'name' => 'balance',
180
                'label' => __('Balance'),
181
                'type' => 'number',
182
            ],
183
            $currency),
184
        ]);
185
186
        if (config('invoicing.allow_scheduled_payments')) {
187
            CRUD::addColumn([
188
                'name' => 'scheduledPayments', // name of relationship method in the model
189
                'type' => 'relationship', 'label' => __('Scheduled Payments'), // OPTIONAL
190
                'attribute' => 'date', 'model' => ScheduledPayment::class, // foreign key model
191
            ]);
192
        }
193
194
        CRUD::addColumns([
195
196
            [
197
                // any type of relationship
198
                'name'         => 'scholarships', // name of relationship method in the model
199
                'type'         => 'relationship',
200
                'label'        => __('Scholarship'),
201
                // OPTIONAL
202
                // 'entity'    => 'tags', // the method that defines the relationship in your Model
203
                'attribute' => 'name', // foreign key attribute that is shown to user
204
                'model'     => Scholarship::class, // foreign key model
205
            ],
206
207
            [
208
                'label'     => __('Email'), // Table column heading
209
                'name' => 'user',
210
                'attribute' => 'email',
211
                'type' => 'relationship',
212
            ],
213
214
            [
215
                'label'     => __('Phone number'), // Table column heading
216
                'type'      => 'select_multiple',
217
                'name'      => 'student.phone', // the method that defines the relationship in your Model
218
                'attribute' => 'phone_number', // foreign key attribute that is shown to user
219
                'model' => PhoneNumber::class, // foreign key model
220
            ],
221
222
        ]);
223
224
        if ($this->mode === 'global') {
225
            CRUD::addFilter([
226
                'name' => 'status_id',
227
                'type' => 'select2_multiple',
228
                'label'=> __('Status'),
229
            ], fn () => EnrollmentStatusType::all()->pluck('name', 'id')->toArray(),
0 ignored issues
show
Bug introduced by
The method toArray() does not exist on Illuminate\Support\Collection. ( Ignorable by Annotation )

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

229
            ], fn () => EnrollmentStatusType::all()->pluck('name', 'id')->/** @scrutinizer ignore-call */ toArray(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
230
            function ($values) {
231
                // if the filter is active
232
                foreach (json_decode($values, null, 512, JSON_THROW_ON_ERROR) as $value) {
233
                    CRUD::addClause('orWhere', 'status_id', $value);
0 ignored issues
show
Unused Code introduced by
The call to Backpack\CRUD\app\Librar...anelFacade::addClause() has too many arguments starting with 'status_id'. ( Ignorable by Annotation )

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

233
                    CRUD::/** @scrutinizer ignore-call */ 
234
                          addClause('orWhere', 'status_id', $value);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
234
                }
235
            });
236
237
            CRUD::addFilter([
238
                'name' => 'period_id',
239
                'type' => 'select2',
240
                'label'=> __('Period'),
241
            ], fn () => Period::all()->pluck('name', 'id')->toArray(), function ($value) {
242
                // if the filter is active
243
                CRUD::addClause('period', $value);
0 ignored issues
show
Unused Code introduced by
The call to Backpack\CRUD\app\Librar...anelFacade::addClause() has too many arguments starting with $value. ( Ignorable by Annotation )

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

243
                CRUD::/** @scrutinizer ignore-call */ 
244
                      addClause('period', $value);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
244
            });
245
246
            CRUD::addFilter(
247
                [
248
                    'name' => 'scholarship',
249
                    'type' => 'select2',
250
                    'label'=> __('Scholarship'),
251
                ],
252
                fn () => Scholarship::all()->pluck('name', 'id')->toArray(),
253
                function ($value) { // if the filter is active
254
                    if ($value == 'all') {
255
                        CRUD::addClause('whereHas', 'scholarships');
0 ignored issues
show
Unused Code introduced by
The call to Backpack\CRUD\app\Librar...anelFacade::addClause() has too many arguments starting with 'scholarships'. ( Ignorable by Annotation )

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

255
                        CRUD::/** @scrutinizer ignore-call */ 
256
                              addClause('whereHas', 'scholarships');

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
256
                    } else {
257
                        CRUD::addClause('whereHas', 'scholarships', function ($q) use ($value) {
258
                            $q->where('scholarships.id', $value);
259
                        });
260
                    }
261
                }
262
            );
263
        }
264
    }
265
266
    public function show($enrollment)
267
    {
268
        // if mode is global, display enrollment
269
        $enrollment = Enrollment::findOrFail($enrollment);
270
271
        // load the products from the invoice tables
272
        $products = $enrollment->invoices()
0 ignored issues
show
Bug introduced by
The method invoices() does not exist on Illuminate\Database\Eloquent\Collection. ( Ignorable by Annotation )

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

272
        $products = $enrollment->/** @scrutinizer ignore-call */ invoices()

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
273
            ->with('invoiceDetails')
274
            ->get();
275
276
        // get related comments
277
        $comments = $enrollment->comments;
0 ignored issues
show
Bug introduced by
The property comments does not seem to exist on Illuminate\Database\Eloquent\Collection.
Loading history...
278
279
        $scholarships = Scholarship::all();
280
281
        $availablePaymentMethods = Paymentmethod::all();
282
283
        //$enrollment->load('invoices')->load('invoices.payments');
284
285
        $writeaccess = $enrollment->status_id !== 2 && backpack_user()->can('enrollments.edit');
0 ignored issues
show
Bug introduced by
The property status_id does not seem to exist on Illuminate\Database\Eloquent\Collection.
Loading history...
286
287
        // then load the page
288
        return view('enrollments.show', compact('enrollment', 'products', 'comments', 'scholarships', 'availablePaymentMethods', 'writeaccess'));
289
    }
290
291
    protected function setupUpdateOperation()
292
    {
293
        if (config('app.currency_position') === 'before') {
294
            $currency = ['prefix' => config('app.currency_symbol')];
295
        } else {
296
            $currency = ['suffix' => config('app.currency_symbol')];
297
        }
298
299
        CRUD::addField([
300
            'label'     => __('Course'),
301
            'type'      => 'select2',
302
            'name'      => 'course_id', // the db column for the foreign key
303
304
            'entity'    => 'course', // the method that defines the relationship in your Model
305
            'model'     => \App\Models\Course::class, // foreign key model
306
            'attribute' => 'name', // foreign key attribute that is shown to user
307
308
            '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\Support\Collection.
Loading history...
Bug introduced by
The property period_id does not seem to exist on Illuminate\Database\Eloquent\Relations\Relation.
Loading history...
309
        ]);
310
311
        CRUD::addField(array_merge([
312
            'name' => 'price', // The db column name
313
            'label' => __('Price'), // Table column heading
314
            'type' => 'number',
315
        ], $currency));
316
317
        if (config('invoicing.allow_scheduled_payments')) {
318
            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]]]);
319
        }
320
321
        CRUD::addField([
322
            'label'     => __('Status'),
323
            'type'      => 'select',
324
            'name'      => 'status_id', // the db column for the foreign key
325
326
            // optional
327
            // 'entity' should point to the method that defines the relationship in your Model
328
            // defining entity will make Backpack guess 'model' and 'attribute'
329
            'entity'    => 'enrollmentStatus',
330
331
            // optional - manually specify the related model and attribute
332
            'model'     => \App\Models\EnrollmentStatusType::class, // related model
333
            'attribute' => 'name', // foreign key attribute that is shown to user
334
        ]);
335
    }
336
337
    public function update()
338
    {
339
        $enrollment = $this->crud->getCurrentEntry();
340
        $newScheduledPayments = collect(json_decode($this->crud->getRequest()->input('scheduledPayments'), null, 512, JSON_THROW_ON_ERROR));
0 ignored issues
show
Bug introduced by
The method input() does not exist on Illuminate\Http\Request. ( Ignorable by Annotation )

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

340
        $newScheduledPayments = collect(json_decode($this->crud->getRequest()->/** @scrutinizer ignore-call */ input('scheduledPayments'), null, 512, JSON_THROW_ON_ERROR));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
341
        $enrollment->saveScheduledPayments($newScheduledPayments);
342
        $response = $this->traitUpdate();
343
344
        return $response;
345
    }
346
347
    public function destroy($enrollment)
348
    {
349
        $enrollment = Enrollment::findOrFail($enrollment);
350
        $enrollment->cancel();
0 ignored issues
show
Bug introduced by
The method cancel() does not exist on Illuminate\Database\Eloquent\Collection. ( Ignorable by Annotation )

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

350
        $enrollment->/** @scrutinizer ignore-call */ 
351
                     cancel();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
351
352
        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...
353
    }
354
}
355