Passed
Push — 1.11.x ( d6c56f...c7cd24 )
by Julito
09:39
created

Positioning::getCourseExercise()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 18
c 1
b 0
f 0
nc 8
nop 4
dl 0
loc 31
rs 9.6666
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
class Positioning extends Plugin
6
{
7
    public $isCoursePlugin = true;
8
    public $table;
9
10
    /**
11
     * Class constructor.
12
     */
13
    protected function __construct()
14
    {
15
        parent::__construct(
16
            '1.0',
17
            'Julio Montoya',
18
            [
19
                'tool_enable' => 'boolean',
20
                'block_course_if_initial_exercise_not_attempted' => 'boolean',
21
                'average_percentage_to_unlock_final_exercise' => 'text',
22
            ]
23
        );
24
25
        $this->table = Database::get_main_table('plugin_positioning_exercise');
26
    }
27
28
    public static function create()
29
    {
30
        static $result = null;
31
32
        return $result ? $result : $result = new self();
33
    }
34
35
    public function install()
36
    {
37
        $table = $this->table;
38
39
        $sql = 'CREATE TABLE IF NOT EXISTS '.$table.' (
40
                id INT unsigned NOT NULL auto_increment PRIMARY KEY,
41
                exercise_id INT unsigned NOT NULL,
42
                c_id INT unsigned NOT NULL,
43
                session_id INT unsigned DEFAULT NULL,
44
                is_initial TINYINT(1) NOT NULL,
45
                is_final TINYINT(1) NOT NULL
46
                )';
47
        Database::query($sql);
48
49
        // Installing course settings
50
        $this->install_course_fields_in_all_courses();
51
    }
52
53
    public function uninstall()
54
    {
55
        $table = $this->table;
56
        Database::query("DROP TABLE IF EXISTS $table");
57
    }
58
59
    public function isInitialExercise($exerciseId, $courseId, $sessionId)
60
    {
61
        $data = $this->getPositionData($exerciseId, $courseId, $sessionId);
62
        if ($data && isset($data['is_initial']) && 1 === (int) $data['is_initial']) {
63
            return true;
64
        }
65
66
        return false;
67
    }
68
69
    public function getPositionData($exerciseId, $courseId, $sessionId)
70
    {
71
        $table = $this->table;
72
        $courseId = (int) $courseId;
73
        $sessionId = (int) $sessionId;
74
75
        $sql = "SELECT * FROM $table
76
                WHERE
77
                    exercise_id = $exerciseId AND
78
                    c_id = $courseId AND
79
                    session_id = $sessionId
80
                    ";
81
        $result = Database::query($sql);
82
83
        if (Database::num_rows($result) > 0) {
84
85
            return Database::fetch_array($result, 'ASSOC');
86
        }
87
88
        return false;
89
    }
90
91
    public function isFinalExercise($exerciseId, $courseId, $sessionId)
92
    {
93
        $data = $this->getPositionData($exerciseId, $courseId, $sessionId);
94
        if ($data && isset($data['is_final']) && 1 === (int) $data['is_final']) {
95
            return true;
96
        }
97
    }
98
99
    public function setInitialExercise($exerciseId, $courseId, $sessionId)
100
    {
101
        $this->setOption('is_initial', $exerciseId, $courseId, $sessionId);
102
    }
103
104
    private function setOption($field, $exerciseId, $courseId, $sessionId)
