Passed
Push — 1.11.x ( cc82ef...dd378f )
by Angel Fernando Quiroz
09:50
created

RemedialCoursePlugin::getAdvacedCourseList()   D

Complexity

Conditions 23
Paths 82

Size

Total Lines 124
Code Lines 72

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 23
eloc 72
c 1
b 0
f 0
nc 82
nop 3
dl 0
loc 124
rs 4.1666

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
/* For licensing terms, see /license.txt */
4
5
/**
6
 * Class RemedialCoursePlugin.
7
 */
8
class RemedialCoursePlugin extends Plugin
9
{
10
    const SETTING_ENABLED = 'enabled';
11
    const EXTRAFIELD_REMEDIAL_VARIABLE = 'remedialcourselist';
12
    const EXTRAFIELD_ADVACED_VARIABLE = 'advancedcourselist';
13
14
    /**
15
     * RemedialCoursePlugin constructor.
16
     */
17
    protected function __construct()
18
    {
19
        $settings = [
20
            self::SETTING_ENABLED => 'boolean',
21
        ];
22
        parent::__construct(
23
            '1.0',
24
            'Carlos Alvarado',
25
            $settings
26
        );
27
    }
28
29
    /**
30
     * Create a new instance of RemedialCoursePlugin.
31
     */
32
    public static function create(): RemedialCoursePlugin
33
    {
34
        static $result = null;
35
36
        return $result ?: $result = new self();
37
    }
38
39
    /**
40
     * Perform the plugin installation.
41
     */
42
    public function install()
43
    {
44
        $this->saveRemedialField();
45
        $this->saveAdvanceRemedialField();
46
    }
47
48
    /**
49
     * Save the arrangement for remedialcourselist, it is adjusted internally so that the values
50
     * match the necessary ones.
51
     */
52
    public function saveRemedialField()
53
    {
54
        $extraField = new ExtraField('exercise');
55
        $remedialcourselist = $extraField->get_handler_field_info_by_field_variable(self::EXTRAFIELD_REMEDIAL_VARIABLE);
56
        if (false === $remedialcourselist) {
57
            $extraField->save([
58
                'field_type' => ExtraField::FIELD_TYPE_SELECT_MULTIPLE,
59
                'variable' => self::EXTRAFIELD_REMEDIAL_VARIABLE,
60
                'display_text' => 'remedialCourseList',
61
                'default_value' => 1,
62
                'field_order' => 0,
63
                'visible_to_self' => 1,
64
                'visible_to_others' => 0,
65
                'changeable' => 1,
66
                'filter' => 0,
67
            ]);
68
        }
69
    }
70
71
    /**
72
     * Save the arrangement for remedialadvancecourselist, it is adjusted internally so that the values
73
     * match the necessary ones.
74
     */
75
    public function saveAdvanceRemedialField()
76
    {
77
        $extraField = new ExtraField('exercise');
78
        $advancedcourselist = $extraField->get_handler_field_info_by_field_variable(
79
            self::EXTRAFIELD_ADVACED_VARIABLE
80
        );
81
        if (false === $advancedcourselist) {
82
            $extraField->save([
83
                'field_type' => ExtraField::FIELD_TYPE_SELECT_MULTIPLE,
84
                'variable' => self::EXTRAFIELD_ADVACED_VARIABLE,
85
                'display_text' => 'advancedCourseList',
86
                'default_value' => 1,
87
                'field_order' => 0,
88
                'visible_to_self' => 1,
89
                'visible_to_others' => 0,
90
                'changeable' => 1,
91
                'filter' => 0,
92
            ]);
93
        }
94
    }
95
96
    /**
97
     * Set default_value to 0.
98
     */
99
    public function uninstall()
100
    {
101
    }
102
103
    public function get_name(): string
104
    {
105
        return 'remedial_course';
106
    }
107
108
    /**
109
     * When a student completes the number of attempts and fails the exam, she is enrolled in a series of remedial
110
     * courses BT#18165.
111
     *
112
     * @param Exercise $objExercise
113
     * @param int      $userId
114
     * @param int      $sessionId
115
     * @param bool     $review
116
     *
117
     * @return string|null
118
     */
119
    public function getRemedialCourseList(
120
        Exercise $objExercise,
121
        int $userId = 0,
122
        int $sessionId = 0,
123
        bool $review = false
124
    ): ?string {
125
        if ('true' !== $this->get(self::SETTING_ENABLED)) {
126
            return null;
127
        }
128
129
        $field = new ExtraField('exercise');
130
        $remedialField = $field->get_handler_field_info_by_field_variable(self::EXTRAFIELD_REMEDIAL_VARIABLE);
131
132
        if (empty($remedialField)) {
133
            return null;
134
        }
135
136
        $extraFieldValue = new ExtraFieldValue('exercise');
137
        $remedialExcerciseField = $extraFieldValue->get_values_by_handler_and_field_variable(
138
            $objExercise->iId,
139
            self::EXTRAFIELD_REMEDIAL_VARIABLE
140
        );
141
        $remedialCourseIds = explode(';', $remedialExcerciseField['value']);
142
143
        if (empty($remedialExcerciseField['value']) || count($remedialCourseIds) == 0) {
144
            return null;
145
        }
146
147
        $questionExcluded = [
148
            FREE_ANSWER,
149
            ORAL_EXPRESSION,
150
            ANNOTATION,
151
        ];
152
153
        $userId = empty($userId) ? api_get_user_id() : $userId;
154
155
        $exerciseStatInfo = Event::getExerciseResultsByUser(
156
            $userId,
157
            $objExercise->iId,
158
            $objExercise->course_id,
159
            $sessionId
160
        );
161
        $bestAttempt = Event::get_best_attempt_exercise_results_per_user(
162
            $userId,
163
            $objExercise->iId,
164
            $objExercise->course_id,
165
            $sessionId
166
        );
167
168
        foreach ($exerciseStatInfo as $attempt) {
169
            if (!isset($bestAttempt['exe_result']) || $attempt['exe_result'] >= $bestAttempt['exe_result']) {
170
                $bestAttempt = $attempt;
171
            }
172
173
            if (!isset($attempt['question_list'])) {
174
                continue;
175
            }
176
177
            foreach ($attempt['question_list'] as $questionId => $answer) {
178
                $question = Question::read($questionId, api_get_course_info_by_id($attempt['c_id']));
179
                $questionOpen = in_array($question->type, $questionExcluded) && !$review;
180
181
                if (!$questionOpen) {
182
                    continue;
183
                }
184
185
                $score = $attempt['exe_result'];
186
                $comments = Event::get_comments($objExercise->iId, $questionId);
187
188
                if (empty($comments) || $score == 0) {
189
                    return null;
190
                }
191
            }
192
        }
193
194
        if (empty($bestAttempt)) {
195
            return null;
196
        }
197
198
        $bestAttempt['exe_result'] = (int) $bestAttempt['exe_result'];
199
200
        $isPassedPercentage = ExerciseLib::isPassPercentageAttemptPassed(
201
            $objExercise,
202
            $bestAttempt['exe_result'],
203
            $bestAttempt['exe_weighting']
204
        );
205
206
        if ($isPassedPercentage) {
207
            return null;
208
        }
209
210
        $hasAttempts = count($exerciseStatInfo) < $objExercise->selectAttempts();
211
212
        $doSubscriptionToRemedial = !$hasAttempts || $objExercise->isBlockedByPercentage($bestAttempt);
213
214
        if (!$doSubscriptionToRemedial) {
215
            return null;
216
        }
217
218
        $courses = [];
219
        $isInASession = !empty($sessionId);
220
221
        foreach ($remedialCourseIds as $courseId) {
222
            $courseData = api_get_course_info_by_id($courseId);
223
224
            if (empty($courseData)) {
225
                continue;
226
            }
227
228
            if ($isInASession) {
229
                $courseExistsInSession = SessionManager::sessionHasCourse($sessionId, $courseData['code']);
230
231
                if ($courseExistsInSession) {
232
                    SessionManager::subscribe_users_to_session_course([$userId], $sessionId, $courseData['code']);
233
                    $courses[] = $courseData['title'];
234
                }
235
            } else {
236
                $isSubscribed = CourseManager::is_user_subscribed_in_course($userId, $courseData['code']);
237
238
                if (!$isSubscribed) {
239
                    CourseManager::subscribeUser($userId, $courseData['code']);
240
                    $courses[] = $courseData['title'];
241
                }
242
            }
243
        }
244
245
        if (empty($courses)) {
246
            return null;
247
        }
248
249
        return sprintf($this->get_lang('SubscriptionToXRemedialCourses'), implode(' - ', $courses));
250
    }
251
252
    /**
253
     * When a student takes an exam, and he gets an acceptable grade, he is enrolled in a series of courses that
254
     * represent the next level BT#18165.
255
     *
256
     * @param Exercise $objExercise
257
     * @param int      $userId
258
     * @param int      $sessionId
259
     *
260
     * @return string|null
261
     */
262
    public function getAdvancedCourseList(Exercise $objExercise, int $userId = 0, int $sessionId = 0): ?string
263
    {
264
        if ('true' !== $this->get(self::SETTING_ENABLED)) {
265
            return null;
266
        }
267
268
        $field = new ExtraField('exercise');
269
        $advancedCourseField = $field->get_handler_field_info_by_field_variable(self::EXTRAFIELD_ADVACED_VARIABLE);
270
271
        if (false === $advancedCourseField) {
272
            return null;
273
        }
274
275
        $userId = empty($userId) ? api_get_user_id() : $userId;
276
        $bestAttempt = Event::get_best_attempt_exercise_results_per_user(
277
            $userId,
278
            $objExercise->iId,
279
            $objExercise->course_id,
280
            $sessionId
281
        );
282
283
        if (!isset($bestAttempt['exe_result'])) {
284
            // In the case that the result is 0, get_best_attempt_exercise_results_per_user does not return data,
285
            // for that this block is used
286
            $exerciseStatInfo = Event::getExerciseResultsByUser(
287
                $userId,
288
                $objExercise->iId,
289
                $objExercise->course_id,
290
                $sessionId
291
            );
292
            $bestAttempt['exe_result'] = 0;
293
294
            foreach ($exerciseStatInfo as $attempt) {
295
                if ($attempt['exe_result'] >= $bestAttempt['exe_result']) {
296
                    $bestAttempt = $attempt;
297
                }
298
            }
299
        }
300
301
        if (
302
            !isset($bestAttempt['exe_result'])
303
            || !isset($bestAttempt['exe_id'])
304
            || !isset($bestAttempt['exe_weighting'])
305
        ) {
306
            // No try, No exercise id, no defined total
307
            return null;
308
        }
309
310
        $percentSuccess = $objExercise->selectPassPercentage();
311
        $pass = ExerciseLib::isPassPercentageAttemptPassed(
312
            $objExercise,
313
            $bestAttempt['exe_result'],
314
            $bestAttempt['exe_weighting']
315
        );
316
317
        if (0 == $percentSuccess && false == $pass) {
318
            return null;
319
        }
320
321
        $canRemedial = false === $pass;
322
        // Advance Course
323
        $extraFieldValue = new ExtraFieldValue('exercise');
324
        $advanceCourseExcerciseField = $extraFieldValue->get_values_by_handler_and_field_variable(
325
            $objExercise->iId,
326
            self::EXTRAFIELD_ADVACED_VARIABLE
327
        );
328
329
        if ($canRemedial || !isset($advanceCourseExcerciseField['value'])) {
330
            return null;
331
        }
332
333
        $coursesIds = explode(';', $advanceCourseExcerciseField['value']);
334
335
        if (empty($advanceCourseExcerciseField['value']) || count($coursesIds) == 0) {
336
            return null;
337
        }
338
339
        $isInASession = !empty($sessionId);
340
        $courses = [];
341
342
        foreach ($coursesIds as $course) {
343
            $courseData = api_get_course_info_by_id($course);
344
345
            if (empty($courseData) || !isset($courseData['real_id'])) {
346
                continue;
347
            }
348
349
            // if session is 0, always will be true
350
            $courseExistsInSession = true;
351
352
            if ($isInASession) {
353
                $courseExistsInSession = SessionManager::sessionHasCourse($sessionId, $courseData['code']);
354
            }
355
356
            if (!$courseExistsInSession) {
357
                continue;
358
            }
359
360
            $isSubscribed = CourseManager::is_user_subscribed_in_course(
361
                $userId,
362
                $courseData['code'],
363
                $isInASession,
364
                $sessionId
365
            );
366
367
            if (!$isSubscribed) {
368
                CourseManager::subscribeUser(
369
                    $userId,
370
                    $courseData['code'],
371
                    STUDENT,
372
                    $sessionId
373
                );
374
            }
375
376
            $courses[] = $courseData['title'];
377
        }
378
379
        if (empty($courses)) {
380
            return null;
381
        }
382
383
        return sprintf(
384
            $this->get_lang('SubscriptionToXAdvancedCourses'),
385
            implode(' - ', $courses)
386
        );
387
    }
388
}
389