Completed
Push — master ( 23c605...87092e )
by
unknown
29:58 queued 29:58
created

ExaminationStudentsController::clone()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 71
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 1
Metric Value
cc 5
eloc 43
c 4
b 0
f 1
nc 7
nop 1
dl 0
loc 71
rs 8.9208

How to fix   Long Method   

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;
4
5
use Session;
6
use App\Models\Institution;
7
use Illuminate\Http\Request;
8
use App\Models\Security_user;
9
use App\Models\Academic_period;
10
use App\Models\Education_grade;
11
use App\Models\Institution_class;
12
use App\Models\Institution_shift;
13
use App\Notifications\ExportReady;
14
use Illuminate\Support\Facades\DB;
15
use App\Models\Examination_student;
16
use App\Models\Institution_student;
17
use Illuminate\Support\Facades\Log;
18
use Illuminate\Support\Facades\Storage;
19
use Illuminate\Support\Facades\Response;
20
use App\Models\Institution_class_student;
21
use App\Exports\ExaminationStudentsExport;
22
use App\Imports\ExaminationStudentsImport;
23
use App\Models\Institution_student_admission;
24
25
class ExaminationStudentsController extends Controller
26
{
27
    public function __construct($year = 2019, $grade = 'G5')
28
    {
29
        $this->year = $year;
0 ignored issues
show
Bug Best Practice introduced by
The property year does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
30
        $this->grade = $grade;
0 ignored issues
show
Bug Best Practice introduced by
The property grade does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
31
        $this->student = new Security_user();
0 ignored issues
show
Bug Best Practice introduced by
The property student does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
32
        $this->examination_student = new Examination_student();
0 ignored issues
show
Bug Best Practice introduced by
The property examination_student does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
33
        $this->academic_period =  Academic_period::where('code', '=', $this->year)->first();
0 ignored issues
show
Bug Best Practice introduced by
The property academic_period does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
34
        $this->education_grade = Education_grade::where('code', '=', $this->grade)->first();
0 ignored issues
show
Bug Best Practice introduced by
The property education_grade does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
35
        $this->output = new \Symfony\Component\Console\Output\ConsoleOutput();
0 ignored issues
show
Bug Best Practice introduced by
The property output does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
36
    }
37
38
    public function index()
39
    {
40
        return view('uploadcsv');
41
    }
42
43
    public function uploadFile(Request $request)
44
    {
45
        if ($request->input('submit') != null) {
46
47
            $file = $request->file('file');
48
49
            // File Details
50
            $filename = 'exams_students.csv';
51
            $extension = $file->getClientOriginalExtension();
52
            $fileSize = $file->getSize();
53
54
            // Valid File Extensions
55
            $valid_extension = array("csv");
56
57
            // 40MB in Bytes
58
            $maxFileSize = 40971520;
59
60
            // Check file extension
61
            if (in_array(strtolower($extension), $valid_extension)) {
62
63
                // Check file size
64
                if ($fileSize <= $maxFileSize) {
65
66
                    // File upload location
67
                    Storage::disk('local')->putFileAs(
68
                        'examination/',
69
                        $file,
0 ignored issues
show
Bug introduced by
It seems like $file can also be of type Illuminate\Http\UploadedFile[] and array; however, parameter $file of Illuminate\Filesystem\Fi...temAdapter::putFileAs() does only seem to accept Illuminate\Http\File|Illuminate\Http\UploadedFile, 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

69
                        /** @scrutinizer ignore-type */ $file,
Loading history...
70
                        $filename
71
                    );
72
                    Session::flash('message', 'File upload successfully!');
73
                    // Redirect to index
74
                } else {
75
                    Session::flash('message', 'File too large. File must be less than 20MB.');
76
                }
77
            } else {
78
                Session::flash('message', 'Invalid File Extension.');
79
            }
80
        }
81
        return redirect()->action('ExaminationStudentsController@index');
82
    }
83
84
    /**
85
     * Import students data to the Examinations table 
86
     *
87
     * @return void
88
     */
89
    public static function callOnClick($year, $grade)
90
    {
91
        // Import CSV to Database
92
        $excelFile = "/examination/exams_students.csv";
93
94
        $import = new ExaminationStudentsImport($year, $grade);
95
        try {
96
            $import->import($excelFile, 'local', \Maatwebsite\Excel\Excel::CSV);
97
            if ($import->failures()->count() > 0) {
98
                $errors = $import->failures();
99
                $columns =  [
100
                    'remarks',
101
                    'st_no',
102
                    'stu_no',
103
                    "f_name",
104
                    "medium",
105
                    "gender",
106
                    "b_date",
107
                    "a_income",
108
                    "schoolid",
109
                    "spl_need",
110
                    "pvt_address",
111
                    "disability_type",
112
                    "disability",
113
                    "sp_center"
114
                ];
115
116
                $file = 'examination/errors.csv';
117
                Storage::put($file, implode(',', $columns));
118
119
                foreach ($errors as $error) {
120
                    Storage::append($file, implode(':', $error->errors()) . ',' . implode(',', $error->values()));
121
                }
122
            }
123
        } catch (\Maatwebsite\Excel\Validators\ValidationException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
124
        }
125
    }
126
127
    /**
128
     * updated wrong census
129
     *
130
     * @param [type] $data
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
131
     * @return void
132
     */
133
    public function updateCensusNo($data)
134
    {
135
        $output = new \Symfony\Component\Console\Output\ConsoleOutput();
136
        $student = Security_user::where('openemis_no', $data['nsid'])
137
            ->select('security_users.id')
138
            ->first();
139
        if (!is_null($student)) {
140
            $student = Institution_student::where('student_id', $student['id'])->get()->toArray();
141
            $Institution = Institution::where('code', $data['schoolid'])->get()->toArray();
142
            if (!empty($Institution)) {
143
                $Institution = $Institution[0];
144
                if (count($student) == 1) {
145
                    $student = $student[0];
146
                    if (((int)$Institution['id']) !=  ((int)$student['institution_id'])) {
147
                        $studentClass = Institution_class_student::where('student_id', $student['student_id'])
148
                            ->first();
149
                        Institution_class_student::where('student_id', $student['student_id'])->delete();
150
                        Institution_student::where('student_id', $student['student_id'])
151
                            ->update(['institution_id' =>  $Institution['id']]);
152
                        $class = new Institution_class();
153
                        if (!is_null($studentClass)) {
154
                            $class->updateClassCount($studentClass->toArray());
155
                        }
156
                        $output->writeln('updated student info:' . $data['nsid']);
157
                    }
158
                } else {
159
                    Institution_student::where('institution_id', '<>', $Institution['id'])->where('student_id', $student[0]['student_id'])
160
                        ->delete();
161
                    $output->writeln('updated student info:' . $Institution['id'] . '==' . $Institution['id']);
162
                }
163
            }
164
        }
165
    }
166
167
    /**
168
     * Iterate over existing student's data
169
     *
170
     * @return void
171
     */
172
    public  function doMatch($offset, $limit, $mode)
173
    {
174
        $students = [];
175
        switch ($mode) {
176
            case 'duplicate':
177
                $students =  DB::table('examination_students as es')
178
                    ->select(DB::raw('count(*) as total'), 'e2.*')
179
                    ->where('grade', $this->grade)
180
                    ->where('year', $this->year)
181
                    ->join('examination_students as e2', 'es.nsid', 'e2.nsid')
182
                    ->having('total', '>', 1)
183
                    ->groupBy('e2.st_no')
184
                    ->orderBy('e2.st_no')
185
                    ->offset($offset)
186
                    ->limit($limit)
187
                    ->get()->toArray();
188
                $students = (array) json_decode(json_encode($students));
189
                $this->output->writeln(count($students) . 'students remaining duplicate');
190
                array_walk($students, array($this, 'clone'));
191
                $this->output->writeln('All are generated');
192
                break;
193
            case 'empty';
194
                $students = Examination_student::
195
                     whereNull('nsid')
196
                    ->where('grade', $this->grade)
197
                    ->where('year', $this->year)
198
                    ->offset($offset)
199
                    ->limit($limit)
200
                    ->get()->toArray();
201
                $students = (array) json_decode(json_encode($students));
202
                $this->output->writeln(count($students) . 'students remaining empty');
203
                array_walk($students, array($this, 'clone'));
204
                $this->output->writeln('All are generated');
205
                break;
206
            case 'invalid';
207
                $students = Examination_student::whereRaw('CHAR_LENGTH(nsid) > 11')
208
                    ->where('grade', $this->grade)
209
                    ->where('year', $this->year)
210
                    ->get()->toArray();
211
                $students = (array) json_decode(json_encode($students));
212
                $this->output->writeln(count($students) . 'students remaining with wrong NSID');
213
                array_walk($students, array($this, 'clone'));
214
                $this->output->writeln('All are generated');
215
                break;
216
            case 'count':
217
                $count = Examination_student::distinct('nsid')
218
                    ->where('grade', $this->grade)
219
                    ->where('year', $this->year)
220
                    ->count();
221
                $all = Examination_student::select('nsid')
222
                    ->count();
223
                $this->output->writeln($all . 'Total Unique nsid are: ' . $count);
224
                break;
225
            default:
226
                $students = Examination_student::offset($offset)
227
                    ->where('grade', $this->grade)
228
                    ->where('year', $this->year)
229
                    ->limit($limit)
230
                    ->get()->toArray();
231
                $students = (array) json_decode(json_encode($students));
232
                $this->output->writeln(count($students) . 'students remaining empty');
233
                array_walk($students, array($this, 'clone'));
234
                $this->output->writeln('All are generated');
235
        }
236
    }
237
238
    /**
239
     * Set Examination values
240
     *
241
     * @param array $students
242
     * @return array
243
     */
244
    public function setIsTakingExam($students)
245
    {
246
        $students['taking_g5_exam'] = false;
247
        $students['taking_ol_exam'] = false;
248
        $students['taking_al_exam'] = false;
249
        $students['taking_git_exam'] = false;
250
            switch ($students['grade']) {
251
                case 'G5':
252
                    $students['taking_g5_exam'] = true;
253
                    break;
254
                case 'G4':
255
                    $students['taking_g5_exam'] = true;
256
                    break;
257
                case 'G10':
258
                    $students['taking_ol_exam'] = true;
259
                    break;
260
                case 'G11':
261
                    $students['taking_ol_exam'] = true;
262
                    break;
263
                case 'GIT':
264
                    $students['taking_git_exam'] = true;
265
                    break;
266
            }
267
       
268
        return $students;
269
    }
270
271
272
    /**
273
     * Main function to merge the student's to SIS
274
     *
275
     * @param array $student
276
     * @return void
277
     */
278
    public function clone($student)
279
    {
280
        $student = (array)json_decode(json_encode($student));
281
        //get student matching with same dob and gender
282
283
        $matchedStudent = $this->getMatchingStudents($student);
284
285
        //add 0 to school id 
286
        $student['schoolid'] = str_pad($student['schoolid'], 5, '0', STR_PAD_LEFT);
287
        
288
        // if the first match missing do complete insertion 
289
        $institution = Institution::where('code', '=', $student['schoolid'])->first();
290
        if (!is_null($institution)) {
291
292
            // ge the class lists to belong the school
293
            $institutionClass = Institution_class::where(
294
                [
295
                    'institution_id' => $institution->id,
296
                    'academic_period_id' => $this->academic_period->id
297
                ]
298
            )
299
            ->where( 'education_grade_id','in', [$this->student->education_garde_id])
0 ignored issues
show
Bug introduced by
The property education_garde_id does not seem to exist on App\Models\Security_user. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
300
            ->join('institution_class_grades', 'institution_classes.id', 'institution_class_grades.institution_class_id')->get()->toArray();
301
302
303
            if(!is_null($this->student->education_garde_id)){
304
                $this->education_grade = Education_grade::where('id', '=', $this->student->education_garde_id)->first();
0 ignored issues
show
Bug Best Practice introduced by
The property education_grade does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
305
            }else{
306
                $this->student->education_garde_id = $this->education_grade->id;
307
            }
308
            
309
            // set search variables 
310
            $admissionInfo = [
311
                'instituion_class' => $institutionClass,
312
                'instituion' => $institution,
313
                'education_grade' =>  $this->education_grade,
314
                'academic_period' => $this->academic_period
315
            ];
316
317
            // if no matching found
318
            if (empty($matchedStudent)) {
319
                $sis_student = $this->student->insertExaminationStudent($student);
320
321
                //TODO implement insert student to admission table
322
                $student['id'] = $sis_student['id'];
323
                $sis_student['student_id'] =  $student['id' ];
324
325
                $student = $this->setIsTakingExam($student);
326
                 if (count($institutionClass) == 1) {
327
                    $admissionInfo['instituion_class'] = $institutionClass[0];
328
                     Institution_student::createExaminationData($student, $admissionInfo);
329
                    Institution_student_admission::createExaminationData($student, $admissionInfo);
330
                    Institution_class_student::createExaminationData($student, $admissionInfo);
331
                } else {
332
                     Institution_student_admission::createExaminationData($student, $admissionInfo);
333
                    Institution_student::createExaminationData($student, $admissionInfo);
334
                }
335
                
336
                $this->updateStudentId($student, $sis_student);
337
                // update the matched student's data    
338
            } else {
339
                $student = $this->setIsTakingExam($student);
340
                $studentData = $this->student->updateExaminationStudent($student, $matchedStudent);
341
                $matchedStudent = array_merge((array) $student, $matchedStudent);
342
                $studentData = array_merge((array) $matchedStudent, $studentData);
343
                Institution_student::updateExaminationData($studentData, $admissionInfo);
344
                $this->updateStudentId($student, $studentData);
345
            }
346
        } else {
347
348
            $this->output->writeln('Student ' . $student['st_no'] . ' not imorted' . $student['f_name']);
349
        }
350
    }
351
352
    /**
353
     * This function is implemented similar_text search algorithm 
354
     * to get the most matching name with the existing students
355
     * data set
356
     *
357
     * @param array $student
358
     * @return array
359
     */
360
    public function getMatchingStudents($student)
361
    {
362
        /**
363
         */
364
        $sis_student = $this->student->getMatches($student);
365
        $doe_students =  Examination_student::where('gender', $student['gender'])
366
            ->where('b_date', $student['b_date'])
367
            ->where('schoolid', $student['schoolid'])
368
            ->where('year',$this->year)
369
            ->where('grade',$this->grade)
370
            ->count();
371
        $count = $this->student->getStudentCount($student);
372
373
        $studentData = [];
374
        $sis_users  = (array) json_decode(json_encode($sis_student), true);
375
        // if the same gender same DOE has more than one 
376
        if (($doe_students > 1) || ($count > 1)) {
377
            $studentData = $this->searchSimilarName($student, $sis_users, false);
378
        } else {
379
            $studentData = $this->searchSimilarName($student, $sis_users);
380
        }
381
        return $studentData;
382
    }
383
384
    /**
385
     * Search most matching name
386
     *
387
     * @param array $student
388
     * @param array $sis_students
389
     * @return array
390
     */
391
    public function searchSimilarName($student, $sis_students, $surname_search = true)
392
    {
393
        $highest = [];
394
        $minDistance = 0;
395
        $matches = [];
396
        $data = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $data is dead and can be removed.
Loading history...
397
        foreach ($sis_students as $key => $value) {
398
            similar_text(strtoupper($value['first_name']), (strtoupper($student['f_name'])), $percentage);
399
            $distance = levenshtein(strtoupper($student['f_name']), strtoupper($value['first_name']));
400
            $value['rate'] = $percentage;
401
            switch (true) {
402
                case $value['rate'] == 100;
403
                    $highest = $value;
404
                    break;
405
                case (($distance <= 2) && ($distance < $minDistance));
406
                    $highest = $value;
407
                    $minDistance = $distance;
408
            }
409
        }
410
411
        if ($surname_search) {
412
            if (empty($highest)) {
413
                foreach ($sis_students as $key => $value) {
414
                    //search name with last name
415
                    similar_text(strtoupper(get_l_name($student['f_name'])), strtoupper(get_l_name($value['first_name'])), $percentage);
416
                    $value['rate'] = $percentage;
417
                    switch (true) {
418
                        case ($value['rate'] == 100);
419
                            $highest = $value;
420
                            $matches[] = $value;
421
                            break;
422
                    }
423
                }
424
            }
425
        }
426
427
        if (count($matches) > 1) {
428
            $highest =  $this->searchSimilarName($student, $sis_students, false);
429
        }
430
431
        return $highest;
432
    }
433
434
    /**
435
     * Generate new NSID for students
436
     *
437
     * @param array $student
438
     * @param array $sis_student
439
     * @return void
440
     */
441
    public function updateStudentId($student, $sis_student)
442
    {
443
        try {
444
            $student['nsid'] =  $sis_student['openemis_no'];
445
            // add new NSID to the examinations data set
446
            unset($student['id']);
447
            unset($student['taking_g5_exam']);
448
            unset($student['taking_al_exam']);
449
            unset($student['taking_ol_exam']);
450
            unset($student['taking_git_exam']);
451
            unset($student['total']);
452
            $students['updated_at'] =  now();
0 ignored issues
show
Comprehensibility Best Practice introduced by
$students was never initialized. Although not strictly required by PHP, it is generally a good practice to add $students = array(); before regardless.
Loading history...
453
            $this->examination_student->where('st_no', $student['st_no'])->update($student);
454
            unset($student['st_no']);
455
            $this->output->writeln('Updated  to NSID' . $sis_student['openemis_no']);
456
        } catch (\Exception $th) {
457
            $this->output->writeln('error');
458
            Log::error($th);
459
        }
460
    }
461
462
    /**
463
     * export the all data with NSID
464
     *
465
     * @return void
466
     */
467
    public function export()
468
    {
469
        $adminUser = Security_user::where('username', 'admin')->first();
470
        try {
471
            (new ExaminationStudentsExport($this->year,$this->grade))->store('examination/student_data_with_nsid.' . time() . '.csv');
472
            (new ExportReady($adminUser));
473
        } catch (\Throwable $th) {
474
            //throw $th;
475
        }
476
        return back()->withSuccess('Export started!');
0 ignored issues
show
Bug Best Practice introduced by
The expression return back()->withSuccess('Export started!') also could return the type Illuminate\Http\RedirectResponse which is incompatible with the documented return type void.
Loading history...
477
    }
478
479
    public function downloadErrors()
480
    {
481
482
        $file_path = storage_path() . '/app/examination/errors.csv';
483
        return Response::download($file_path);
484
    }
485
486
    public function downloadProcessedFile()
487
    {
488
489
        $file_path = storage_path() . '/app/examination/student_data_with_nsid.1628499466.csv'; //hard coded file name
490
        return Response::download($file_path);
491
    }
492
}
493