Passed
Push — 1.11.x ( c58798...fcc443 )
by Angel Fernando Quiroz
10:54
created

RemedialCoursePlugin::create()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
cc 2
eloc 2
c 3
b 1
f 0
nc 1
nop 0
dl 0
loc 5
rs 10
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
    public function getRemedialCourseList(
109
        Exercise $objExercise,
110
        int $userId = 0,
111
        int $sessionId = 0,
112
        bool $review = false
113
    ): ?string {
114
        if ('true' !== $this->get(self::SETTING_ENABLED)) {
115
            return null;
116
        }
117
118
        $field = new ExtraField('exercise');
119
        $remedialField = $field->get_handler_field_info_by_field_variable(self::EXTRAFIELD_REMEDIAL_VARIABLE);
120
121
        if (empty($remedialField)) {
122
            return null;
123
        }
124
125
        $extraFieldValue = new ExtraFieldValue('exercise');
126
        $remedialExcerciseField = $extraFieldValue->get_values_by_handler_and_field_variable(
127
            $objExercise->iId,
128
            self::EXTRAFIELD_REMEDIAL_VARIABLE
129
        );
130
        $remedialCourseIds = explode(';', $remedialExcerciseField['value']);
131
132
        if (empty($remedialExcerciseField['value']) || count($remedialCourseIds) == 0) {
133
            return null;
134
        }
135
136
        $questionExcluded = [
137
            FREE_ANSWER,
138
            ORAL_EXPRESSION,
139
            ANNOTATION,
140
        ];
141
142
        $userId = empty($userId) ? api_get_user_id() : $userId;
143
144
        $exerciseStatInfo = Event::getExerciseResultsByUser(
145
            $userId,
146
            $objExercise->iId,
147
            $objExercise->course_id,
148
            $sessionId
149
        );
150
        $bestAttempt = Event::get_best_attempt_exercise_results_per_user(
151
            $userId,
152
            $objExercise->iId,
153
            $objExercise->course_id,
154
            $sessionId
155
        );
156
157
        foreach ($exerciseStatInfo as $attempt) {
158
            if (!isset($bestAttempt['exe_result']) || $attempt['exe_result'] >= $bestAttempt['exe_result']) {
159
                $bestAttempt = $attempt;
160
            }
161
162
            if (!isset($attempt['question_list'])) {
163
                continue;
164
            }
165
166
            foreach ($attempt['question_list'] as $questionId => $answer) {
167
                $question = Question::read($questionId, api_get_course_info_by_id($attempt['c_id']));
168
                $questionOpen = in_array($question->type, $questionExcluded) && !$review;
169
170
                if (!$questionOpen) {
171
                    continue;
172
                }
173
174
                $score = $attempt['exe_result'];
175
                $comments = Event::get_comments($objExercise->iId, $questionId);
176
177
                if (empty($comments) || $score == 0) {
178
                    return null;
179
                }
180
            }
181
        }
182
183
        if (empty($bestAttempt)) {
184
            return null;
185
        }
186
187
        $bestAttempt['exe_result'] = (int) $bestAttempt['exe_result'];
188
189
        $isPassedPercentage = ExerciseLib::isPassPercentageAttemptPassed(
190
            $objExercise,
191
            $bestAttempt['exe_result'],
192
            $bestAttempt['exe_weighting']
193
        );
194
195
        if ($isPassedPercentage) {
196
            return null;
197
        }
198
199
        $hasAttempts = count($exerciseStatInfo) < $objExercise->selectAttempts();
200
201
        $doSubscriptionToRemedial = !$hasAttempts || $objExercise->isBlockedByPercentage($bestAttempt);
202
203
        if (!$doSubscriptionToRemedial) {
204
            return null;
205
        }
206
207
        $courses = [];
208
        $isInASession = !empty($sessionId);
209
210
        foreach ($remedialCourseIds as $courseId) {
211
            $courseData = api_get_course_info_by_id($courseId);
212
213
            if (empty($courseData)) {
214
                continue;
215
            }
216
217
            if ($isInASession) {
218
                $courseExistsInSession = SessionManager::sessionHasCourse($sessionId, $courseData['code']);
219
220
                if ($courseExistsInSession) {
221
                    SessionManager::subscribe_users_to_session_course([$userId], $sessionId, $courseData['code']);
222
                    $courses[] = $courseData['title'];
223
                }
224
            } else {
225
                $isSubscribed = CourseManager::is_user_subscribed_in_course($userId, $courseData['code']);
226
227
                if (!$isSubscribed) {
228
                    CourseManager::subscribeUser($userId, $courseData['code']);
229
                    $courses[] = $courseData['title'];
230
                }
231
            }
232
        }
233
234
        if (empty($courses)) {
235
            return null;
236
        }
237
238
        return sprintf($this->get_lang('SubscriptionToXRemedialCourses'), implode(' - ', $courses));
239
    }
