|
1
|
|
|
<?php |
|
2
|
|
|
/* For licensing terms, see /license.txt */ |
|
3
|
|
|
|
|
4
|
|
|
/** |
|
5
|
|
|
* Gradebook link to student publication item. |
|
6
|
|
|
* |
|
7
|
|
|
* @author Bert Steppé |
|
8
|
|
|
* |
|
9
|
|
|
* @package chamilo.gradebook |
|
10
|
|
|
*/ |
|
11
|
|
|
class StudentPublicationLink extends AbstractLink |
|
12
|
|
|
{ |
|
13
|
|
|
private $studpub_table = null; |
|
14
|
|
|
private $itemprop_table = null; |
|
15
|
|
|
|
|
16
|
|
|
/** |
|
17
|
|
|
* Constructor. |
|
18
|
|
|
*/ |
|
19
|
|
|
public function __construct() |
|
20
|
|
|
{ |
|
21
|
|
|
parent::__construct(); |
|
22
|
|
|
$this->set_type(LINK_STUDENTPUBLICATION); |
|
23
|
|
|
} |
|
24
|
|
|
|
|
25
|
|
|
/** |
|
26
|
|
|
* Returns the URL of a document |
|
27
|
|
|
* This function is loaded when using a gradebook as a tab (gradebook = -1) |
|
28
|
|
|
* see issue #2705. |
|
29
|
|
|
*/ |
|
30
|
|
|
public function get_view_url($stud_id) |
|
31
|
|
|
{ |
|
32
|
|
|
return null; |
|
33
|
|
|
// find a file uploaded by the given student, |
|
34
|
|
|
// with the same title as the evaluation name |
|
35
|
|
|
|
|
36
|
|
|
$eval = $this->get_evaluation(); |
|
|
|
|
|
|
37
|
|
|
$stud_id = intval($stud_id); |
|
38
|
|
|
$itemProperty = $this->get_itemprop_table(); |
|
39
|
|
|
$workTable = $this->get_studpub_table(); |
|
40
|
|
|
$courseId = $this->course_id; |
|
41
|
|
|
|
|
42
|
|
|
$sql = "SELECT pub.url |
|
43
|
|
|
FROM $itemProperty prop INNER JOIN $workTable pub |
|
44
|
|
|
ON (prop.c_id = pub.c_id AND prop.ref = pub.id) |
|
45
|
|
|
WHERE |
|
46
|
|
|
prop.c_id = ".$courseId." AND |
|
47
|
|
|
pub.c_id = ".$courseId." AND |
|
48
|
|
|
prop.tool = 'work' AND |
|
49
|
|
|
prop.insert_user_id = $stud_id AND |
|
50
|
|
|
pub.title = '".Database::escape_string($eval->get_name())."' AND |
|
51
|
|
|
pub.session_id=".api_get_session_id(); |
|
52
|
|
|
|
|
53
|
|
|
$result = Database::query($sql); |
|
54
|
|
|
if ($fileurl = Database::fetch_row($result)) { |
|
55
|
|
|
return null; |
|
56
|
|
|
} else { |
|
57
|
|
|
return null; |
|
58
|
|
|
} |
|
59
|
|
|
} |
|
60
|
|
|
|
|
61
|
|
|
/** |
|
62
|
|
|
* @return string |
|
63
|
|
|
*/ |
|
64
|
|
|
public function get_type_name() |
|
65
|
|
|
{ |
|
66
|
|
|
return get_lang('Works'); |
|
67
|
|
|
} |
|
68
|
|
|
|
|
69
|
|
|
public function is_allowed_to_change_name() |
|
70
|
|
|
{ |
|
71
|
|
|
return false; |
|
72
|
|
|
} |
|
73
|
|
|
|
|
74
|
|
|
/** |
|
75
|
|
|
* Generate an array of all exercises available. |
|
76
|
|
|
* |
|
77
|
|
|
* @return array 2-dimensional array - every element contains 2 subelements (id, name) |
|
78
|
|
|
*/ |
|
79
|
|
|
public function get_all_links() |
|
80
|
|
|
{ |
|
81
|
|
|
if (empty($this->course_code)) { |
|
82
|
|
|
return []; |
|
83
|
|
|
} |
|
84
|
|
|
$em = Database::getManager(); |
|
85
|
|
|
$session = $em->find('ChamiloCoreBundle:Session', api_get_session_id()); |
|
86
|
|
|
/* |
|
87
|
|
|
if (empty($session_id)) { |
|
88
|
|
|
$session_condition = api_get_session_condition(0, true); |
|
89
|
|
|
} else { |
|
90
|
|
|
$session_condition = api_get_session_condition($session_id, true, true); |
|
91
|
|
|
} |
|
92
|
|
|
$sql = "SELECT id, url, title FROM $tbl_grade_links |
|
93
|
|
|
WHERE c_id = {$this->course_id} AND filetype='folder' AND active = 1 $session_condition ";*/ |
|
94
|
|
|
|
|
95
|
|
|
//Only show works from the session |
|
96
|
|
|
//AND has_properties != '' |
|
97
|
|
|
$links = $em |
|
98
|
|
|
->getRepository('ChamiloCourseBundle:CStudentPublication') |
|
99
|
|
|
->findBy([ |
|
100
|
|
|
'cId' => $this->course_id, |
|
101
|
|
|
'active' => true, |
|
102
|
|
|
'filetype' => 'folder', |
|
103
|
|
|
'session' => $session, |
|
104
|
|
|
]); |
|
105
|
|
|
|
|
106
|
|
|
foreach ($links as $data) { |
|
107
|
|
|
$work_name = $data->getTitle(); |
|
108
|
|
|
if (empty($work_name)) { |
|
109
|
|
|
$work_name = basename($data->getUrl()); |
|
110
|
|
|
} |
|
111
|
|
|
$cats[] = [$data->getId(), $work_name]; |
|
112
|
|
|
} |
|
113
|
|
|
$cats = isset($cats) ? $cats : []; |
|
|
|
|
|
|
114
|
|
|
|
|
115
|
|
|
return $cats; |
|
116
|
|
|
} |
|
117
|
|
|
|
|
118
|
|
|
/** |
|
119
|
|
|
* Has anyone done this exercise yet ? |
|
120
|
|
|
*/ |
|
121
|
|
|
public function has_results() |
|
122
|
|
|
{ |
|
123
|
|
|
$data = $this->get_exercise_data(); |
|
124
|
|
|
|
|
125
|
|
|
if (empty($data)) { |
|
126
|
|
|
return ''; |
|
|
|
|
|
|
127
|
|
|
} |
|
128
|
|
|
$id = $data['id']; |
|
129
|
|
|
|
|
130
|
|
|
$em = Database::getManager(); |
|
131
|
|
|
$session = $em->find('ChamiloCoreBundle:Session', api_get_session_id()); |
|
132
|
|
|
$results = $em |
|
133
|
|
|
->getRepository('ChamiloCourseBundle:CStudentPublication') |
|
134
|
|
|
->findBy([ |
|
135
|
|
|
'cId' => $this->course_id, |
|
136
|
|
|
'parentId' => $id, |
|
137
|
|
|
'session' => $session, |
|
138
|
|
|
]); |
|
139
|
|
|
|
|
140
|
|
|
return count($results) != 0; |
|
141
|
|
|
} |
|
142
|
|
|
|
|
143
|
|
|
/** |
|
144
|
|
|
* @param null $stud_id |
|
|
|
|
|
|
145
|
|
|
* |
|
146
|
|
|
* @return array |
|
147
|
|
|
*/ |
|
148
|
|
|
public function calc_score($stud_id = null, $type = null) |
|
149
|
|
|
{ |
|
150
|
|
|
$stud_id = (int) $stud_id; |
|
151
|
|
|
$em = Database::getManager(); |
|
152
|
|
|
$data = $this->get_exercise_data(); |
|
153
|
|
|
|
|
154
|
|
|
if (empty($data)) { |
|
155
|
|
|
return []; |
|
156
|
|
|
} |
|
157
|
|
|
$id = $data['id']; |
|
158
|
|
|
$session = $em->find('ChamiloCoreBundle:Session', api_get_session_id()); |
|
159
|
|
|
|
|
160
|
|
|
$assignment = $em |
|
161
|
|
|
->getRepository('ChamiloCourseBundle:CStudentPublication') |
|
162
|
|
|
->findOneBy([ |
|
163
|
|
|
'cId' => $this->course_id, |
|
164
|
|
|
'id' => $id, |
|
165
|
|
|
'session' => $session, |
|
166
|
|
|
]) |
|
167
|
|
|
; |
|
168
|
|
|
|
|
169
|
|
|
$parentId = !$assignment ? 0 : $assignment->getId(); |
|
170
|
|
|
|
|
171
|
|
|
if (empty($session)) { |
|
172
|
|
|
$dql = 'SELECT a FROM ChamiloCourseBundle:CStudentPublication a |
|
173
|
|
|
WHERE |
|
174
|
|
|
a.cId = :course AND |
|
175
|
|
|
a.active = :active AND |
|
176
|
|
|
a.parentId = :parent AND |
|
177
|
|
|
a.session is null AND |
|
178
|
|
|
a.qualificatorId <> 0 |
|
179
|
|
|
'; |
|
180
|
|
|
|
|
181
|
|
|
$params = [ |
|
182
|
|
|
'course' => $this->course_id, |
|
183
|
|
|
'parent' => $parentId, |
|
184
|
|
|
'active' => true, |
|
185
|
|
|
]; |
|
186
|
|
|
} else { |
|
187
|
|
|
$dql = 'SELECT a FROM ChamiloCourseBundle:CStudentPublication a |
|
188
|
|
|
WHERE |
|
189
|
|
|
a.cId = :course AND |
|
190
|
|
|
a.active = :active AND |
|
191
|
|
|
a.parentId = :parent AND |
|
192
|
|
|
a.session = :session AND |
|
193
|
|
|
a.qualificatorId <> 0 |
|
194
|
|
|
'; |
|
195
|
|
|
|
|
196
|
|
|
$params = [ |
|
197
|
|
|
'course' => $this->course_id, |
|
198
|
|
|
'parent' => $parentId, |
|
199
|
|
|
'session' => $session, |
|
200
|
|
|
'active' => true, |
|
201
|
|
|
]; |
|
202
|
|
|
} |
|
203
|
|
|
|
|
204
|
|
|
if (!empty($stud_id)) { |
|
205
|
|
|
$dql .= ' AND a.userId = :student '; |
|
206
|
|
|
$params['student'] = $stud_id; |
|
207
|
|
|
} |
|
208
|
|
|
|
|
209
|
|
|
$order = api_get_setting('student_publication_to_take_in_gradebook'); |
|
210
|
|
|
|
|
211
|
|
|
switch ($order) { |
|
212
|
|
|
case 'last': |
|
213
|
|
|
// latest attempt |
|
214
|
|
|
$dql .= ' ORDER BY a.sentDate DESC'; |
|
215
|
|
|
break; |
|
216
|
|
|
case 'first': |
|
217
|
|
|
default: |
|
218
|
|
|
// first attempt |
|
219
|
|
|
$dql .= ' ORDER BY a.id'; |
|
220
|
|
|
break; |
|
221
|
|
|
} |
|
222
|
|
|
|
|
223
|
|
|
$scores = $em->createQuery($dql)->execute($params); |
|
224
|
|
|
|
|
225
|
|
|
// for 1 student |
|
226
|
|
|
if (!empty($stud_id)) { |
|
227
|
|
|
if (!count($scores)) { |
|
228
|
|
|
return ''; |
|
|
|
|
|
|
229
|
|
|
} |
|
230
|
|
|
|
|
231
|
|
|
$data = $scores[0]; |
|
232
|
|
|
|
|
233
|
|
|
return [ |
|
234
|
|
|
$data->getQualification(), |
|
235
|
|
|
$assignment->getQualification(), |
|
236
|
|
|
]; |
|
237
|
|
|
} |
|
238
|
|
|
|
|
239
|
|
|
$students = []; // user list, needed to make sure we only |
|
240
|
|
|
// take first attempts into account |
|
241
|
|
|
$rescount = 0; |
|
242
|
|
|
$sum = 0; |
|
243
|
|
|
$bestResult = 0; |
|
244
|
|
|
$weight = 0; |
|
245
|
|
|
$sumResult = 0; |
|
246
|
|
|
|
|
247
|
|
|
foreach ($scores as $data) { |
|
248
|
|
|
if (!(array_key_exists($data->getUserId(), $students))) { |
|
249
|
|
|
if ($assignment->getQualification() != 0) { |
|
250
|
|
|
$students[$data->getUserId()] = $data->getQualification(); |
|
251
|
|
|
$rescount++; |
|
252
|
|
|
$sum += $data->getQualification() / $assignment->getQualification(); |
|
253
|
|
|
$sumResult += $data->getQualification(); |
|
254
|
|
|
|
|
255
|
|
|
if ($data->getQualification() > $bestResult) { |
|
256
|
|
|
$bestResult = $data->getQualification(); |
|
257
|
|
|
} |
|
258
|
|
|
$weight = $assignment->getQualification(); |
|
259
|
|
|
} |
|
260
|
|
|
} |
|
261
|
|
|
} |
|
262
|
|
|
|
|
263
|
|
|
if ($rescount == 0) { |
|
264
|
|
|
return null; |
|
265
|
|
|
} |
|
266
|
|
|
|
|
267
|
|
|
switch ($type) { |
|
268
|
|
|
case 'best': |
|
269
|
|
|
return [$bestResult, $weight]; |
|
270
|
|
|
break; |
|
|
|
|
|
|
271
|
|
|
case 'average': |
|
272
|
|
|
return [$sumResult / $rescount, $weight]; |
|
273
|
|
|
break; |
|
274
|
|
|
case 'ranking': |
|
275
|
|
|
return AbstractLink::getCurrentUserRanking($stud_id, $students); |
|
276
|
|
|
break; |
|
277
|
|
|
default: |
|
278
|
|
|
return [$sum, $rescount]; |
|
279
|
|
|
break; |
|
280
|
|
|
} |
|
281
|
|
|
} |
|
282
|
|
|
|
|
283
|
|
|
public function needs_name_and_description() |
|
284
|
|
|
{ |
|
285
|
|
|
return false; |
|
286
|
|
|
} |
|
287
|
|
|
|
|
288
|
|
|
public function get_name() |
|
289
|
|
|
{ |
|
290
|
|
|
$this->get_exercise_data(); |
|
291
|
|
|
$name = isset($this->exercise_data['title']) && !empty($this->exercise_data['title']) ? $this->exercise_data['title'] : get_lang('Untitled'); |
|
292
|
|
|
|
|
293
|
|
|
return $name; |
|
294
|
|
|
} |
|
295
|
|
|
|
|
296
|
|
|
public function get_description() |
|
297
|
|
|
{ |
|
298
|
|
|
$this->get_exercise_data(); |
|
299
|
|
|
|
|
300
|
|
|
return isset($this->exercise_data['description']) ? $this->exercise_data['description'] : null; |
|
301
|
|
|
} |
|
302
|
|
|
|
|
303
|
|
|
public function get_link() |
|
304
|
|
|
{ |
|
305
|
|
|
$session_id = api_get_session_id(); |
|
306
|
|
|
$url = api_get_path(WEB_PATH).'main/work/work.php?'.api_get_cidreq_params($this->get_course_code(), $session_id).'&id='.$this->exercise_data['id'].'&gradebook=view'; |
|
307
|
|
|
|
|
308
|
|
|
return $url; |
|
309
|
|
|
} |
|
310
|
|
|
|
|
311
|
|
|
public function needs_max() |
|
312
|
|
|
{ |
|
313
|
|
|
return false; |
|
314
|
|
|
} |
|
315
|
|
|
|
|
316
|
|
|
public function needs_results() |
|
317
|
|
|
{ |
|
318
|
|
|
return false; |
|
319
|
|
|
} |
|
320
|
|
|
|
|
321
|
|
|
public function is_valid_link() |
|
322
|
|
|
{ |
|
323
|
|
|
$data = $this->get_exercise_data(); |
|
324
|
|
|
|
|
325
|
|
|
if (empty($data)) { |
|
326
|
|
|
return ''; |
|
|
|
|
|
|
327
|
|
|
} |
|
328
|
|
|
$id = $data['id']; |
|
329
|
|
|
$sql = 'SELECT count(id) FROM '.$this->get_studpub_table().' |
|
330
|
|
|
WHERE |
|
331
|
|
|
c_id = "'.$this->course_id.'" AND |
|
332
|
|
|
id = '.$id.''; |
|
333
|
|
|
$result = Database::query($sql); |
|
334
|
|
|
$number = Database::fetch_row($result); |
|
335
|
|
|
|
|
336
|
|
|
return $number[0] != 0; |
|
337
|
|
|
} |
|
338
|
|
|
|
|
339
|
|
|
public function get_icon_name() |
|
340
|
|
|
{ |
|
341
|
|
|
return 'studentpublication'; |
|
342
|
|
|
} |
|
343
|
|
|
|
|
344
|
|
|
public function save_linked_data() |
|
345
|
|
|
{ |
|
346
|
|
|
$data = $this->get_exercise_data(); |
|
347
|
|
|
|
|
348
|
|
|
if (empty($data)) { |
|
349
|
|
|
return ''; |
|
350
|
|
|
} |
|
351
|
|
|
$id = $data['id']; |
|
352
|
|
|
|
|
353
|
|
|
$weight = api_float_val($this->get_weight()); |
|
354
|
|
|
if (!empty($id)) { |
|
355
|
|
|
//Cleans works |
|
356
|
|
|
$sql = 'UPDATE '.$this->get_studpub_table().' |
|
357
|
|
|
SET weight= '.$weight.' |
|
358
|
|
|
WHERE c_id = '.$this->course_id.' AND id ='.$id; |
|
359
|
|
|
Database::query($sql); |
|
360
|
|
|
} |
|
361
|
|
|
} |
|
362
|
|
|
|
|
363
|
|
|
/** |
|
364
|
|
|
* @return string |
|
365
|
|
|
*/ |
|
366
|
|
|
public function delete_linked_data() |
|
367
|
|
|
{ |
|
368
|
|
|
$data = $this->get_exercise_data(); |
|
369
|
|
|
if (empty($data)) { |
|
370
|
|
|
return ''; |
|
371
|
|
|
} |
|
372
|
|
|
|
|
373
|
|
|
if (!empty($id)) { |
|
|
|
|
|
|
374
|
|
|
//Cleans works |
|
375
|
|
|
$sql = 'UPDATE '.$this->get_studpub_table().' |
|
376
|
|
|
SET weight = 0 |
|
377
|
|
|
WHERE c_id = '.$this->course_id.' AND id ='.$id; |
|
378
|
|
|
Database::query($sql); |
|
379
|
|
|
} |
|
380
|
|
|
} |
|
381
|
|
|
|
|
382
|
|
|
/** |
|
383
|
|
|
* Lazy load function to get the database table of the student publications. |
|
384
|
|
|
*/ |
|
385
|
|
|
private function get_studpub_table() |
|
386
|
|
|
{ |
|
387
|
|
|
return $this->studpub_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION); |
|
388
|
|
|
} |
|
389
|
|
|
|
|
390
|
|
|
/** |
|
391
|
|
|
* Lazy load function to get the database table of the item properties. |
|
392
|
|
|
*/ |
|
393
|
|
|
private function get_itemprop_table() |
|
394
|
|
|
{ |
|
395
|
|
|
return $this->itemprop_table = Database::get_course_table(TABLE_ITEM_PROPERTY); |
|
396
|
|
|
} |
|
397
|
|
|
|
|
398
|
|
|
/** |
|
399
|
|
|
* @return array |
|
400
|
|
|
*/ |
|
401
|
|
|
private function get_exercise_data() |
|
402
|
|
|
{ |
|
403
|
|
|
$course_info = api_get_course_info($this->get_course_code()); |
|
404
|
|
|
if (!isset($this->exercise_data)) { |
|
405
|
|
|
$sql = 'SELECT * FROM '.$this->get_studpub_table()." |
|
406
|
|
|
WHERE |
|
407
|
|
|
c_id ='".$course_info['real_id']."' AND |
|
408
|
|
|
id = '".$this->get_ref_id()."' "; |
|
409
|
|
|
$query = Database::query($sql); |
|
410
|
|
|
$this->exercise_data = Database::fetch_array($query); |
|
|
|
|
|
|
411
|
|
|
|
|
412
|
|
|
// Try with iid |
|
413
|
|
|
if (empty($this->exercise_data)) { |
|
414
|
|
|
$sql = 'SELECT * FROM '.$this->get_studpub_table()." |
|
415
|
|
|
WHERE |
|
416
|
|
|
c_id ='".$course_info['real_id']."' AND |
|
417
|
|
|
iid = '".$this->get_ref_id()."' "; |
|
418
|
|
|
$query = Database::query($sql); |
|
419
|
|
|
$this->exercise_data = Database::fetch_array($query); |
|
420
|
|
|
} |
|
421
|
|
|
} |
|
422
|
|
|
|
|
423
|
|
|
return $this->exercise_data; |
|
424
|
|
|
} |
|
425
|
|
|
} |
|
426
|
|
|
|
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return,dieorexitstatements that have been added for debug purposes.In the above example, the last
return falsewill never be executed, because a return statement has already been met in every possible execution path.