105
    {
106
        if (!in_array($field, ['is_initial', 'is_final'], true)) {
107
            return false;
108
        }
109
110
        $data = $this->getPositionData($exerciseId, $courseId, $sessionId);
111
        $disableField = $field === 'is_initial' ? 'is_final' : 'is_initial';
112
        if ($data && isset($data['id'])) {
113
            $id = $data['id'];
114
            $sql = "UPDATE $this->table SET
115
                    $field = 1,
116
                    $disableField = 0
117
                    WHERE id = $id";
118
            Database::query($sql);
119
120
            $sql = "DELETE FROM $this->table
121
                    WHERE $field = 1 AND c_id = $courseId AND session_id = $sessionId AND id <> $id";
122
            Database::query($sql);
123
124
        } else {
125
            $params = [
126
                'exercise_id' => $exerciseId,
127
                'c_id' => $courseId,
128
                'session_id' => $sessionId,
129
                $field => 1,
130
                $disableField => 0,
131
            ];
132
            $id = Database::insert($this->table, $params);
133
134
            $sql = "DELETE FROM $this->table
135
                    WHERE $field = 1 AND c_id = $courseId AND session_id = $sessionId AND id <> $id";
136
            Database::query($sql);
137
        }
138
    }
139
140
    public function setFinalExercise($exerciseId, $courseId, $sessionId)
141
    {
142
        $this->setOption('is_final', $exerciseId, $courseId, $sessionId);
143
    }
144
145
    public function blockFinalExercise($userId, $exerciseId, $courseId, $sessionId)
146
    {
147
        $initialData = $this->getInitialExercise($courseId, $sessionId);
148
149
        if (empty($initialData)) {
150
            return false;
151
        }
152
153
        if ($initialData && isset($initialData['exercise_id'])) {
154
            // If this is final exercise?
155
            $finalData = $this->getFinalExercise($courseId, $sessionId);
156
            if (!empty($finalData) && $finalData['exercise_id'] && $exerciseId == $finalData['exercise_id']) {
157
                $initialResults = Event::getExerciseResultsByUser(
0 ignored issues
show
Bug introduced by
The method getExerciseResultsByUser() does not exist on Event. ( Ignorable by Annotation )

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

157
                /** @scrutinizer ignore-call */ 
158
                $initialResults = Event::getExerciseResultsByUser(

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...
158
                    $userId,
159
                    $initialData['exercise_id'],
160
                    $courseId,
161
                    $sessionId
162
                );
163
164
                if (empty($initialResults)) {
165
                    return true;
166
                }
167
168
                $averageToUnlock = (int) $this->get('average_percentage_to_unlock_final_exercise');
169
                if (empty($averageToUnlock)) {
170
                    return false;
171
                }
172
173
                // Check average
174
                $courseInfo = api_get_course_info_by_id($courseId);
175
                $userAverage = (int) Tracking::getAverageStudentScore($userId, $courseInfo['code'], [], $sessionId);
176
177
                if ($userAverage >= $averageToUnlock) {
178
                    return false;
179
                }
180
181
                return true;
182
            } else {
183
                return false;
184
            }
185
        }
186
187
        return true;
188
    }
189
190
    public function getInitialExercise($courseId, $sessionId)
191
    {
192
        return $this->getCourseExercise($courseId, $sessionId, true, false);
193
    }
194
195
    private function getCourseExercise($courseId, $sessionId, $isInitial, $isFinal)
196
    {
197
        $table = $this->table;
198
        $courseId = (int) $courseId;
199
        $sessionId = (int) $sessionId;
200
201
        $sql = "SELECT * FROM $table
202
                WHERE
203
                    c_id = $courseId AND
204
                    session_id = $sessionId
205
                    ";
206
207
        if ($isInitial) {
208
            $sql .= ' AND is_initial = 1 ';
209
        } else {
210
            $sql .= ' AND is_initial = 0 ';
211
        }
212
213
        if ($isFinal) {
214
            $sql .= ' AND is_final = 1 ';
215
        } else {
216
            $sql .= ' AND is_final = 0 ';
217
        }
218
219
        $result = Database::query($sql);
220
221
        if (Database::num_rows($result) > 0) {
222
            return Database::fetch_array($result, 'ASSOC');
223
        }
224
225
        return false;
226
    }
227
228
    public function getFinalExercise($courseId, $sessionId)
229
    {
230
        return $this->getCourseExercise($courseId, $sessionId, false, true);
231
    }
232
}
233