240
241
    public function getAdvacedCourseList(Exercise $objExercise, int $userId = 0, int $sessionId = 0): ?string
242
    {
243
        if ('true' !== $this->get(self::SETTING_ENABLED)) {
244
            return null;
245
        }
246
247
        $field = new ExtraField('exercise');
248
        $advancedCourseField = $field->get_handler_field_info_by_field_variable(self::EXTRAFIELD_ADVACED_VARIABLE);
249
250
        if (false === $advancedCourseField) {
251
            return null;
252
        }
253
254
        $userId = empty($userId) ? api_get_user_id() : $userId;
255
        $bestAttempt = Event::get_best_attempt_exercise_results_per_user(
256
            $userId,
257
            $objExercise->iId,
258
            $objExercise->course_id,
259
            $sessionId
260
        );
261
262
        if (!isset($bestAttempt['exe_result'])) {
263
            // In the case that the result is 0, get_best_attempt_exercise_results_per_user does not return data,
264
            // for that this block is used
265
            $exerciseStatInfo = Event::getExerciseResultsByUser(
266
                $userId,
267
                $objExercise->iId,
268
                $objExercise->course_id,
269
                $sessionId
270
            );
271
            $bestAttempt['exe_result'] = 0;
272
273
            foreach ($exerciseStatInfo as $attempt) {
274
                if ($attempt['exe_result'] >= $bestAttempt['exe_result']) {
275
                    $bestAttempt = $attempt;
276
                }
277
            }
278
        }
279
280
        if (
281
            !isset($bestAttempt['exe_result'])
282
            || !isset($bestAttempt['exe_id'])
283
            || !isset($bestAttempt['exe_weighting'])
284
        ) {
285
            // No try, No exercise id, no defined total
286
            return null;
287
        }
288
289
        $percentSuccess = $objExercise->selectPassPercentage();
290
        $pass = ExerciseLib::isPassPercentageAttemptPassed(
291
            $objExercise,
292
            $bestAttempt['exe_result'],
293
            $bestAttempt['exe_weighting']
294
        );
295
296
        if (0 == $percentSuccess && false == $pass) {
297
            return null;
298
        }
299
300
        $canRemedial = false === $pass;
301
        // Advance Course
302
        $extraFieldValue = new ExtraFieldValue('exercise');
303
        $advanceCourseExcerciseField = $extraFieldValue->get_values_by_handler_and_field_variable(
304
            $objExercise->iId,
305
            self::EXTRAFIELD_ADVACED_VARIABLE
306
        );
307
308
        if ($canRemedial || !isset($advanceCourseExcerciseField['value'])) {
309
            return null;
310
        }
311
312
        $coursesIds = explode(';', $advanceCourseExcerciseField['value']);
313
314
        if (empty($advanceCourseExcerciseField['value']) || count($coursesIds) == 0) {
315
            return null;
316
        }
317
318
        $isInASession = !empty($sessionId);
319
        $courses = [];
320
321
        foreach ($coursesIds as $course) {
322
            $courseData = api_get_course_info_by_id($course);
323
324
            if (empty($courseData) || !isset($courseData['real_id'])) {
325
                continue;
326
            }
327
328
            // if session is 0, always will be true
329
            $courseExistsInSession = true;
330
331
            if ($isInASession) {
332
                $courseExistsInSession = SessionManager::sessionHasCourse($sessionId, $courseData['code']);
333
            }
334
335
            if (!$courseExistsInSession) {
336
                continue;
337
            }
338
339
            $isSubscribed = CourseManager::is_user_subscribed_in_course(
340
                $userId,
341
                $courseData['code'],
342
                $isInASession,
343
                $sessionId
344
            );
345
346
            if (!$isSubscribed) {
347
                CourseManager::subscribeUser(
348
                    $userId,
349
                    $courseData['code'],
350
                    STUDENT,
351
                    $sessionId
352
                );
353
            }
354
355
            $courses[] = $courseData['title'];
356
        }
357
358
        if (empty($courses)) {
359
            return null;
360
        }
361
362
        return sprintf(
363
            $this->get_lang('SubscriptionToXAdvancedCourses'),
364
            implode(' - ', $courses)
365
        );
366
    }
367
}
368