Commit | Line | Data |
---|---|---|
4636bf83 | 1 | <?php |
2 | ||
3 | // This file is part of Moodle - http://moodle.org/ | |
4 | // | |
5 | // Moodle is free software: you can redistribute it and/or modify | |
6 | // it under the terms of the GNU General Public License as published by | |
7 | // the Free Software Foundation, either version 3 of the License, or | |
8 | // (at your option) any later version. | |
9 | // | |
10 | // Moodle is distributed in the hope that it will be useful, | |
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | // GNU General Public License for more details. | |
14 | // | |
15 | // You should have received a copy of the GNU General Public License | |
16 | // along with Moodle. If not, see <http://www.gnu.org/licenses/>. | |
3d4b223a | 17 | |
4636bf83 | 18 | /** |
750eb434 | 19 | * @package mod-data |
4636bf83 | 20 | * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} |
21 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
22 | */ | |
23 | ||
b8b554ac | 24 | // Some constants |
0997e51a | 25 | define ('DATA_MAX_ENTRIES', 50); |
26 | define ('DATA_PERPAGE_SINGLE', 1); | |
b572ce19 | 27 | |
714bec74 | 28 | define ('DATA_FIRSTNAME', -1); |
29 | define ('DATA_LASTNAME', -2); | |
bb5740f4 | 30 | define ('DATA_APPROVED', -3); |
3239b010 | 31 | define ('DATA_TIMEADDED', 0); |
32 | define ('DATA_TIMEMODIFIED', -4); | |
714bec74 | 33 | |
a7e35395 | 34 | define ('DATA_CAP_EXPORT', 'mod/data:viewalluserpresets'); |
8aff1574 SH |
35 | |
36 | define('DATA_PRESET_COMPONENT', 'mod_data'); | |
37 | define('DATA_PRESET_FILEAREA', 'site_presets'); | |
38 | define('DATA_PRESET_CONTEXT', SYSCONTEXTID); | |
39 | ||
a7e35395 | 40 | // Users having assigned the default role "Non-editing teacher" can export database records |
41 | // Using the mod/data capability "viewalluserpresets" existing in Moodle 1.9.x. | |
8429163d | 42 | // In Moodle >= 2, new roles may be introduced and used instead. |
a7e35395 | 43 | |
4636bf83 | 44 | /** |
750eb434 | 45 | * @package mod-data |
4636bf83 | 46 | * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} |
47 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
48 | */ | |
668fc89a | 49 | class data_field_base { // Base class for Database Field Types (see field/*/field.class.php) |
3d4b223a | 50 | |
4636bf83 | 51 | /** @var string Subclasses must override the type with their name */ |
52 | var $type = 'unknown'; | |
53 | /** @var object The database object that this field belongs to */ | |
54 | var $data = NULL; | |
55 | /** @var object The field object itself, if we know it */ | |
56c1ca88 | 56 | var $field = NULL; |
4636bf83 | 57 | /** @var int Width of the icon for this fieldtype */ |
58 | var $iconwidth = 16; | |
59 | /** @var int Width of the icon for this fieldtype */ | |
60 | var $iconheight = 16; | |
61 | /** @var object course module or cmifno */ | |
62 | var $cm; | |
63 | /** @var object activity context */ | |
64 | var $context; | |
65 | ||
66 | /** | |
67 | * Constructor function | |
68 | * | |
69 | * @global object | |
70 | * @uses CONTEXT_MODULE | |
71 | * @param int $field | |
72 | * @param int $data | |
73 | * @param int $cm | |
74 | */ | |
8429163d | 75 | function __construct($field=0, $data=0, $cm=0) { // Field or data or both, each can be id or object |
9c00b5d7 | 76 | global $DB; |
0997e51a | 77 | |
78 | if (empty($field) && empty($data)) { | |
29c1bb15 | 79 | print_error('missingfield', 'data'); |
0997e51a | 80 | } |
b572ce19 | 81 | |
0997e51a | 82 | if (!empty($field)) { |
83 | if (is_object($field)) { | |
84 | $this->field = $field; // Programmer knows what they are doing, we hope | |
9c00b5d7 | 85 | } else if (!$this->field = $DB->get_record('data_fields', array('id'=>$field))) { |
29c1bb15 | 86 | print_error('invalidfieldid', 'data'); |
0997e51a | 87 | } |
88 | if (empty($data)) { | |
9c00b5d7 | 89 | if (!$this->data = $DB->get_record('data', array('id'=>$this->field->dataid))) { |
29c1bb15 | 90 | print_error('invalidid', 'data'); |
0997e51a | 91 | } |
92 | } | |
93 | } | |
b572ce19 | 94 | |
0997e51a | 95 | if (empty($this->data)) { // We need to define this properly |
96 | if (!empty($data)) { | |
97 | if (is_object($data)) { | |
98 | $this->data = $data; // Programmer knows what they are doing, we hope | |
9c00b5d7 | 99 | } else if (!$this->data = $DB->get_record('data', array('id'=>$data))) { |
29c1bb15 | 100 | print_error('invalidid', 'data'); |
0997e51a | 101 | } |
102 | } else { // No way to define it! | |
29c1bb15 | 103 | print_error('missingdata', 'data'); |
0997e51a | 104 | } |
105 | } | |
b572ce19 | 106 | |
8429163d | 107 | if ($cm) { |
108 | $this->cm = $cm; | |
109 | } else { | |
110 | $this->cm = get_coursemodule_from_instance('data', $this->data->id); | |
111 | } | |
112 | ||
0997e51a | 113 | if (empty($this->field)) { // We need to define some default values |
114 | $this->define_default_field(); | |
115 | } | |
8429163d | 116 | |
117 | $this->context = get_context_instance(CONTEXT_MODULE, $this->cm->id); | |
3d4b223a | 118 | } |
0997e51a | 119 | |
6403e679 | 120 | |
4636bf83 | 121 | /** |
122 | * This field just sets up a default field object | |
123 | * | |
124 | * @return bool | |
125 | */ | |
0997e51a | 126 | function define_default_field() { |
4102b449 | 127 | global $OUTPUT; |
0997e51a | 128 | if (empty($this->data->id)) { |
4102b449 | 129 | echo $OUTPUT->notification('Programmer error: dataid not defined in field class'); |
0997e51a | 130 | } |
39790bd8 | 131 | $this->field = new stdClass(); |
0997e51a | 132 | $this->field->id = 0; |
133 | $this->field->dataid = $this->data->id; | |
134 | $this->field->type = $this->type; | |
135 | $this->field->param1 = ''; | |
136 | $this->field->param2 = ''; | |
137 | $this->field->param3 = ''; | |
138 | $this->field->name = ''; | |
139 | $this->field->description = ''; | |
b572ce19 | 140 | |
0997e51a | 141 | return true; |
3d4b223a | 142 | } |
0997e51a | 143 | |
4636bf83 | 144 | /** |
145 | * Set up the field object according to data in an object. Now is the time to clean it! | |
146 | * | |
147 | * @return bool | |
148 | */ | |
0997e51a | 149 | function define_field($data) { |
150 | $this->field->type = $this->type; | |
151 | $this->field->dataid = $this->data->id; | |
152 | ||
153 | $this->field->name = trim($data->name); | |
154 | $this->field->description = trim($data->description); | |
155 | ||
156 | if (isset($data->param1)) { | |
157 | $this->field->param1 = trim($data->param1); | |
158 | } | |
159 | if (isset($data->param2)) { | |
8921fdb7 | 160 | $this->field->param2 = trim($data->param2); |
0997e51a | 161 | } |
162 | if (isset($data->param3)) { | |
163 | $this->field->param3 = trim($data->param3); | |
164 | } | |
165 | if (isset($data->param4)) { | |
166 | $this->field->param4 = trim($data->param4); | |
167 | } | |
168 | if (isset($data->param5)) { | |
169 | $this->field->param5 = trim($data->param5); | |
170 | } | |
171 | ||
172 | return true; | |
3d4b223a | 173 | } |
6403e679 | 174 | |
4636bf83 | 175 | /** |
176 | * Insert a new field in the database | |
177 | * We assume the field object is already defined as $this->field | |
178 | * | |
179 | * @global object | |
180 | * @return bool | |
181 | */ | |
0997e51a | 182 | function insert_field() { |
4102b449 | 183 | global $DB, $OUTPUT; |
9c00b5d7 | 184 | |
0997e51a | 185 | if (empty($this->field)) { |
4102b449 | 186 | echo $OUTPUT->notification('Programmer error: Field has not been defined yet! See define_field()'); |
0997e51a | 187 | return false; |
188 | } | |
189 | ||
a8f3a651 | 190 | $this->field->id = $DB->insert_record('data_fields',$this->field); |
0997e51a | 191 | return true; |
3d4b223a | 192 | } |
193 | ||
0997e51a | 194 | |
4636bf83 | 195 | /** |
196 | * Update a field in the database | |
197 | * | |
198 | * @global object | |
199 | * @return bool | |
200 | */ | |
0997e51a | 201 | function update_field() { |
9c00b5d7 | 202 | global $DB; |
203 | ||
9d749339 | 204 | $DB->update_record('data_fields', $this->field); |
0997e51a | 205 | return true; |
206 | } | |
3d4b223a | 207 | |
4636bf83 | 208 | /** |
209 | * Delete a field completely | |
210 | * | |
211 | * @global object | |
212 | * @return bool | |
213 | */ | |
0997e51a | 214 | function delete_field() { |
9c00b5d7 | 215 | global $DB; |
216 | ||
0997e51a | 217 | if (!empty($this->field->id)) { |
0997e51a | 218 | $this->delete_content(); |
8429163d | 219 | $DB->delete_records('data_fields', array('id'=>$this->field->id)); |
3d4b223a | 220 | } |
0997e51a | 221 | return true; |
222 | } | |
223 | ||
4636bf83 | 224 | /** |
225 | * Print the relevant form element in the ADD template for this field | |
226 | * | |
227 | * @global object | |
228 | * @param int $recordid | |
229 | * @return string | |
230 | */ | |
0997e51a | 231 | function display_add_field($recordid=0){ |
9c00b5d7 | 232 | global $DB; |
233 | ||
0997e51a | 234 | if ($recordid){ |
9c00b5d7 | 235 | $content = $DB->get_field('data_content', 'content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid)); |
0997e51a | 236 | } else { |
3d4b223a | 237 | $content = ''; |
238 | } | |
6403e679 | 239 | |
344e15e6 | 240 | // beware get_field returns false for new, empty records MDL-18567 |
241 | if ($content===false) { | |
242 | $content=''; | |
243 | } | |
244 | ||
9706fa56 | 245 | $str = '<div title="'.s($this->field->description).'">'; |
0997e51a | 246 | $str .= '<input style="width:300px;" type="text" name="field_'.$this->field->id.'" id="field_'.$this->field->id.'" value="'.s($content).'" />'; |
bbe39b6c | 247 | $str .= '</div>'; |
0997e51a | 248 | |
3d4b223a | 249 | return $str; |
250 | } | |
251 | ||
4636bf83 | 252 | /** |
253 | * Print the relevant form element to define the attributes for this field | |
254 | * viewable by teachers only. | |
255 | * | |
256 | * @global object | |
257 | * @global object | |
258 | * @return void Output is echo'd | |
259 | */ | |
0997e51a | 260 | function display_edit_field() { |
b2dc6880 | 261 | global $CFG, $DB, $OUTPUT; |
0997e51a | 262 | |
263 | if (empty($this->field)) { // No field has been defined yet, try and make one | |
264 | $this->define_default_field(); | |
3d4b223a | 265 | } |
4102b449 | 266 | echo $OUTPUT->box_start('generalbox boxaligncenter boxwidthwide'); |
0997e51a | 267 | |
b7dc2256 | 268 | echo '<form id="editfield" action="'.$CFG->wwwroot.'/mod/data/field.php" method="post">'."\n"; |
0997e51a | 269 | echo '<input type="hidden" name="d" value="'.$this->data->id.'" />'."\n"; |
270 | if (empty($this->field->id)) { | |
271 | echo '<input type="hidden" name="mode" value="add" />'."\n"; | |
272 | $savebutton = get_string('add'); | |
273 | } else { | |
274 | echo '<input type="hidden" name="fid" value="'.$this->field->id.'" />'."\n"; | |
275 | echo '<input type="hidden" name="mode" value="update" />'."\n"; | |
276 | $savebutton = get_string('savechanges'); | |
277 | } | |
278 | echo '<input type="hidden" name="type" value="'.$this->type.'" />'."\n"; | |
279 | echo '<input name="sesskey" value="'.sesskey().'" type="hidden" />'."\n"; | |
6403e679 | 280 | |
b2dc6880 | 281 | echo $OUTPUT->heading($this->name()); |
0997e51a | 282 | |
3d4b223a | 283 | require_once($CFG->dirroot.'/mod/data/field/'.$this->type.'/mod.html'); |
0997e51a | 284 | |
85db96c5 | 285 | echo '<div class="mdl-align">'; |
0997e51a | 286 | echo '<input type="submit" value="'.$savebutton.'" />'."\n"; |
ec865e2d | 287 | echo '<input type="submit" name="cancel" value="'.get_string('cancel').'" />'."\n"; |
e357c206 | 288 | echo '</div>'; |
0997e51a | 289 | |
290 | echo '</form>'; | |
291 | ||
4102b449 | 292 | echo $OUTPUT->box_end(); |
3d4b223a | 293 | } |
6403e679 | 294 | |
4636bf83 | 295 | /** |
296 | * Display the content of the field in browse mode | |
297 | * | |
298 | * @global object | |
299 | * @param int $recordid | |
300 | * @param object $template | |
301 | * @return bool|string | |
302 | */ | |
0997e51a | 303 | function display_browse_field($recordid, $template) { |
9c00b5d7 | 304 | global $DB; |
305 | ||
306 | if ($content = $DB->get_record('data_content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid))) { | |
6403e679 | 307 | if (isset($content->content)) { |
39790bd8 | 308 | $options = new stdClass(); |
c8505cac | 309 | if ($this->field->param1 == '1') { // We are autolinking this field, so disable linking within us |
310 | //$content->content = '<span class="nolink">'.$content->content.'</span>'; | |
311 | //$content->content1 = FORMAT_HTML; | |
312 | $options->filter=false; | |
313 | } | |
1f697b99 | 314 | $options->para = false; |
315 | $str = format_text($content->content, $content->content1, $options); | |
3d4b223a | 316 | } else { |
317 | $str = ''; | |
318 | } | |
319 | return $str; | |
320 | } | |
321 | return false; | |
322 | } | |
6403e679 | 323 | |
4636bf83 | 324 | /** |
325 | * Update the content of one data field in the data_content table | |
326 | * @global object | |
327 | * @param int $recordid | |
328 | * @param mixed $value | |
329 | * @param string $name | |
330 | * @return bool | |
331 | */ | |
0997e51a | 332 | function update_content($recordid, $value, $name=''){ |
9c00b5d7 | 333 | global $DB; |
334 | ||
39790bd8 | 335 | $content = new stdClass(); |
0997e51a | 336 | $content->fieldid = $this->field->id; |
c87fbb27 | 337 | $content->recordid = $recordid; |
338 | $content->content = clean_param($value, PARAM_NOTAGS); | |
0997e51a | 339 | |
9c00b5d7 | 340 | if ($oldcontent = $DB->get_record('data_content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid))) { |
3d4b223a | 341 | $content->id = $oldcontent->id; |
9c00b5d7 | 342 | return $DB->update_record('data_content', $content); |
0997e51a | 343 | } else { |
9c00b5d7 | 344 | return $DB->insert_record('data_content', $content); |
3d4b223a | 345 | } |
0997e51a | 346 | } |
6403e679 | 347 | |
4636bf83 | 348 | /** |
349 | * Delete all content associated with the field | |
350 | * | |
351 | * @global object | |
352 | * @param int $recordid | |
353 | * @return bool | |
354 | */ | |
0997e51a | 355 | function delete_content($recordid=0) { |
9c00b5d7 | 356 | global $DB; |
0997e51a | 357 | |
0997e51a | 358 | if ($recordid) { |
8429163d | 359 | $conditions = array('fieldid'=>$this->field->id, 'recordid'=>$recordid); |
0997e51a | 360 | } else { |
8429163d | 361 | $conditions = array('fieldid'=>$this->field->id); |
3d4b223a | 362 | } |
0997e51a | 363 | |
6b1b1d03 EL |
364 | $rs = $DB->get_recordset('data_content', $conditions); |
365 | if ($rs->valid()) { | |
8429163d | 366 | $fs = get_file_storage(); |
367 | foreach ($rs as $content) { | |
64f93798 | 368 | $fs->delete_area_files($this->context->id, 'mod_data', 'content', $content->id); |
8429163d | 369 | } |
0997e51a | 370 | } |
6b1b1d03 | 371 | $rs->close(); |
0997e51a | 372 | |
8429163d | 373 | return $DB->delete_records('data_content', $conditions); |
0997e51a | 374 | } |
6403e679 | 375 | |
4636bf83 | 376 | /** |
377 | * Check if a field from an add form is empty | |
378 | * | |
379 | * @param mixed $value | |
380 | * @param mixed $name | |
381 | * @return bool | |
382 | */ | |
f9eab7b0 | 383 | function notemptyfield($value, $name) { |
3d4b223a | 384 | return !empty($value); |
385 | } | |
6403e679 | 386 | |
4636bf83 | 387 | /** |
388 | * Just in case a field needs to print something before the whole form | |
389 | */ | |
0997e51a | 390 | function print_before_form() { |
3d4b223a | 391 | } |
0997e51a | 392 | |
4636bf83 | 393 | /** |
394 | * Just in case a field needs to print something after the whole form | |
395 | */ | |
5f5bcda8 | 396 | function print_after_form() { |
5f5bcda8 | 397 | } |
6403e679 | 398 | |
399 | ||
4636bf83 | 400 | /** |
401 | * Returns the sortable field for the content. By default, it's just content | |
402 | * but for some plugins, it could be content 1 - content4 | |
403 | * | |
404 | * @return string | |
405 | */ | |
cf3e199b | 406 | function get_sort_field() { |
407 | return 'content'; | |
408 | } | |
0997e51a | 409 | |
4636bf83 | 410 | /** |
411 | * Returns the SQL needed to refer to the column. Some fields may need to CAST() etc. | |
412 | * | |
413 | * @param string $fieldname | |
414 | * @return string $fieldname | |
415 | */ | |
64452eb4 | 416 | function get_sort_sql($fieldname) { |
417 | return $fieldname; | |
418 | } | |
419 | ||
4636bf83 | 420 | /** |
421 | * Returns the name/type of the field | |
422 | * | |
423 | * @return string | |
424 | */ | |
b8b554ac | 425 | function name() { |
0997e51a | 426 | return get_string('name'.$this->type, 'data'); |
427 | } | |
6403e679 | 428 | |
4636bf83 | 429 | /** |
430 | * Prints the respective type icon | |
431 | * | |
432 | * @global object | |
433 | * @return string | |
434 | */ | |
0997e51a | 435 | function image() { |
5ef44400 | 436 | global $OUTPUT; |
0997e51a | 437 | |
a7d4cb67 DC |
438 | $params = array('d'=>$this->data->id, 'fid'=>$this->field->id, 'mode'=>'display', 'sesskey'=>sesskey()); |
439 | $link = new moodle_url('/mod/data/field.php', $params); | |
440 | $str = '<a href="'.$link->out().'">'; | |
441 | $str .= '<img src="'.$OUTPUT->pix_url('field/'.$this->type, 'data') . '" '; | |
051aad68 | 442 | $str .= 'height="'.$this->iconheight.'" width="'.$this->iconwidth.'" alt="'.$this->type.'" title="'.$this->type.'" /></a>'; |
0997e51a | 443 | return $str; |
444 | } | |
445 | ||
4636bf83 | 446 | /** |
447 | * Per default, it is assumed that fields support text exporting. | |
448 | * Override this (return false) on fields not supporting text exporting. | |
449 | * | |
450 | * @return bool true | |
451 | */ | |
b8b554ac | 452 | function text_export_supported() { |
453 | return true; | |
454 | } | |
6403e679 | 455 | |
4636bf83 | 456 | /** |
457 | * Per default, return the record's text value only from the "content" field. | |
458 | * Override this in fields class if necesarry. | |
459 | * | |
460 | * @param string $record | |
461 | * @return string | |
462 | */ | |
b8b554ac | 463 | function export_text_value($record) { |
464 | if ($this->text_export_supported()) { | |
465 | return $record->content; | |
466 | } | |
467 | } | |
0997e51a | 468 | |
4636bf83 | 469 | /** |
470 | * @param string $relativepath | |
471 | * @return bool false | |
472 | */ | |
8429163d | 473 | function file_ok($relativepath) { |
474 | return false; | |
475 | } | |
b8b554ac | 476 | } |
3d4b223a | 477 | |
478 | ||
4636bf83 | 479 | /** |
480 | * Given a template and a dataid, generate a default case template | |
481 | * | |
482 | * @global object | |
483 | * @param object $data | |
484 | * @param string template [addtemplate, singletemplate, listtempalte, rsstemplate] | |
485 | * @param int $recordid | |
486 | * @param bool $form | |
487 | * @param bool $update | |
488 | * @return bool|string | |
489 | */ | |
a44e7081 | 490 | function data_generate_default_template(&$data, $template, $recordid=0, $form=false, $update=true) { |
9c00b5d7 | 491 | global $DB; |
d118d06a | 492 | |
edaa546a | 493 | if (!$data && !$template) { |
3d4b223a | 494 | return false; |
495 | } | |
5cd07964 | 496 | if ($template == 'csstemplate' or $template == 'jstemplate' ) { |
f24eb261 | 497 | return ''; |
498 | } | |
6403e679 | 499 | |
b8b554ac | 500 | // get all the fields for that database |
9c00b5d7 | 501 | if ($fields = $DB->get_records('data_fields', array('dataid'=>$data->id), 'id')) { |
6403e679 | 502 | |
b41fc49c NK |
503 | $table = new html_table(); |
504 | $table->attributes['class'] = 'mod-data-default-template'; | |
505 | $table->colclasses = array('template-field', 'template-token'); | |
506 | $table->data = array(); | |
f41cadeb | 507 | foreach ($fields as $field) { |
b8b554ac | 508 | if ($form) { // Print forms instead of data |
d118d06a | 509 | $fieldobj = data_get_field($field, $data); |
b41fc49c | 510 | $token = $fieldobj->display_add_field($recordid); |
b8b554ac | 511 | } else { // Just print the tag |
b41fc49c | 512 | $token = '[['.$field->name.']]'; |
d118d06a | 513 | } |
b41fc49c NK |
514 | $table->data[] = array( |
515 | $field->name.': ', | |
516 | $token | |
517 | ); | |
3d4b223a | 518 | } |
bb828644 | 519 | if ($template == 'listtemplate') { |
b41fc49c NK |
520 | $cell = new html_table_cell('##edit## ##more## ##delete## ##approve## ##export##'); |
521 | $cell->colspan = 2; | |
522 | $cell->attributes['class'] = 'controls'; | |
523 | $table->data[] = new html_table_row(array($cell)); | |
bb828644 | 524 | } else if ($template == 'singletemplate') { |
b41fc49c NK |
525 | $cell = new html_table_cell('##edit## ##delete## ##approve## ##export##'); |
526 | $cell->colspan = 2; | |
527 | $cell->attributes['class'] = 'controls'; | |
528 | $table->data[] = new html_table_row(array($cell)); | |
714bec74 | 529 | } else if ($template == 'asearchtemplate') { |
2b04c41c | 530 | $row = new html_table_row(array(get_string('authorfirstname', 'data').': ', '##firstname##')); |
b41fc49c NK |
531 | $row->attributes['class'] = 'searchcontrols'; |
532 | $table->data[] = $row; | |
2b04c41c | 533 | $row = new html_table_row(array(get_string('authorlastname', 'data').': ', '##lastname##')); |
b41fc49c NK |
534 | $row->attributes['class'] = 'searchcontrols'; |
535 | $table->data[] = $row; | |
3d4b223a | 536 | } |
537 | ||
b41fc49c NK |
538 | $str = html_writer::start_tag('div', array('class' => 'defaulttemplate')); |
539 | $str .= html_writer::table($table); | |
540 | $str .= html_writer::end_tag('div'); | |
d118d06a | 541 | if ($template == 'listtemplate'){ |
b41fc49c | 542 | $str .= html_writer::empty_tag('hr'); |
3d4b223a | 543 | } |
f9eab7b0 | 544 | |
d118d06a | 545 | if ($update) { |
39790bd8 | 546 | $newdata = new stdClass(); |
d118d06a | 547 | $newdata->id = $data->id; |
f41cadeb | 548 | $newdata->{$template} = $str; |
9d749339 | 549 | $DB->update_record('data', $newdata); |
550 | $data->{$template} = $str; | |
3d4b223a | 551 | } |
d118d06a | 552 | |
553 | return $str; | |
3d4b223a | 554 | } |
555 | } | |
556 | ||
557 | ||
4636bf83 | 558 | /** |
56c1ca88 | 559 | * Search for a field name and replaces it with another one in all the |
560 | * form templates. Set $newfieldname as '' if you want to delete the | |
4636bf83 | 561 | * field from the form. |
562 | * | |
563 | * @global object | |
564 | * @param object $data | |
565 | * @param string $searchfieldname | |
566 | * @param string $newfieldname | |
567 | * @return bool | |
568 | */ | |
0997e51a | 569 | function data_replace_field_in_templates($data, $searchfieldname, $newfieldname) { |
9c00b5d7 | 570 | global $DB; |
571 | ||
f9eab7b0 | 572 | if (!empty($newfieldname)) { |
573 | $prestring = '[['; | |
574 | $poststring = ']]'; | |
9706fa56 | 575 | $idpart = '#id'; |
735a7952 | 576 | |
577 | } else { | |
f9eab7b0 | 578 | $prestring = ''; |
579 | $poststring = ''; | |
9706fa56 | 580 | $idpart = ''; |
f9eab7b0 | 581 | } |
6403e679 | 582 | |
39790bd8 | 583 | $newdata = new stdClass(); |
735a7952 | 584 | $newdata->id = $data->id; |
9c00b5d7 | 585 | $newdata->singletemplate = str_ireplace('[['.$searchfieldname.']]', |
586 | $prestring.$newfieldname.$poststring, $data->singletemplate); | |
6403e679 | 587 | |
9c00b5d7 | 588 | $newdata->listtemplate = str_ireplace('[['.$searchfieldname.']]', |
589 | $prestring.$newfieldname.$poststring, $data->listtemplate); | |
6403e679 | 590 | |
9c00b5d7 | 591 | $newdata->addtemplate = str_ireplace('[['.$searchfieldname.']]', |
592 | $prestring.$newfieldname.$poststring, $data->addtemplate); | |
6403e679 | 593 | |
9c00b5d7 | 594 | $newdata->addtemplate = str_ireplace('[['.$searchfieldname.'#id]]', |
595 | $prestring.$newfieldname.$idpart.$poststring, $data->addtemplate); | |
9706fa56 | 596 | |
9c00b5d7 | 597 | $newdata->rsstemplate = str_ireplace('[['.$searchfieldname.']]', |
598 | $prestring.$newfieldname.$poststring, $data->rsstemplate); | |
6403e679 | 599 | |
9c00b5d7 | 600 | return $DB->update_record('data', $newdata); |
f9eab7b0 | 601 | } |
602 | ||
603 | ||
4636bf83 | 604 | /** |
605 | * Appends a new field at the end of the form template. | |
606 | * | |
607 | * @global object | |
608 | * @param object $data | |
609 | * @param string $newfieldname | |
610 | */ | |
0997e51a | 611 | function data_append_new_field_to_templates($data, $newfieldname) { |
9c00b5d7 | 612 | global $DB; |
0997e51a | 613 | |
39790bd8 | 614 | $newdata = new stdClass(); |
0997e51a | 615 | $newdata->id = $data->id; |
ed69c723 | 616 | $change = false; |
0997e51a | 617 | |
f9eab7b0 | 618 | if (!empty($data->singletemplate)) { |
9c00b5d7 | 619 | $newdata->singletemplate = $data->singletemplate.' [[' . $newfieldname .']]'; |
ed69c723 | 620 | $change = true; |
0997e51a | 621 | } |
622 | if (!empty($data->addtemplate)) { | |
9c00b5d7 | 623 | $newdata->addtemplate = $data->addtemplate.' [[' . $newfieldname . ']]'; |
ed69c723 | 624 | $change = true; |
f9eab7b0 | 625 | } |
626 | if (!empty($data->rsstemplate)) { | |
9c00b5d7 | 627 | $newdata->rsstemplate = $data->singletemplate.' [[' . $newfieldname . ']]'; |
ed69c723 | 628 | $change = true; |
629 | } | |
630 | if ($change) { | |
9c00b5d7 | 631 | $DB->update_record('data', $newdata); |
f9eab7b0 | 632 | } |
f9eab7b0 | 633 | } |
634 | ||
635 | ||
4636bf83 | 636 | /** |
637 | * given a field name | |
638 | * this function creates an instance of the particular subfield class | |
639 | * | |
640 | * @global object | |
641 | * @param string $name | |
642 | * @param object $data | |
643 | * @return object|bool | |
644 | */ | |
0997e51a | 645 | function data_get_field_from_name($name, $data){ |
9c00b5d7 | 646 | global $DB; |
647 | ||
1e123f47 | 648 | $field = $DB->get_record('data_fields', array('name'=>$name, 'dataid'=>$data->id)); |
0997e51a | 649 | |
650 | if ($field) { | |
651 | return data_get_field($field, $data); | |
652 | } else { | |
653 | return false; | |
654 | } | |
655 | } | |
656 | ||
4636bf83 | 657 | /** |
658 | * given a field id | |
659 | * this function creates an instance of the particular subfield class | |
660 | * | |
661 | * @global object | |
662 | * @param int $fieldid | |
663 | * @param object $data | |
664 | * @return bool|object | |
665 | */ | |
0997e51a | 666 | function data_get_field_from_id($fieldid, $data){ |
9c00b5d7 | 667 | global $DB; |
668 | ||
1e123f47 | 669 | $field = $DB->get_record('data_fields', array('id'=>$fieldid, 'dataid'=>$data->id)); |
3d4b223a | 670 | |
0997e51a | 671 | if ($field) { |
672 | return data_get_field($field, $data); | |
5782be6b | 673 | } else { |
d6f0e247 | 674 | return false; |
3d4b223a | 675 | } |
3d4b223a | 676 | } |
677 | ||
4636bf83 | 678 | /** |
679 | * given a field id | |
680 | * this function creates an instance of the particular subfield class | |
681 | * | |
682 | * @global object | |
683 | * @param string $type | |
684 | * @param object $data | |
685 | * @return object | |
686 | */ | |
0997e51a | 687 | function data_get_field_new($type, $data) { |
688 | global $CFG; | |
b572ce19 | 689 | |
0997e51a | 690 | require_once($CFG->dirroot.'/mod/data/field/'.$type.'/field.class.php'); |
691 | $newfield = 'data_field_'.$type; | |
692 | $newfield = new $newfield(0, $data); | |
693 | return $newfield; | |
694 | } | |
695 | ||
4636bf83 | 696 | /** |
697 | * returns a subclass field object given a record of the field, used to | |
698 | * invoke plugin methods | |
699 | * input: $param $field - record from db | |
700 | * | |
701 | * @global object | |
702 | * @param object $field | |
703 | * @param object $data | |
704 | * @param object $cm | |
705 | * @return object | |
706 | */ | |
8429163d | 707 | function data_get_field($field, $data, $cm=null) { |
0997e51a | 708 | global $CFG; |
b572ce19 | 709 | |
0997e51a | 710 | if ($field) { |
3d4b223a | 711 | require_once('field/'.$field->type.'/field.class.php'); |
712 | $newfield = 'data_field_'.$field->type; | |
8429163d | 713 | $newfield = new $newfield($field, $data, $cm); |
3d4b223a | 714 | return $newfield; |
715 | } | |
716 | } | |
717 | ||
718 | ||
8429163d | 719 | /** |
720 | * Given record object (or id), returns true if the record belongs to the current user | |
4636bf83 | 721 | * |
722 | * @global object | |
723 | * @global object | |
724 | * @param mixed $record record object or id | |
8429163d | 725 | * @return bool |
726 | */ | |
727 | function data_isowner($record) { | |
9c00b5d7 | 728 | global $USER, $DB; |
3d4b223a | 729 | |
4f0c2d00 | 730 | if (!isloggedin()) { // perf shortcut |
3d4b223a | 731 | return false; |
732 | } | |
733 | ||
8429163d | 734 | if (!is_object($record)) { |
735 | if (!$record = $DB->get_record('data_records', array('id'=>$record))) { | |
736 | return false; | |
737 | } | |
3d4b223a | 738 | } |
739 | ||
8429163d | 740 | return ($record->userid == $USER->id); |
3d4b223a | 741 | } |
742 | ||
4636bf83 | 743 | /** |
744 | * has a user reached the max number of entries? | |
745 | * | |
746 | * @param object $data | |
747 | * @return bool | |
748 | */ | |
b572ce19 | 749 | function data_atmaxentries($data){ |
750 | if (!$data->maxentries){ | |
3d4b223a | 751 | return false; |
b572ce19 | 752 | |
3d4b223a | 753 | } else { |
754 | return (data_numentries($data) >= $data->maxentries); | |
755 | } | |
756 | } | |
757 | ||
4636bf83 | 758 | /** |
759 | * returns the number of entries already made by this user | |
56c1ca88 | 760 | * |
4636bf83 | 761 | * @global object |
762 | * @global object | |
56c1ca88 | 763 | * @param object $data |
4636bf83 | 764 | * @return int |
765 | */ | |
3d4b223a | 766 | function data_numentries($data){ |
8429163d | 767 | global $USER, $DB; |
9c00b5d7 | 768 | $sql = 'SELECT COUNT(*) FROM {data_records} WHERE dataid=? AND userid=?'; |
769 | return $DB->count_records_sql($sql, array($data->id, $USER->id)); | |
3d4b223a | 770 | } |
771 | ||
4636bf83 | 772 | /** |
56c1ca88 | 773 | * function that takes in a dataid and adds a record |
4636bf83 | 774 | * this is used everytime an add template is submitted |
775 | * | |
776 | * @global object | |
777 | * @global object | |
778 | * @param object $data | |
779 | * @param int $groupid | |
780 | * @return bool | |
781 | */ | |
0997e51a | 782 | function data_add_record($data, $groupid=0){ |
9c00b5d7 | 783 | global $USER, $DB; |
6403e679 | 784 | |
c088d603 | 785 | $cm = get_coursemodule_from_instance('data', $data->id); |
bbbf2d40 | 786 | $context = get_context_instance(CONTEXT_MODULE, $cm->id); |
b572ce19 | 787 | |
39790bd8 | 788 | $record = new stdClass(); |
3d4b223a | 789 | $record->userid = $USER->id; |
0997e51a | 790 | $record->dataid = $data->id; |
3d4b223a | 791 | $record->groupid = $groupid; |
0997e51a | 792 | $record->timecreated = $record->timemodified = time(); |
0468976c | 793 | if (has_capability('mod/data:approve', $context)) { |
6e0119dd | 794 | $record->approved = 1; |
795 | } else { | |
796 | $record->approved = 0; | |
797 | } | |
9c00b5d7 | 798 | return $DB->insert_record('data_records', $record); |
3d4b223a | 799 | } |
800 | ||
4636bf83 | 801 | /** |
802 | * check the multple existence any tag in a template | |
803 | * | |
804 | * check to see if there are 2 or more of the same tag being used. | |
805 | * | |
806 | * @global object | |
807 | * @param int $dataid, | |
56c1ca88 | 808 | * @param string $template |
4636bf83 | 809 | * @return bool |
810 | */ | |
9c00b5d7 | 811 | function data_tags_check($dataid, $template) { |
4102b449 | 812 | global $DB, $OUTPUT; |
9c00b5d7 | 813 | |
b8b554ac | 814 | // first get all the possible tags |
9c00b5d7 | 815 | $fields = $DB->get_records('data_fields', array('dataid'=>$dataid)); |
b8b554ac | 816 | // then we generate strings to replace |
817 | $tagsok = true; // let's be optimistic | |
b572ce19 | 818 | foreach ($fields as $field){ |
d118d06a | 819 | $pattern="/\[\[".$field->name."\]\]/i"; |
b572ce19 | 820 | if (preg_match_all($pattern, $template, $dummy)>1){ |
3d4b223a | 821 | $tagsok = false; |
4102b449 | 822 | echo $OUTPUT->notification('[['.$field->name.']] - '.get_string('multipletags','data')); |
3d4b223a | 823 | } |
824 | } | |
b8b554ac | 825 | // else return true |
3d4b223a | 826 | return $tagsok; |
827 | } | |
828 | ||
4636bf83 | 829 | /** |
830 | * Adds an instance of a data | |
831 | * | |
832 | * @global object | |
833 | * @param object $data | |
834 | * @return $int | |
835 | */ | |
3d4b223a | 836 | function data_add_instance($data) { |
8429163d | 837 | global $DB; |
3d4b223a | 838 | |
57244db3 | 839 | if (empty($data->assessed)) { |
840 | $data->assessed = 0; | |
d6af3cfa | 841 | } |
842 | ||
3d4b223a | 843 | $data->timemodified = time(); |
844 | ||
a8f3a651 | 845 | $data->id = $DB->insert_record('data', $data); |
3d4b223a | 846 | |
612607bd | 847 | data_grade_item_update($data); |
b572ce19 | 848 | |
3d4b223a | 849 | return $data->id; |
850 | } | |
851 | ||
4636bf83 | 852 | /** |
853 | * updates an instance of a data | |
854 | * | |
855 | * @global object | |
856 | * @param object $data | |
857 | * @return bool | |
858 | */ | |
3d4b223a | 859 | function data_update_instance($data) { |
4102b449 | 860 | global $DB, $OUTPUT; |
6403e679 | 861 | |
04366d79 | 862 | $data->timemodified = time(); |
b572ce19 | 863 | $data->id = $data->instance; |
6403e679 | 864 | |
57244db3 | 865 | if (empty($data->assessed)) { |
866 | $data->assessed = 0; | |
17e5f3fc | 867 | } |
b572ce19 | 868 | |
d251b259 AD |
869 | if (empty($data->ratingtime) or empty($data->assessed)) { |
870 | $data->assesstimestart = 0; | |
871 | $data->assesstimefinish = 0; | |
872 | } | |
873 | ||
05ac14ca | 874 | if (empty($data->notification)) { |
875 | $data->notification = 0; | |
876 | } | |
877 | ||
0bcf8b6f | 878 | $DB->update_record('data', $data); |
04366d79 | 879 | |
04366d79 | 880 | data_grade_item_update($data); |
b572ce19 | 881 | |
04366d79 | 882 | return true; |
b572ce19 | 883 | |
3d4b223a | 884 | } |
885 | ||
4636bf83 | 886 | /** |
887 | * deletes an instance of a data | |
888 | * | |
889 | * @global object | |
890 | * @param int $id | |
891 | * @return bool | |
892 | */ | |
b8b554ac | 893 | function data_delete_instance($id) { // takes the dataid |
650a0c0a | 894 | global $DB, $CFG; |
3d4b223a | 895 | |
8429163d | 896 | if (!$data = $DB->get_record('data', array('id'=>$id))) { |
3d4b223a | 897 | return false; |
898 | } | |
899 | ||
8429163d | 900 | $cm = get_coursemodule_from_instance('data', $data->id); |
901 | $context = get_context_instance(CONTEXT_MODULE, $cm->id); | |
b572ce19 | 902 | |
8429163d | 903 | /// Delete all the associated information |
6403e679 | 904 | |
8429163d | 905 | // files |
906 | $fs = get_file_storage(); | |
64f93798 | 907 | $fs->delete_area_files($context->id, 'mod_data'); |
3d4b223a | 908 | |
8429163d | 909 | // get all the records in this data |
910 | $sql = "SELECT r.id | |
911 | FROM {data_records} r | |
912 | WHERE r.dataid = ?"; | |
6403e679 | 913 | |
8429163d | 914 | $DB->delete_records_select('data_content', "recordid IN ($sql)", array($id)); |
3d4b223a | 915 | |
916 | // delete all the records and fields | |
c18269c7 | 917 | $DB->delete_records('data_records', array('dataid'=>$id)); |
918 | $DB->delete_records('data_fields', array('dataid'=>$id)); | |
3d4b223a | 919 | |
920 | // Delete the instance itself | |
c18269c7 | 921 | $result = $DB->delete_records('data', array('id'=>$id)); |
04366d79 | 922 | |
8429163d | 923 | // cleanup gradebook |
b82cacea | 924 | data_grade_item_delete($data); |
b572ce19 | 925 | |
04366d79 | 926 | return $result; |
3d4b223a | 927 | } |
928 | ||
4636bf83 | 929 | /** |
930 | * returns a summary of data activity of this user | |
931 | * | |
932 | * @global object | |
933 | * @param object $course | |
934 | * @param object $user | |
935 | * @param object $mod | |
936 | * @param object $data | |
937 | * @return object|null | |
938 | */ | |
3d4b223a | 939 | function data_user_outline($course, $user, $mod, $data) { |
1a96363a NC |
940 | global $DB, $CFG; |
941 | require_once("$CFG->libdir/gradelib.php"); | |
942 | ||
943 | $grades = grade_get_grades($course->id, 'mod', 'data', $data->id, $user->id); | |
944 | if (empty($grades->items[0]->grades)) { | |
945 | $grade = false; | |
946 | } else { | |
947 | $grade = reset($grades->items[0]->grades); | |
948 | } | |
949 | ||
9c00b5d7 | 950 | |
951 | if ($countrecords = $DB->count_records('data_records', array('dataid'=>$data->id, 'userid'=>$user->id))) { | |
39790bd8 | 952 | $result = new stdClass(); |
63701c78 | 953 | $result->info = get_string('numrecords', 'data', $countrecords); |
9c00b5d7 | 954 | $lastrecord = $DB->get_record_sql('SELECT id,timemodified FROM {data_records} |
955 | WHERE dataid = ? AND userid = ? | |
956 | ORDER BY timemodified DESC', array($data->id, $user->id), true); | |
3d4b223a | 957 | $result->time = $lastrecord->timemodified; |
1a96363a NC |
958 | if ($grade) { |
959 | $result->info .= ', ' . get_string('grade') . ': ' . $grade->str_long_grade; | |
960 | } | |
961 | return $result; | |
962 | } else if ($grade) { | |
39790bd8 | 963 | $result = new stdClass(); |
1a96363a | 964 | $result->info = get_string('grade') . ': ' . $grade->str_long_grade; |
4433f871 AD |
965 | |
966 | //datesubmitted == time created. dategraded == time modified or time overridden | |
967 | //if grade was last modified by the user themselves use date graded. Otherwise use date submitted | |
94a74f54 | 968 | //TODO: move this copied & pasted code somewhere in the grades API. See MDL-26704 |
4433f871 AD |
969 | if ($grade->usermodified == $user->id || empty($grade->datesubmitted)) { |
970 | $result->time = $grade->dategraded; | |
971 | } else { | |
972 | $result->time = $grade->datesubmitted; | |
973 | } | |
974 | ||
3d4b223a | 975 | return $result; |
976 | } | |
977 | return NULL; | |
3d4b223a | 978 | } |
979 | ||
4636bf83 | 980 | /** |
981 | * Prints all the records uploaded by this user | |
982 | * | |
983 | * @global object | |
984 | * @param object $course | |
985 | * @param object $user | |
986 | * @param object $mod | |
987 | * @param object $data | |
988 | */ | |
3d4b223a | 989 | function data_user_complete($course, $user, $mod, $data) { |
1a96363a NC |
990 | global $DB, $CFG, $OUTPUT; |
991 | require_once("$CFG->libdir/gradelib.php"); | |
992 | ||
993 | $grades = grade_get_grades($course->id, 'mod', 'data', $data->id, $user->id); | |
994 | if (!empty($grades->items[0]->grades)) { | |
995 | $grade = reset($grades->items[0]->grades); | |
996 | echo $OUTPUT->container(get_string('grade').': '.$grade->str_long_grade); | |
997 | if ($grade->str_feedback) { | |
998 | echo $OUTPUT->container(get_string('feedback').': '.$grade->str_feedback); | |
999 | } | |
1000 | } | |
9c00b5d7 | 1001 | |
1002 | if ($records = $DB->get_records('data_records', array('dataid'=>$data->id,'userid'=>$user->id), 'timemodified DESC')) { | |
3d45b8e5 | 1003 | data_print_template('singletemplate', $records, $data); |
3d4b223a | 1004 | } |
1005 | } | |
1006 | ||
04366d79 | 1007 | /** |
1008 | * Return grade for given user or all users. | |
1009 | * | |
4636bf83 | 1010 | * @global object |
1011 | * @param object $data | |
04366d79 | 1012 | * @param int $userid optional user id, 0 means all users |
1013 | * @return array array of grades, false if none | |
1014 | */ | |
612607bd | 1015 | function data_get_user_grades($data, $userid=0) { |
d251b259 AD |
1016 | global $CFG; |
1017 | ||
1018 | require_once($CFG->dirroot.'/rating/lib.php'); | |
04366d79 | 1019 | |
2b04c41c SH |
1020 | $ratingoptions = new stdClass; |
1021 | $ratingoptions->component = 'mod_data'; | |
1022 | $ratingoptions->ratingarea = 'entry'; | |
d251b259 AD |
1023 | $ratingoptions->modulename = 'data'; |
1024 | $ratingoptions->moduleid = $data->id; | |
04366d79 | 1025 | |
d251b259 AD |
1026 | $ratingoptions->userid = $userid; |
1027 | $ratingoptions->aggregationmethod = $data->assessed; | |
1028 | $ratingoptions->scaleid = $data->scale; | |
1029 | $ratingoptions->itemtable = 'data_records'; | |
1030 | $ratingoptions->itemtableusercolumn = 'userid'; | |
04366d79 | 1031 | |
2b04c41c | 1032 | $rm = new rating_manager(); |
d251b259 | 1033 | return $rm->get_user_grades($ratingoptions); |
04366d79 | 1034 | } |
1035 | ||
1036 | /** | |
775f811a | 1037 | * Update activity grades |
04366d79 | 1038 | * |
4636bf83 | 1039 | * @global object |
1040 | * @global object | |
775f811a | 1041 | * @param object $data |
1042 | * @param int $userid specific user only, 0 means all | |
4636bf83 | 1043 | * @param bool $nullifnone |
04366d79 | 1044 | */ |
775f811a | 1045 | function data_update_grades($data, $userid=0, $nullifnone=true) { |
9c00b5d7 | 1046 | global $CFG, $DB; |
1047 | require_once($CFG->libdir.'/gradelib.php'); | |
04366d79 | 1048 | |
775f811a | 1049 | if (!$data->assessed) { |
1050 | data_grade_item_update($data); | |
b572ce19 | 1051 | |
775f811a | 1052 | } else if ($grades = data_get_user_grades($data, $userid)) { |
1053 | data_grade_item_update($data, $grades); | |
b572ce19 | 1054 | |
775f811a | 1055 | } else if ($userid and $nullifnone) { |
39790bd8 | 1056 | $grade = new stdClass(); |
775f811a | 1057 | $grade->userid = $userid; |
1058 | $grade->rawgrade = NULL; | |
1059 | data_grade_item_update($data, $grade); | |
b572ce19 | 1060 | |
04366d79 | 1061 | } else { |
775f811a | 1062 | data_grade_item_update($data); |
1063 | } | |
1064 | } | |
1065 | ||
1066 | /** | |
1067 | * Update all grades in gradebook. | |
4636bf83 | 1068 | * |
1069 | * @global object | |
775f811a | 1070 | */ |
1071 | function data_upgrade_grades() { | |
1072 | global $DB; | |
1073 | ||
1074 | $sql = "SELECT COUNT('x') | |
1075 | FROM {data} d, {course_modules} cm, {modules} m | |
1076 | WHERE m.name='data' AND m.id=cm.module AND cm.instance=d.id"; | |
1077 | $count = $DB->count_records_sql($sql); | |
1078 | ||
1079 | $sql = "SELECT d.*, cm.idnumber AS cmidnumber, d.course AS courseid | |
1080 | FROM {data} d, {course_modules} cm, {modules} m | |
1081 | WHERE m.name='data' AND m.id=cm.module AND cm.instance=d.id"; | |
6b1b1d03 EL |
1082 | $rs = $DB->get_recordset_sql($sql); |
1083 | if ($rs->valid()) { | |
775f811a | 1084 | // too much debug output |
775f811a | 1085 | $pbar = new progress_bar('dataupgradegrades', 500, true); |
1086 | $i=0; | |
1087 | foreach ($rs as $data) { | |
1088 | $i++; | |
1089 | upgrade_set_timeout(60*5); // set up timeout, may also abort execution | |
1090 | data_update_grades($data, 0, false); | |
1091 | $pbar->update($i, $count, "Updating Database grades ($i/$count)."); | |
04366d79 | 1092 | } |
1093 | } | |
6b1b1d03 | 1094 | $rs->close(); |
04366d79 | 1095 | } |
1096 | ||
1097 | /** | |
612607bd | 1098 | * Update/create grade item for given data |
04366d79 | 1099 | * |
4636bf83 | 1100 | * @global object |
04366d79 | 1101 | * @param object $data object with extra cmidnumber |
0b5a80a1 | 1102 | * @param mixed optional array/object of grade(s); 'reset' means reset grades in gradebook |
04366d79 | 1103 | * @return object grade_item |
1104 | */ | |
0b5a80a1 | 1105 | function data_grade_item_update($data, $grades=NULL) { |
612607bd | 1106 | global $CFG; |
9c00b5d7 | 1107 | require_once($CFG->libdir.'/gradelib.php'); |
04366d79 | 1108 | |
13534ef7 | 1109 | $params = array('itemname'=>$data->name, 'idnumber'=>$data->cmidnumber); |
b572ce19 | 1110 | |
04366d79 | 1111 | if (!$data->assessed or $data->scale == 0) { |
612607bd | 1112 | $params['gradetype'] = GRADE_TYPE_NONE; |
b572ce19 | 1113 | |
04366d79 | 1114 | } else if ($data->scale > 0) { |
1115 | $params['gradetype'] = GRADE_TYPE_VALUE; | |
1116 | $params['grademax'] = $data->scale; | |
1117 | $params['grademin'] = 0; | |
b572ce19 | 1118 | |
04366d79 | 1119 | } else if ($data->scale < 0) { |
1120 | $params['gradetype'] = GRADE_TYPE_SCALE; | |
1121 | $params['scaleid'] = -$data->scale; | |
1122 | } | |
b572ce19 | 1123 | |
0b5a80a1 | 1124 | if ($grades === 'reset') { |
1125 | $params['reset'] = true; | |
1126 | $grades = NULL; | |
1127 | } | |
1128 | ||
1129 | return grade_update('mod/data', $data->course, 'mod', 'data', $data->id, 0, $grades, $params); | |
04366d79 | 1130 | } |
1131 | ||
1132 | /** | |
1133 | * Delete grade item for given data | |
1134 | * | |
4636bf83 | 1135 | * @global object |
04366d79 | 1136 | * @param object $data object |
1137 | * @return object grade_item | |
1138 | */ | |
1139 | function data_grade_item_delete($data) { | |
612607bd | 1140 | global $CFG; |
1141 | require_once($CFG->libdir.'/gradelib.php'); | |
b572ce19 | 1142 | |
b67ec72f | 1143 | return grade_update('mod/data', $data->course, 'mod', 'data', $data->id, 0, NULL, array('deleted'=>1)); |
04366d79 | 1144 | } |
1145 | ||
4636bf83 | 1146 | /** |
1147 | * returns a list of participants of this database | |
1148 | * | |
2b04c41c SH |
1149 | * Returns the users with data in one data |
1150 | * (users with records in data_records, data_comments and ratings) | |
1151 | * | |
1152 | * @todo: deprecated - to be deleted in 2.2 | |
1153 | * | |
1154 | * @param int $dataid | |
4636bf83 | 1155 | * @return array |
1156 | */ | |
3d4b223a | 1157 | function data_get_participants($dataid) { |
8429163d | 1158 | global $DB; |
9c00b5d7 | 1159 | |
2b04c41c SH |
1160 | $params = array('dataid' => $dataid); |
1161 | ||
1162 | $sql = "SELECT DISTINCT u.id, u.id | |
1163 | FROM {user} u, | |
1164 | {data_records} r | |
1165 | WHERE r.dataid = :dataid AND | |
1166 | u.id = r.userid"; | |
1167 | $records = $DB->get_records_sql($sql, $params); | |
1168 | ||
1169 | $sql = "SELECT DISTINCT u.id, u.id | |
1170 | FROM {user} u, | |
1171 | {data_records} r, | |
1172 | {comments} c | |
1173 | WHERE r.dataid = ? AND | |
1174 | u.id = r.userid AND | |
1175 | r.id = c.itemid AND | |
1176 | c.commentarea = 'database_entry'"; | |
1177 | $comments = $DB->get_records_sql($sql, $params); | |
1178 | ||
1179 | $sql = "SELECT DISTINCT u.id, u.id | |
1180 | FROM {user} u, | |
1181 | {data_records} r, | |
1182 | {ratings} a | |
1183 | WHERE r.dataid = ? AND | |
1184 | u.id = r.userid AND | |
1185 | r.id = a.itemid AND | |
1186 | a.component = 'mod_data' AND | |
1187 | a.ratingarea = 'entry'"; | |
1188 | $ratings = $DB->get_records_sql($sql, $params); | |
3d4b223a | 1189 | |
1190 | $participants = array(); | |
b572ce19 | 1191 | |
8429163d | 1192 | if ($records) { |
3d4b223a | 1193 | foreach ($records as $record) { |
1194 | $participants[$record->id] = $record; | |
1195 | } | |
1196 | } | |
8429163d | 1197 | if ($comments) { |
3d4b223a | 1198 | foreach ($comments as $comment) { |
1199 | $participants[$comment->id] = $comment; | |
1200 | } | |
1201 | } | |
8429163d | 1202 | if ($ratings) { |
cf040300 | 1203 | foreach ($ratings as $rating) { |
1204 | $participants[$rating->id] = $rating; | |
1205 | } | |
1206 | } | |
b572ce19 | 1207 | |
3d4b223a | 1208 | return $participants; |
1209 | } | |
1210 | ||
b8b554ac | 1211 | // junk functions |
4636bf83 | 1212 | /** |
56c1ca88 | 1213 | * takes a list of records, the current data, a search string, |
4636bf83 | 1214 | * and mode to display prints the translated template |
1215 | * | |
1216 | * @global object | |
1217 | * @global object | |
1218 | * @param string $template | |
56c1ca88 | 1219 | * @param array $records |
4636bf83 | 1220 | * @param object $data |
56c1ca88 | 1221 | * @param string $search |
4636bf83 | 1222 | * @param int $page |
1223 | * @param bool $return | |
1224 | * @return mixed | |
1225 | */ | |
d53e5129 | 1226 | function data_print_template($template, $records, $data, $search='', $page=0, $return=false) { |
f2a1963c | 1227 | global $CFG, $DB, $OUTPUT; |
c088d603 | 1228 | $cm = get_coursemodule_from_instance('data', $data->id); |
dabfd0ed | 1229 | $context = get_context_instance(CONTEXT_MODULE, $cm->id); |
b572ce19 | 1230 | |
3d45b8e5 | 1231 | static $fields = NULL; |
1232 | static $isteacher; | |
63701c78 | 1233 | static $dataid = NULL; |
b572ce19 | 1234 | |
63701c78 | 1235 | if (empty($dataid)) { |
1236 | $dataid = $data->id; | |
1237 | } else if ($dataid != $data->id) { | |
1238 | $fields = NULL; | |
1239 | } | |
b572ce19 | 1240 | |
3d45b8e5 | 1241 | if (empty($fields)) { |
9c00b5d7 | 1242 | $fieldrecords = $DB->get_records('data_fields', array('dataid'=>$data->id)); |
3d45b8e5 | 1243 | foreach ($fieldrecords as $fieldrecord) { |
1244 | $fields[]= data_get_field($fieldrecord, $data); | |
1245 | } | |
81e956b9 | 1246 | $isteacher = has_capability('mod/data:managetemplates', $context); |
3d45b8e5 | 1247 | } |
b572ce19 | 1248 | |
64452eb4 | 1249 | if (empty($records)) { |
1250 | return; | |
1251 | } | |
b572ce19 | 1252 | |
668fc89a | 1253 | foreach ($records as $record) { // Might be just one for the single template |
b572ce19 | 1254 | |
b8b554ac | 1255 | // Replacing tags |
3d4b223a | 1256 | $patterns = array(); |
1257 | $replacement = array(); | |
b572ce19 | 1258 | |
b8b554ac | 1259 | // Then we generate strings to replace for normal tags |
3d45b8e5 | 1260 | foreach ($fields as $field) { |
f2584d0e | 1261 | $patterns[]='[['.$field->field->name.']]'; |
d118d06a | 1262 | $replacement[] = highlight($search, $field->display_browse_field($record->id, $template)); |
3d4b223a | 1263 | } |
b572ce19 | 1264 | |
b8b554ac | 1265 | // Replacing special tags (##Edit##, ##Delete##, ##More##) |
e357c206 | 1266 | $patterns[]='##edit##'; |
1267 | $patterns[]='##delete##'; | |
046dd7dc | 1268 | if (has_capability('mod/data:manageentries', $context) or data_isowner($record->id)) { |
64452eb4 | 1269 | $replacement[] = '<a href="'.$CFG->wwwroot.'/mod/data/edit.php?d=' |
b5d0cafc | 1270 | .$data->id.'&rid='.$record->id.'&sesskey='.sesskey().'"><img src="'.$OUTPUT->pix_url('t/edit') . '" class="iconsmall" alt="'.get_string('edit').'" title="'.get_string('edit').'" /></a>'; |
3d4b223a | 1271 | $replacement[] = '<a href="'.$CFG->wwwroot.'/mod/data/view.php?d=' |
b5d0cafc | 1272 | .$data->id.'&delete='.$record->id.'&sesskey='.sesskey().'"><img src="'.$OUTPUT->pix_url('t/delete') . '" class="iconsmall" alt="'.get_string('delete').'" title="'.get_string('delete').'" /></a>'; |
046dd7dc | 1273 | } else { |
3d4b223a | 1274 | $replacement[] = ''; |
eeeb4f2a | 1275 | $replacement[] = ''; |
3d4b223a | 1276 | } |
d53e5129 | 1277 | |
1278 | $moreurl = $CFG->wwwroot . '/mod/data/view.php?d=' . $data->id . '&rid=' . $record->id; | |
32d799c6 | 1279 | if ($search) { |
1280 | $moreurl .= '&filter=1'; | |
1281 | } | |
e357c206 | 1282 | $patterns[]='##more##'; |
b5d0cafc | 1283 | $replacement[] = '<a href="' . $moreurl . '"><img src="' . $OUTPUT->pix_url('i/search') . '" class="iconsmall" alt="' . get_string('more', 'data') . '" title="' . get_string('more', 'data') . '" /></a>'; |
d53e5129 | 1284 | |
e357c206 | 1285 | $patterns[]='##moreurl##'; |
d53e5129 | 1286 | $replacement[] = $moreurl; |
473dd288 | 1287 | |
e357c206 | 1288 | $patterns[]='##user##'; |
64452eb4 | 1289 | $replacement[] = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$record->userid. |
1290 | '&course='.$data->course.'">'.fullname($record).'</a>'; | |
8185aeb6 | 1291 | |
1292 | $patterns[]='##export##'; | |
1293 | ||
6708a1f5 | 1294 | if (!empty($CFG->enableportfolios) && ($template == 'singletemplate' || $template == 'listtemplate') |
8185aeb6 | 1295 | && ((has_capability('mod/data:exportentry', $context) |
1296 | || (data_isowner($record->id) && has_capability('mod/data:exportownentry', $context))))) { | |
24ba58ee | 1297 | require_once($CFG->libdir . '/portfoliolib.php'); |
0d06b6fd | 1298 | $button = new portfolio_add_button(); |
24ba58ee | 1299 | $button->set_callback_options('data_portfolio_caller', array('id' => $cm->id, 'recordid' => $record->id), '/mod/data/locallib.php'); |
6be1dcae | 1300 | list($formats, $files) = data_portfolio_caller::formats($fields, $record); |
276378e6 | 1301 | $button->set_formats($formats); |
0d06b6fd | 1302 | $replacement[] = $button->to_html(PORTFOLIO_ADD_ICON_LINK); |
8185aeb6 | 1303 | } else { |
1304 | $replacement[] = ''; | |
1305 | } | |
8429163d | 1306 | |
c95034f2 | 1307 | $patterns[] = '##timeadded##'; |
8429163d | 1308 | $replacement[] = userdate($record->timecreated); |
c95034f2 | 1309 | |
1310 | $patterns[] = '##timemodified##'; | |
35e129c1 | 1311 | $replacement [] = userdate($record->timemodified); |
473dd288 | 1312 | |
e357c206 | 1313 | $patterns[]='##approve##'; |
b572ce19 | 1314 | if (has_capability('mod/data:approve', $context) && ($data->approval) && (!$record->approved)){ |
b5d0cafc | 1315 | $replacement[] = '<span class="approve"><a href="'.$CFG->wwwroot.'/mod/data/view.php?d='.$data->id.'&approve='.$record->id.'&sesskey='.sesskey().'"><img src="'.$OUTPUT->pix_url('i/approve') . '" class="icon" alt="'.get_string('approve').'" /></a></span>'; |
473dd288 | 1316 | } else { |
6e0119dd | 1317 | $replacement[] = ''; |
1318 | } | |
6403e679 | 1319 | |
e357c206 | 1320 | $patterns[]='##comments##'; |
4d3d87f0 | 1321 | if (($template == 'listtemplate') && ($data->comments)) { |
e998effa DC |
1322 | |
1323 | if (!empty($CFG->usecomments)) { | |
36051c9e | 1324 | require_once($CFG->dirroot . '/comment/lib.php'); |
866354a9 | 1325 | list($context, $course, $cm) = get_context_info_array($context->id); |
6bdfef5d | 1326 | $cmt = new stdClass(); |
e998effa | 1327 | $cmt->context = $context; |
866354a9 DC |
1328 | $cmt->course = $course; |
1329 | $cmt->cm = $cm; | |
1330 | $cmt->area = 'database_entry'; | |
e998effa DC |
1331 | $cmt->itemid = $record->id; |
1332 | $cmt->showcount = true; | |
d846488e | 1333 | $cmt->component = 'mod_data'; |
e998effa | 1334 | $comment = new comment($cmt); |
36051c9e | 1335 | $replacement[] = $comment->output(true); |
e998effa | 1336 | } |
4d3d87f0 | 1337 | } else { |
1338 | $replacement[] = ''; | |
1339 | } | |
6e0119dd | 1340 | |
b8b554ac | 1341 | // actual replacement of the tags |
f2584d0e | 1342 | $newtext = str_ireplace($patterns, $replacement, $data->{$template}); |
5023c3ab | 1343 | |
b8b554ac | 1344 | // no more html formatting and filtering - see MDL-6635 |
aa3b20e9 | 1345 | if ($return) { |
1346 | return $newtext; | |
1347 | } else { | |
1348 | echo $newtext; | |
b572ce19 | 1349 | |
aa3b20e9 | 1350 | // hack alert - return is always false in singletemplate anyway ;-) |
1351 | /********************************** | |
1352 | * Printing Ratings Form * | |
1353 | *********************************/ | |
1354 | if ($template == 'singletemplate') { //prints ratings options | |
1355 | data_print_ratings($data, $record); | |
1356 | } | |
b572ce19 | 1357 | |
aa3b20e9 | 1358 | /********************************** |
d251b259 | 1359 | * Printing Comments Form * |
aa3b20e9 | 1360 | *********************************/ |
d251b259 | 1361 | if (($template == 'singletemplate') && ($data->comments)) { |
e998effa | 1362 | if (!empty($CFG->usecomments)) { |
36051c9e | 1363 | require_once($CFG->dirroot . '/comment/lib.php'); |
866354a9 | 1364 | list($context, $course, $cm) = get_context_info_array($context->id); |
6bdfef5d | 1365 | $cmt = new stdClass(); |
e998effa | 1366 | $cmt->context = $context; |
866354a9 DC |
1367 | $cmt->course = $course; |
1368 | $cmt->cm = $cm; | |
1369 | $cmt->area = 'database_entry'; | |
e998effa DC |
1370 | $cmt->itemid = $record->id; |
1371 | $cmt->showcount = true; | |
d846488e | 1372 | $cmt->component = 'mod_data'; |
e998effa | 1373 | $comment = new comment($cmt); |
36051c9e | 1374 | $comment->output(false); |
e998effa | 1375 | } |
aa3b20e9 | 1376 | } |
4d3d87f0 | 1377 | } |
3d4b223a | 1378 | } |
1379 | } | |
1380 | ||
d251b259 AD |
1381 | /** |
1382 | * Return rating related permissions | |
2b04c41c SH |
1383 | * |
1384 | * @param string $contextid the context id | |
1385 | * @param string $component the component to get rating permissions for | |
1386 | * @param string $ratingarea the rating area to get permissions for | |
d251b259 AD |
1387 | * @return array an associative array of the user's rating permissions |
1388 | */ | |
2b04c41c SH |
1389 | function data_rating_permissions($contextid, $component, $ratingarea) { |
1390 | $context = get_context_instance_by_id($contextid, MUST_EXIST); | |
1391 | if ($component != 'mod_data' || $ratingarea != 'entry') { | |
d251b259 | 1392 | return null; |
d251b259 | 1393 | } |
2b04c41c SH |
1394 | return array( |
1395 | 'view' => has_capability('mod/data:viewrating',$context), | |
1396 | 'viewany' => has_capability('mod/data:viewanyrating',$context), | |
1397 | 'viewall' => has_capability('mod/data:viewallratings',$context), | |
1398 | 'rate' => has_capability('mod/data:rate',$context) | |
1399 | ); | |
d251b259 AD |
1400 | } |
1401 | ||
aeafd436 | 1402 | /** |
2c2ff8d5 AD |
1403 | * Validates a submitted rating |
1404 | * @param array $params submitted data | |
1405 | * context => object the context in which the rated items exists [required] | |
1406 | * itemid => int the ID of the object being rated | |
1407 | * scaleid => int the scale from which the user can select a rating. Used for bounds checking. [required] | |
1408 | * rating => int the submitted rating | |
1409 | * rateduserid => int the id of the user whose items have been rated. NOT the user who submitted the ratings. 0 to update all. [required] | |
1410 | * aggregation => int the aggregation method to apply when calculating grades ie RATING_AGGREGATE_AVERAGE [required] | |
778361c3 | 1411 | * @return boolean true if the rating is valid. Will throw rating_exception if not |
aeafd436 | 1412 | */ |
778361c3 | 1413 | function data_rating_validate($params) { |
2c2ff8d5 AD |
1414 | global $DB, $USER; |
1415 | ||
2b04c41c SH |
1416 | // Check the component is mod_data |
1417 | if ($params['component'] != 'mod_data') { | |
1418 | throw new rating_exception('invalidcomponent'); | |
2c2ff8d5 AD |
1419 | } |
1420 | ||
2b04c41c SH |
1421 | // Check the ratingarea is entry (the only rating area in data module) |
1422 | if ($params['ratingarea'] != 'entry') { | |
1423 | throw new rating_exception('invalidratingarea'); | |
1424 | } | |
1425 | ||
1426 | // Check the rateduserid is not the current user .. you can't rate your own entries | |
1427 | if ($params['rateduserid'] == $USER->id) { | |
1428 | throw new rating_exception('nopermissiontorate'); | |
1429 | } | |
1430 | ||
1431 | $datasql = "SELECT d.id as dataid, d.scale, d.course, r.userid as userid, d.approval, r.approved, r.timecreated, d.assesstimestart, d.assesstimefinish, r.groupid | |
2c2ff8d5 AD |
1432 | FROM {data_records} r |
1433 | JOIN {data} d ON r.dataid = d.id | |
1434 | WHERE r.id = :itemid"; | |
1435 | $dataparams = array('itemid'=>$params['itemid']); | |
1436 | if (!$info = $DB->get_record_sql($datasql, $dataparams)) { | |
778361c3 AD |
1437 | //item doesn't exist |
1438 | throw new rating_exception('invaliditemid'); | |
2c2ff8d5 AD |
1439 | } |
1440 | ||
6ac149dc AD |
1441 | if ($info->scale != $params['scaleid']) { |
1442 | //the scale being submitted doesnt match the one in the database | |
1443 | throw new rating_exception('invalidscaleid'); | |
1444 | } | |
1445 | ||
6ac149dc | 1446 | //check that the submitted rating is valid for the scale |
5693d56c EL |
1447 | |
1448 | // lower limit | |
1449 | if ($params['rating'] < 0 && $params['rating'] != RATING_UNSET_RATING) { | |
6ac149dc | 1450 | throw new rating_exception('invalidnum'); |
5693d56c EL |
1451 | } |
1452 | ||
1453 | // upper limit | |
1454 | if ($info->scale < 0) { | |
6ac149dc | 1455 | //its a custom scale |
2b04c41c | 1456 | $scalerecord = $DB->get_record('scale', array('id' => -$info->scale)); |
6ac149dc AD |
1457 | if ($scalerecord) { |
1458 | $scalearray = explode(',', $scalerecord->scale); | |
1459 | if ($params['rating'] > count($scalearray)) { | |
1460 | throw new rating_exception('invalidnum'); | |
1461 | } | |
1462 | } else { | |
1463 | throw new rating_exception('invalidscaleid'); | |
1464 | } | |
1465 | } else if ($params['rating'] > $info->scale) { | |
1466 | //if its numeric and submitted rating is above maximum | |
1467 | throw new rating_exception('invalidnum'); | |
1468 | } | |
1469 | ||
2c2ff8d5 AD |
1470 | if ($info->approval && !$info->approved) { |
1471 | //database requires approval but this item isnt approved | |
778361c3 | 1472 | throw new rating_exception('nopermissiontorate'); |
2c2ff8d5 AD |
1473 | } |
1474 | ||
2b04c41c | 1475 | // check the item we're rating was created in the assessable time window |
2c2ff8d5 AD |
1476 | if (!empty($info->assesstimestart) && !empty($info->assesstimefinish)) { |
1477 | if ($info->timecreated < $info->assesstimestart || $info->timecreated > $info->assesstimefinish) { | |
778361c3 | 1478 | throw new rating_exception('notavailable'); |
2c2ff8d5 AD |
1479 | } |
1480 | } | |
1481 | ||
2b04c41c SH |
1482 | $course = $DB->get_record('course', array('id'=>$info->course), '*', MUST_EXIST); |
1483 | $cm = get_coursemodule_from_instance('data', $info->dataid, $course->id, false, MUST_EXIST); | |
1484 | $context = get_context_instance(CONTEXT_MODULE, $cm->id, MUST_EXIST); | |
2c2ff8d5 | 1485 | |
2b04c41c SH |
1486 | // if the supplied context doesnt match the item's context |
1487 | if ($context->id != $params['context']->id) { | |
778361c3 | 1488 | throw new rating_exception('invalidcontext'); |
2c2ff8d5 AD |
1489 | } |
1490 | ||
1491 | // Make sure groups allow this user to see the item they're rating | |
2b04c41c | 1492 | $groupid = $info->groupid; |
2c2ff8d5 AD |
1493 | if ($groupid > 0 and $groupmode = groups_get_activity_groupmode($cm, $course)) { // Groups are being used |
1494 | if (!groups_group_exists($groupid)) { // Can't find group | |
778361c3 | 1495 | throw new rating_exception('cannotfindgroup');//something is wrong |
2c2ff8d5 AD |
1496 | } |
1497 | ||
1498 | if (!groups_is_member($groupid) and !has_capability('moodle/site:accessallgroups', $context)) { | |
1499 | // do not allow rating of posts from other groups when in SEPARATEGROUPS or VISIBLEGROUPS | |
778361c3 | 1500 | throw new rating_exception('notmemberofgroup'); |
2c2ff8d5 AD |
1501 | } |
1502 | } | |
1503 | ||
1504 | return true; | |
aeafd436 AD |
1505 | } |
1506 | ||
a593aeee | 1507 | |
4636bf83 | 1508 | /** |
56c1ca88 | 1509 | * function that takes in the current data, number of items per page, |
1510 | * a search string and prints a preference box in view.php | |
1511 | * | |
1512 | * This preference box prints a searchable advanced search template if | |
1513 | * a) A template is defined | |
1514 | * b) The advanced search checkbox is checked. | |
4636bf83 | 1515 | * |
1516 | * @global object | |
1517 | * @global object | |
56c1ca88 | 1518 | * @param object $data |
1519 | * @param int $perpage | |
4636bf83 | 1520 | * @param string $search |
1521 | * @param string $sort | |
1522 | * @param string $order | |
1523 | * @param array $search_array | |
1524 | * @param int $advanced | |
1525 | * @param string $mode | |
1526 | * @return void | |
1527 | */ | |
7900ecb0 | 1528 | function data_print_preference_form($data, $perpage, $search, $sort='', $order='ASC', $search_array = '', $advanced = 0, $mode= ''){ |
601104f2 | 1529 | global $CFG, $DB, $PAGE, $OUTPUT; |
8429163d | 1530 | |
7900ecb0 | 1531 | $cm = get_coursemodule_from_instance('data', $data->id); |
1532 | $context = get_context_instance(CONTEXT_MODULE, $cm->id); | |
1533 | echo '<br /><div class="datapreferences">'; | |
b7dc2256 | 1534 | echo '<form id="options" action="view.php" method="get">'; |
7900ecb0 | 1535 | echo '<div>'; |
473dd288 | 1536 | echo '<input type="hidden" name="d" value="'.$data->id.'" />'; |
7900ecb0 | 1537 | if ($mode =='asearch') { |
1538 | $advanced = 1; | |
1539 | echo '<input type="hidden" name="mode" value="list" />'; | |
1540 | } | |
a032a460 | 1541 | echo '<label for="pref_perpage">'.get_string('pagesize','data').'</label> '; |
76a2fd82 | 1542 | $pagesizes = array(2=>2,3=>3,4=>4,5=>5,6=>6,7=>7,8=>8,9=>9,10=>10,15=>15, |
6e0119dd | 1543 | 20=>20,30=>30,40=>40,50=>50,100=>100,200=>200,300=>300,400=>400,500=>500,1000=>1000); |
d776d59e | 1544 | echo html_writer::select($pagesizes, 'perpage', $perpage, false, array('id'=>'pref_perpage')); |
4b9210f3 | 1545 | echo '<div id="reg_search" style="display: '; |
7900ecb0 | 1546 | if ($advanced) { |
1547 | echo 'none'; | |
1548 | } | |
1549 | else { | |
1550 | echo 'inline'; | |
1551 | } | |
1552 | echo ';" > <label for="pref_search">'.get_string('search').'</label> <input type="text" size="16" name="search" id= "pref_search" value="'.s($search).'" /></div>'; | |
a032a460 | 1553 | echo ' <label for="pref_sortby">'.get_string('sortby').'</label> '; |
b8b554ac | 1554 | // foreach field, print the option |
3239b010 | 1555 | echo '<select name="sort" id="pref_sortby">'; |
9c00b5d7 | 1556 | if ($fields = $DB->get_records('data_fields', array('dataid'=>$data->id), 'name')) { |
3239b010 | 1557 | echo '<optgroup label="'.get_string('fields', 'data').'">'; |
1558 | foreach ($fields as $field) { | |
1559 | if ($field->id == $sort) { | |
1560 | echo '<option value="'.$field->id.'" selected="selected">'.$field->name.'</option>'; | |
1561 | } else { | |
1562 | echo '<option value="'.$field->id.'">'.$field->name.'</option>'; | |
1563 | } | |
1564 | } | |
1565 | echo '</optgroup>'; | |
714bec74 | 1566 | } |
3239b010 | 1567 | $options = array(); |
1568 | $options[DATA_TIMEADDED] = get_string('timeadded', 'data'); | |
1569 | $options[DATA_TIMEMODIFIED] = get_string('timemodified', 'data'); | |
1570 | $options[DATA_FIRSTNAME] = get_string('authorfirstname', 'data'); | |
1571 | $options[DATA_LASTNAME] = get_string('authorlastname', 'data'); | |
bb5740f4 | 1572 | if ($data->approval and has_capability('mod/data:approve', $context)) { |
1573 | $options[DATA_APPROVED] = get_string('approved', 'data'); | |
1574 | } | |
3239b010 | 1575 | echo '<optgroup label="'.get_string('other', 'data').'">'; |
714bec74 | 1576 | foreach ($options as $key => $name) { |
1577 | if ($key == $sort) { | |
1578 | echo '<option value="'.$key.'" selected="selected">'.$name.'</option>'; | |
cf3e199b | 1579 | } else { |
714bec74 | 1580 | echo '<option value="'.$key.'">'.$name.'</option>'; |
cf3e199b | 1581 | } |
1582 | } | |
3239b010 | 1583 | echo '</optgroup>'; |
cf3e199b | 1584 | echo '</select>'; |
a032a460 | 1585 | echo '<label for="pref_order" class="accesshide">'.get_string('order').'</label>'; |
1586 | echo '<select id="pref_order" name="order">'; | |
c8505cac | 1587 | if ($order == 'ASC') { |
af25f45e | 1588 | echo '<option value="ASC" selected="selected">'.get_string('ascending','data').'</option>'; |
cf3e199b | 1589 | } else { |
1590 | echo '<option value="ASC">'.get_string('ascending','data').'</option>'; | |
1591 | } | |
c8505cac | 1592 | if ($order == 'DESC') { |
af25f45e | 1593 | echo '<option value="DESC" selected="selected">'.get_string('descending','data').'</option>'; |
cf3e199b | 1594 | } else { |
1595 | echo '<option value="DESC">'.get_string('descending','data').'</option>'; | |
1596 | } | |
af25f45e | 1597 | echo '</select>'; |
86638489 | 1598 | |
7900ecb0 | 1599 | if ($advanced) { |
1600 | $checked = ' checked="checked" '; | |
1601 | } | |
1602 | else { | |
1603 | $checked = ''; | |
1604 | } | |
9dec75db | 1605 | $PAGE->requires->js('/mod/data/data.js'); |
de8ff581 | 1606 | echo ' <input type="hidden" name="advanced" value="0" />'; |
d53e5129 | 1607 | echo ' <input type="hidden" name="filter" value="1" />'; |
714bec74 | 1608 | echo ' <input type="checkbox" id="advancedcheckbox" name="advanced" value="1" '.$checked.' onchange="showHideAdvSearch(this.checked);" /><label for="advancedcheckbox">'.get_string('advancedsearch', 'data').'</label>'; |
7900ecb0 | 1609 | echo ' <input type="submit" value="'.get_string('savesettings','data').'" />'; |
8429163d | 1610 | |
7900ecb0 | 1611 | echo '<br />'; |
86638489 | 1612 | echo '<div class="dataadvancedsearch" id="data_adv_form" style="display: '; |
8429163d | 1613 | |
7900ecb0 | 1614 | if ($advanced) { |
1615 | echo 'inline'; | |
1616 | } | |
1617 | else { | |
1618 | echo 'none'; | |
1619 | } | |
86638489 | 1620 | echo ';margin-left:auto;margin-right:auto;" >'; |
7900ecb0 | 1621 | echo '<table class="boxaligncenter">'; |
8429163d | 1622 | |
7900ecb0 | 1623 | // print ASC or DESC |
1624 | echo '<tr><td colspan="2"> </td></tr>'; | |
1625 | $i = 0; | |
1626 | ||
1627 | // Determine if we are printing all fields for advanced search, or the template for advanced search | |
1628 | // If a template is not defined, use the deafault template and display all fields. | |
1629 | if(empty($data->asearchtemplate)) { | |
1630 | data_generate_default_template($data, 'asearchtemplate'); | |
1631 | } | |
1632 | ||
1633 | static $fields = NULL; | |
1634 | static $isteacher; | |
1635 | static $dataid = NULL; | |
b572ce19 | 1636 | |
7900ecb0 | 1637 | if (empty($dataid)) { |
1638 | $dataid = $data->id; | |
1639 | } else if ($dataid != $data->id) { | |
1640 | $fields = NULL; | |
1641 | } | |
1642 | ||
1643 | if (empty($fields)) { | |
9c00b5d7 | 1644 | $fieldrecords = $DB->get_records('data_fields', array('dataid'=>$data->id)); |
7900ecb0 | 1645 | foreach ($fieldrecords as $fieldrecord) { |
1646 | $fields[]= data_get_field($fieldrecord, $data); | |
1647 | } | |
b572ce19 | 1648 | |
7900ecb0 | 1649 | $isteacher = has_capability('mod/data:managetemplates', $context); |
1650 | } | |
1651 | ||
b8b554ac | 1652 | // Replacing tags |
7900ecb0 | 1653 | $patterns = array(); |
1654 | $replacement = array(); | |
1655 | ||
b8b554ac | 1656 | // Then we generate strings to replace for normal tags |
7900ecb0 | 1657 | foreach ($fields as $field) { |
98f67312 | 1658 | $fieldname = $field->field->name; |
1659 | $fieldname = preg_quote($fieldname, '/'); | |
1660 | $patterns[] = "/\[\[$fieldname\]\]/i"; | |
714bec74 | 1661 | $searchfield = data_get_field_from_id($field->field->id, $data); |
7900ecb0 | 1662 | if (!empty($search_array[$field->field->id]->data)) { |
1663 | $replacement[] = $searchfield->display_search_field($search_array[$field->field->id]->data); | |
1664 | } else { | |
1665 | $replacement[] = $searchfield->display_search_field(); | |
1666 | } | |
1667 | } | |
714bec74 | 1668 | $fn = !empty($search_array[DATA_FIRSTNAME]->data) ? $search_array[DATA_FIRSTNAME]->data : ''; |
1669 | $ln = !empty($search_array[DATA_LASTNAME]->data) ? $search_array[DATA_LASTNAME]->data : ''; | |
1670 | $patterns[] = '/##firstname##/'; | |
bc16bd57 | 1671 | $replacement[] = '<input type="text" size="16" name="u_fn" value="'.$fn.'" />'; |
714bec74 | 1672 | $patterns[] = '/##lastname##/'; |
bc16bd57 | 1673 | $replacement[] = '<input type="text" size="16" name="u_ln" value="'.$ln.'" />'; |
714bec74 | 1674 | |
668fc89a | 1675 | // actual replacement of the tags |
7900ecb0 | 1676 | $newtext = preg_replace($patterns, $replacement, $data->asearchtemplate); |
b572ce19 | 1677 | |
39790bd8 | 1678 | $options = new stdClass(); |
7900ecb0 | 1679 | $options->para=false; |
1680 | $options->noclean=true; | |
1681 | echo '<tr><td>'; | |
1682 | echo format_text($newtext, FORMAT_HTML, $options); | |
1683 | echo '</td></tr>'; | |
b572ce19 | 1684 | |
eeeb4f2a | 1685 | echo '<tr><td colspan="4" style="text-align: center;"><br/><input type="submit" value="'.get_string('savesettings','data').'" /><input type="submit" name="resetadv" value="'.get_string('resetsettings','data').'" /></td></tr>'; |
7900ecb0 | 1686 | echo '</table>'; |
c8505cac | 1687 | echo '</div>'; |
7900ecb0 | 1688 | echo '</div>'; |
1689 | echo '</form>'; | |
b8b554ac | 1690 | echo '</div>'; |
3d4b223a | 1691 | } |
5f5bcda8 | 1692 | |
4636bf83 | 1693 | /** |
1694 | * @global object | |
1695 | * @global object | |
1696 | * @param object $data | |
1697 | * @param object $record | |
1698 | * @return void Output echo'd | |
1699 | */ | |
4d3d87f0 | 1700 | function data_print_ratings($data, $record) { |
56c1ca88 | 1701 | global $OUTPUT; |
2b04c41c | 1702 | if (!empty($record->rating)){ |
d251b259 | 1703 | echo $OUTPUT->render($record->rating); |
4d3d87f0 | 1704 | } |
4d3d87f0 | 1705 | } |
1706 | ||
4636bf83 | 1707 | /** |
1708 | * For Participantion Reports | |
1709 | * | |
1710 | * @return array | |
1711 | */ | |
4c03f920 | 1712 | function data_get_view_actions() { |
1713 | return array('view'); | |
1714 | } | |
1715 | ||
4636bf83 | 1716 | /** |
1717 | * @return array | |
1718 | */ | |
4c03f920 | 1719 | function data_get_post_actions() { |
1720 | return array('add','update','record delete'); | |
1721 | } | |
1722 | ||
4636bf83 | 1723 | /** |
4636bf83 | 1724 | * @param string $name |
1725 | * @param int $dataid | |
1726 | * @param int $fieldid | |
1727 | * @return bool | |
1728 | */ | |
e9da9f5b PS |
1729 | function data_fieldname_exists($name, $dataid, $fieldid = 0) { |
1730 | global $DB; | |
0997e51a | 1731 | |
e9da9f5b PS |
1732 | if (!is_numeric($name)) { |
1733 | $like = $DB->sql_like('df.name', ':name', false); | |
fdeb3e1f | 1734 | } else { |
e9da9f5b | 1735 | $like = "df.name = :name"; |
fdeb3e1f | 1736 | } |
e9da9f5b | 1737 | $params = array('name'=>$name); |
6403e679 | 1738 | if ($fieldid) { |
e9da9f5b PS |
1739 | $params['dataid'] = $dataid; |
1740 | $params['fieldid1'] = $fieldid; | |
1741 | $params['fieldid2'] = $fieldid; | |
9c00b5d7 | 1742 | return $DB->record_exists_sql("SELECT * FROM {data_fields} df |
e9da9f5b PS |
1743 | WHERE $like AND df.dataid = :dataid |
1744 | AND ((df.id < :fieldid1) OR (df.id > :fieldid2))", $params); | |
0997e51a | 1745 | } else { |
e9da9f5b | 1746 | $params['dataid'] = $dataid; |
9c00b5d7 | 1747 | return $DB->record_exists_sql("SELECT * FROM {data_fields} df |
e9da9f5b | 1748 | WHERE $like AND df.dataid = :dataid", $params); |
0997e51a | 1749 | } |
1750 | } | |
1751 | ||
4636bf83 | 1752 | /** |
1753 | * @param array $fieldinput | |
1754 | */ | |
0997e51a | 1755 | function data_convert_arrays_to_strings(&$fieldinput) { |
1756 | foreach ($fieldinput as $key => $val) { | |
1757 | if (is_array($val)) { | |
1758 | $str = ''; | |
1759 | foreach ($val as $inner) { | |
1760 | $str .= $inner . ','; | |
1761 | } | |
1762 | $str = substr($str, 0, -1); | |
b572ce19 | 1763 | |
0997e51a | 1764 | $fieldinput->$key = $str; |
1765 | } | |
1766 | } | |
1767 | } | |
1768 | ||
901dd2fb | 1769 | |
7f258664 | 1770 | /** |
1771 | * Converts a database (module instance) to use the Roles System | |
4636bf83 | 1772 | * |
1773 | * @global object | |
1774 | * @global object | |
1775 | * @uses CONTEXT_MODULE | |
1776 | * @uses CAP_PREVENT | |
1777 | * @uses CAP_ALLOW | |
1778 | * @param object $data a data object with the same attributes as a record | |
1779 | * from the data database table | |
1780 | * @param int $datamodid the id of the data module, from the modules table | |
4f0c2d00 PS |
1781 | * @param array $teacherroles array of roles that have archetype teacher |
1782 | * @param array $studentroles array of roles that have archetype student | |
1783 | * @param array $guestroles array of roles that have archetype guest | |
4636bf83 | 1784 | * @param int $cmid the course_module id for this data instance |
1785 | * @return boolean data module was converted or not | |
7f258664 | 1786 | */ |
1787 | function data_convert_to_roles($data, $teacherroles=array(), $studentroles=array(), $cmid=NULL) { | |
4102b449 | 1788 | global $CFG, $DB, $OUTPUT; |
6403e679 | 1789 | |
7f258664 | 1790 | if (!isset($data->participants) && !isset($data->assesspublic) |
1791 | && !isset($data->groupmode)) { | |
1792 | // We assume that this database has already been converted to use the | |
1793 | // Roles System. above fields get dropped the data module has been | |
1794 | // upgraded to use Roles. | |
1795 | return false; | |
1796 | } | |
b572ce19 | 1797 | |
7f258664 | 1798 | if (empty($cmid)) { |
1799 | // We were not given the course_module id. Try to find it. | |
741c4d0b | 1800 | if (!$cm = get_coursemodule_from_instance('data', $data->id)) { |
4102b449 | 1801 | echo $OUTPUT->notification('Could not get the course module for the data'); |
7f258664 | 1802 | return false; |
1803 | } else { | |
1804 | $cmid = $cm->id; | |
1805 | } | |
1806 | } | |
1807 | $context = get_context_instance(CONTEXT_MODULE, $cmid); | |
6403e679 | 1808 | |
b572ce19 | 1809 | |
7f258664 | 1810 | // $data->participants: |
1811 | // 1 - Only teachers can add entries | |
1812 | // 3 - Teachers and students can add entries | |
1813 | switch ($data->participants) { | |
1814 | case 1: | |
1815 | foreach ($studentroles as $studentrole) { | |
1816 | assign_capability('mod/data:writeentry', CAP_PREVENT, $studentrole->id, $context->id); | |
1817 | } | |
1818 | foreach ($teacherroles as $teacherrole) { | |
1819 | assign_capability('mod/data:writeentry', CAP_ALLOW, $teacherrole->id, $context->id); | |
1820 | } | |
1821 | break; | |
1822 | case 3: | |
1823 | foreach ($studentroles as $studentrole) { | |
1824 | assign_capability('mod/data:writeentry', CAP_ALLOW, $studentrole->id, $context->id); | |
1825 | } | |
1826 | foreach ($teacherroles as $teacherrole) { | |
1827 | assign_capability('mod/data:writeentry', CAP_ALLOW, $teacherrole->id, $context->id); | |
1828 | } | |
1829 | break; | |
1830 | } | |
6403e679 | 1831 | |
7f258664 | 1832 | // $data->assessed: |
1833 | // 2 - Only teachers can rate posts | |
1834 | // 1 - Everyone can rate posts | |
1835 | // 0 - No one can rate posts | |
1836 | switch ($data->assessed) { | |
1837 | case 0: | |
1838 | foreach ($studentroles as $studentrole) { | |
1839 | assign_capability('mod/data:rate', CAP_PREVENT, $studentrole->id, $context->id); | |
1840 | } | |
1841 | foreach ($teacherroles as $teacherrole) { | |
1842 | assign_capability('mod/data:rate', CAP_PREVENT, $teacherrole->id, $context->id); | |
1843 | } | |
1844 | break; | |
1845 | case 1: | |
1846 | foreach ($studentroles as $studentrole) { | |
1847 | assign_capability('mod/data:rate', CAP_ALLOW, $studentrole->id, $context->id); | |
1848 | } | |
1849 | foreach ($teacherroles as $teacherrole) { | |
1850 | assign_capability('mod/data:rate', CAP_ALLOW, $teacherrole->id, $context->id); | |
1851 | } | |
1852 | break; | |
1853 | case 2: | |
1854 | foreach ($studentroles as $studentrole) { | |
1855 | assign_capability('mod/data:rate', CAP_PREVENT, $studentrole->id, $context->id); | |
1856 | } | |
1857 | foreach ($teacherroles as $teacherrole) { | |
1858 | assign_capability('mod/data:rate', CAP_ALLOW, $teacherrole->id, $context->id); | |
1859 | } | |
1860 | break; | |
1861 | } | |
6403e679 | 1862 | |
7f258664 | 1863 | // $data->assesspublic: |
1864 | // 0 - Students can only see their own ratings | |
1865 | // 1 - Students can see everyone's ratings | |
1866 | switch ($data->assesspublic) { | |
1867 | case 0: | |
1868 | foreach ($studentroles as $studentrole) { | |
1869 | assign_capability('mod/data:viewrating', CAP_PREVENT, $studentrole->id, $context->id); | |
1870 | } | |
1871 | foreach ($teacherroles as $teacherrole) { | |
1872 | assign_capability('mod/data:viewrating', CAP_ALLOW, $teacherrole->id, $context->id); | |
1873 | } | |
1874 | break; | |
1875 | case 1: | |
1876 | foreach ($studentroles as $studentrole) { | |
1877 | assign_capability('mod/data:viewrating', CAP_ALLOW, $studentrole->id, $context->id); | |
1878 | } | |
1879 | foreach ($teacherroles as $teacherrole) { | |
1880 | assign_capability('mod/data:viewrating', CAP_ALLOW, $teacherrole->id, $context->id); | |
1881 | } | |
1882 | break; | |
1883 | } | |
1884 | ||
1885 | if (empty($cm)) { | |
9c00b5d7 | 1886 | $cm = $DB->get_record('course_modules', array('id'=>$cmid)); |
7f258664 | 1887 | } |
6403e679 | 1888 | |
7f258664 | 1889 | switch ($cm->groupmode) { |
055f2185 | 1890 | case NOGROUPS: |
7f258664 | 1891 | break; |
055f2185 | 1892 | case SEPARATEGROUPS: |
7f258664 | 1893 | foreach ($studentroles as $studentrole) { |
1894 | assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $studentrole->id, $context->id); | |
1895 | } | |
1896 | foreach ($teacherroles as $teacherrole) { | |
1897 | assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $teacherrole->id, $context->id); | |
1898 | } | |
1899 | break; | |
055f2185 | 1900 | case VISIBLEGROUPS: |
7f258664 | 1901 | foreach ($studentroles as $studentrole) { |
1902 | assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $studentrole->id, $context->id); | |
1903 | } | |
1904 | foreach ($teacherroles as $teacherrole) { | |
1905 | assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $teacherrole->id, $context->id); | |
1906 | } | |
1907 | break; | |
1908 | } | |
1909 | return true; | |
1910 | } | |
1911 | ||
4636bf83 | 1912 | /** |
8303eb84 | 1913 | * Returns the best name to show for a preset |
4636bf83 | 1914 | * |
1915 | * @param string $shortname | |
1916 | * @param string $path | |
1917 | * @return string | |
8303eb84 | 1918 | */ |
1919 | function data_preset_name($shortname, $path) { | |
1920 | ||
668fc89a | 1921 | // We are looking inside the preset itself as a first choice, but also in normal data directory |
30d76014 | 1922 | $string = get_string('modulename', 'datapreset_'.$shortname); |
8303eb84 | 1923 | |
1924 | if (substr($string, 0, 1) == '[') { | |
1925 | return $shortname; | |
1926 | } else { | |
1927 | return $string; | |
1928 | } | |
1929 | } | |
1930 | ||
4636bf83 | 1931 | /** |
8aff1574 | 1932 | * Returns an array of all the available presets. |
4636bf83 | 1933 | * |
4636bf83 | 1934 | * @return array |
8303eb84 | 1935 | */ |
1936 | function data_get_available_presets($context) { | |
1937 | global $CFG, $USER; | |
b572ce19 | 1938 | |
8303eb84 | 1939 | $presets = array(); |
b572ce19 | 1940 | |
8aff1574 | 1941 | // First load the ratings sub plugins that exist within the modules preset dir |
8303eb84 | 1942 | if ($dirs = get_list_of_plugins('mod/data/preset')) { |
1943 | foreach ($dirs as $dir) { | |
1944 | $fulldir = $CFG->dirroot.'/mod/data/preset/'.$dir; | |
8303eb84 | 1945 | if (is_directory_a_preset($fulldir)) { |
39790bd8 | 1946 | $preset = new stdClass(); |
8303eb84 | 1947 | $preset->path = $fulldir; |
1948 | $preset->userid = 0; | |
1949 | $preset->shortname = $dir; | |
1950 | $preset->name = data_preset_name($dir, $fulldir); | |
1951 | if (file_exists($fulldir.'/screenshot.jpg')) { | |
1952 | $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.jpg'; | |
1953 | } else if (file_exists($fulldir.'/screenshot.png')) { | |
1954 | $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.png'; | |
1955 | } else if (file_exists($fulldir.'/screenshot.gif')) { | |
1956 | $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.gif'; | |
1957 | } | |
1958 | $presets[] = $preset; | |
1959 | } | |
1960 | } | |
1961 | } | |
8aff1574 SH |
1962 | // Now add to that the site presets that people have saved |
1963 | $presets = data_get_available_site_presets($context, $presets); | |
1964 | return $presets; | |
1965 | } | |
8303eb84 | 1966 | |
8aff1574 SH |
1967 | /** |
1968 | * Gets an array of all of the presets that users have saved to the site. | |
1969 | * | |
1970 | * @param stdClass $context The context that we are looking from. | |
1971 | * @param array $presets | |
1972 | * @return array An array of presets | |
1973 | */ | |
1974 | function data_get_available_site_presets($context, array $presets=array()) { | |
810860d2 PS |
1975 | global $USER; |
1976 | ||
8aff1574 SH |
1977 | $fs = get_file_storage(); |
1978 | $files = $fs->get_area_files(DATA_PRESET_CONTEXT, DATA_PRESET_COMPONENT, DATA_PRESET_FILEAREA); | |
1979 | $canviewall = has_capability('mod/data:viewalluserpresets', $context); | |
1980 | if (empty($files)) { | |
1981 | return $presets; | |
1982 | } | |
1983 | foreach ($files as $file) { | |
1984 | if (($file->is_directory() && $file->get_filepath()=='/') || !$file->is_directory() || (!$canviewall && $file->get_userid() != $USER->id)) { | |
1985 | continue; | |
1986 | } | |
1987 | $preset = new stdClass; | |
1988 | $preset->path = $file->get_filepath(); | |
1989 | $preset->name = trim($preset->path, '/'); | |
1990 | $preset->shortname = $preset->name; | |
1991 | $preset->userid = $file->get_userid(); | |
1992 | $preset->id = $file->get_id(); | |
1993 | $preset->storedfile = $file; | |
1994 | $presets[] = $preset; | |
1995 | } | |
1996 | return $presets; | |
1997 | } | |
1998 | ||
1999 | /** | |
2000 | * Deletes a saved preset. | |
2001 | * | |
2002 | * @param string $name | |
2003 | * @return bool | |
2004 | */ | |
2005 | function data_delete_site_preset($name) { | |
2006 | $fs = get_file_storage(); | |
2007 | ||
2008 | $files = $fs->get_directory_files(DATA_PRESET_CONTEXT, DATA_PRESET_COMPONENT, DATA_PRESET_FILEAREA, 0, '/'.$name.'/'); | |
2009 | if (!empty($files)) { | |
2010 | foreach ($files as $file) { | |
2011 | $file->delete(); | |
8303eb84 | 2012 | } |
2013 | } | |
b572ce19 | 2014 | |
8aff1574 SH |
2015 | $dir = $fs->get_file(DATA_PRESET_CONTEXT, DATA_PRESET_COMPONENT, DATA_PRESET_FILEAREA, 0, '/'.$name.'/', '.'); |
2016 | if (!empty($dir)) { | |
2017 | $dir->delete(); | |
2018 | } | |
2019 | return true; | |
8303eb84 | 2020 | } |
2021 | ||
4636bf83 | 2022 | /** |
8aff1574 SH |
2023 | * Prints the heads for a page |
2024 | * | |
2025 | * @param stdClass $course | |
2026 | * @param stdClass $cm | |
2027 | * @param stdClass $data | |
4636bf83 | 2028 | * @param string $currenttab |
2029 | */ | |
8303eb84 | 2030 | function data_print_header($course, $cm, $data, $currenttab='') { |
b572ce19 | 2031 | |
b0ff558c | 2032 | global $CFG, $displaynoticegood, $displaynoticebad, $OUTPUT, $PAGE; |
b572ce19 | 2033 | |
b0ff558c | 2034 | $PAGE->set_title($data->name); |
b0ff558c | 2035 | echo $OUTPUT->header(); |
b2dc6880 | 2036 | echo $OUTPUT->heading(format_string($data->name)); |
8303eb84 | 2037 | |
b8b554ac | 2038 | // Groups needed for Add entry tab |
055f2185 | 2039 | $currentgroup = groups_get_activity_group($cm); |
5d59cbe9 | 2040 | $groupmode = groups_get_activity_groupmode($cm); |
b572ce19 | 2041 | |
668fc89a | 2042 | // Print the tabs |
b572ce19 | 2043 | |
8303eb84 | 2044 | if ($currenttab) { |
138e480e | 2045 | include('tabs.php'); |
8303eb84 | 2046 | } |
b572ce19 | 2047 | |
b8b554ac | 2048 | // Print any notices |
b572ce19 | 2049 | |
8303eb84 | 2050 | if (!empty($displaynoticegood)) { |
4102b449 | 2051 | echo $OUTPUT->notification($displaynoticegood, 'notifysuccess'); // good (usually green) |
8303eb84 | 2052 | } else if (!empty($displaynoticebad)) { |
4102b449 | 2053 | echo $OUTPUT->notification($displaynoticebad); // bad (usuually red) |
8303eb84 | 2054 | } |
2055 | } | |
7f258664 | 2056 | |
4636bf83 | 2057 | /** |
0393a8b7 PS |
2058 | * Can user add more entries? |
2059 | * | |
4636bf83 | 2060 | * @param object $data |
2061 | * @param mixed $currentgroup | |
2062 | * @param int $groupmode | |
0393a8b7 | 2063 | * @param stdClass $context |
4636bf83 | 2064 | * @return bool |
2065 | */ | |
e4e96115 | 2066 | function data_user_can_add_entry($data, $currentgroup, $groupmode, $context = null) { |
cca1547e | 2067 | global $USER; |
b572ce19 | 2068 | |
e4e96115 | 2069 | if (empty($context)) { |
0393a8b7 | 2070 | $cm = get_coursemodule_from_instance('data', $data->id, 0, false, MUST_EXIST); |
e4e96115 RW |
2071 | $context = get_context_instance(CONTEXT_MODULE, $cm->id); |
2072 | } | |
2073 | ||
0393a8b7 PS |
2074 | if (has_capability('mod/data:manageentries', $context)) { |
2075 | // no entry limits apply if user can manage | |
e4e96115 | 2076 | |
0393a8b7 | 2077 | } else if (!has_capability('mod/data:writeentry', $context)) { |
e4e96115 | 2078 | return false; |
b572ce19 | 2079 | |
0393a8b7 | 2080 | } else if (data_atmaxentries($data)) { |
cca1547e | 2081 | return false; |
2082 | } | |
b572ce19 | 2083 | |
2742ffe7 AD |
2084 | //if in the view only time window |
2085 | $now = time(); | |
2086 | if ($now>$data->timeviewfrom && $now<$data->timeviewto) { | |
2087 | return false; | |
2088 | } | |
2089 | ||
04366d79 | 2090 | if (!$groupmode or has_capability('moodle/site:accessallgroups', $context)) { |
2091 | return true; | |
2092 | } | |
2093 | ||
cca1547e | 2094 | if ($currentgroup) { |
2c386f82 | 2095 | return groups_is_member($currentgroup); |
cca1547e | 2096 | } else { |
2097 | //else it might be group 0 in visible mode | |
2098 | if ($groupmode == VISIBLEGROUPS){ | |
cca1547e | 2099 | return true; |
04366d79 | 2100 | } else { |
2101 | return false; | |
cca1547e | 2102 | } |
2103 | } | |
2104 | } | |
2105 | ||
50194545 | 2106 | |
4636bf83 | 2107 | /** |
2108 | * @return bool | |
2109 | */ | |
50194545 | 2110 | function is_directory_a_preset($directory) { |
2111 | $directory = rtrim($directory, '/\\') . '/'; | |
2dc6be3f | 2112 | $status = file_exists($directory.'singletemplate.html') && |
2113 | file_exists($directory.'listtemplate.html') && | |
2114 | file_exists($directory.'listtemplateheader.html') && | |
2115 | file_exists($directory.'listtemplatefooter.html') && | |
2116 | file_exists($directory.'addtemplate.html') && | |
2117 | file_exists($directory.'rsstemplate.html') && | |
2118 | file_exists($directory.'rsstitletemplate.html') && | |
2119 | file_exists($directory.'csstemplate.css') && | |
2120 | file_exists($directory.'jstemplate.js') && | |
2121 | file_exists($directory.'preset.xml'); | |
b572ce19 | 2122 | |
2dc6be3f | 2123 | return $status; |
50194545 | 2124 | } |
2125 | ||
4636bf83 | 2126 | /** |
cba87c36 | 2127 | * Abstract class used for data preset importers |
4636bf83 | 2128 | */ |
cba87c36 | 2129 | abstract class data_preset_importer { |
b572ce19 | 2130 | |
cba87c36 SH |
2131 | protected $course; |
2132 | protected $cm; | |
2133 | protected $module; | |
2134 | protected $directory; | |
50194545 | 2135 | |
4636bf83 | 2136 | /** |
cba87c36 SH |
2137 | * Constructor |
2138 | * | |
2139 | * @param stdClass $course | |
2140 | * @param stdClass $cm | |
2141 | * @param stdClass $module | |
2142 | * @param string $directory | |
4636bf83 | 2143 | */ |
cba87c36 | 2144 | public function __construct($course, $cm, $module, $directory) { |
50194545 | 2145 | $this->course = $course; |
2146 | $this->cm = $cm; | |
cba87c36 SH |
2147 | $this->module = $module; |
2148 | $this->directory = $directory; | |
2149 | } | |
2150 | ||
2151 | /** | |
2152 | * Returns the name of the directory the preset is located in | |
2153 | * @return string | |
2154 | */ | |
2155 | public function get_directory() { | |
2156 | return basename($this->directory); | |
50194545 | 2157 | } |
263819c8 AD |
2158 | |
2159 | /** | |
2160 | * Retreive the contents of a file. That file may either be in a conventional directory of the Moodle file storage | |
2161 | * @param file_storage $filestorage. should be null if using a conventional directory | |
2162 | * @param stored_file $fileobj the directory to look in. null if using a conventional directory | |
2163 | * @param string $dir the directory to look in. null if using the Moodle file storage | |
2164 | * @param string $filename the name of the file we want | |
2165 | * @return string the contents of the file | |
2166 | */ | |
2167 | public function data_preset_get_file_contents(&$filestorage, &$fileobj, $dir, $filename) { | |
2168 | if(empty($filestorage) || empty($fileobj)) { | |
2169 | if (substr($dir, -1)!='/') { | |
2170 | $dir .= '/'; | |
2171 | } | |
2172 | return file_get_contents($dir.$filename); | |
2173 | } else { | |
2174 | $file = $filestorage->get_file(DATA_PRESET_CONTEXT, DATA_PRESET_COMPONENT, DATA_PRESET_FILEAREA, 0, $fileobj->get_filepath(), $filename); | |
2175 | return $file->get_content(); | |
2176 | } | |
2177 | ||
2178 | } | |
4636bf83 | 2179 | /** |
cba87c36 SH |
2180 | * Gets the preset settings |
2181 | * @global moodle_database $DB | |
2182 | * @return stdClass | |
4636bf83 | 2183 | */ |
cba87c36 SH |
2184 | public function get_preset_settings() { |
2185 | global $DB; | |
50194545 | 2186 | |
263819c8 | 2187 | $fs = $fileobj = null; |
cba87c36 | 2188 | if (!is_directory_a_preset($this->directory)) { |
263819c8 | 2189 | //maybe the user requested a preset stored in the Moodle file storage |
375053ed | 2190 | |
263819c8 AD |
2191 | $fs = get_file_storage(); |
2192 | $files = $fs->get_area_files(DATA_PRESET_CONTEXT, DATA_PRESET_COMPONENT, DATA_PRESET_FILEAREA); | |
2193 | ||
720f37fd AD |
2194 | //preset name to find will be the final element of the directory |
2195 | $presettofind = end(explode('/',$this->directory)); | |
2196 | ||
2197 | //now go through the available files available and see if we can find it | |
263819c8 AD |
2198 | foreach ($files as $file) { |
2199 | if (($file->is_directory() && $file->get_filepath()=='/') || !$file->is_directory()) { | |
2200 | continue; | |
2201 | } | |
2202 | $presetname = trim($file->get_filepath(), '/'); | |
720f37fd | 2203 | if ($presetname==$presettofind) { |
263819c8 AD |
2204 | $this->directory = $presetname; |
2205 | $fileobj = $file; | |
2206 | } | |
2207 | } | |
2208 | ||
2209 | if (empty($fileobj)) { | |
2210 | print_error('invalidpreset', 'data', '', $this->directory); | |
2211 | } | |
50194545 | 2212 | } |
2213 | ||
cba87c36 SH |
2214 | $allowed_settings = array( |
2215 | 'intro', | |
2216 | 'comments', | |
2217 | 'requiredentries', | |
2218 | 'requiredentriestoview', | |
2219 | 'maxentries', | |
2220 | 'rssarticles', | |
2221 | 'approval', | |
2222 | 'defaultsortdir', | |
2223 | 'defaultsort'); | |
2224 | ||
2225 | $result = new stdClass; | |
2226 | $result->settings = new stdClass; | |
2227 | $result->importfields = array(); | |
2228 | $result->currentfields = $DB->get_records('data_fields', array('dataid'=>$this->module->id)); | |
2229 | if (!$result->currentfields) { | |
2230 | $result->currentfields = array(); | |
2231 | } | |
2232 | ||
2233 | ||
50194545 | 2234 | /* Grab XML */ |
263819c8 | 2235 | $presetxml = $this->data_preset_get_file_contents($fs, $fileobj, $this->directory,'preset.xml'); |
143c1eb9 | 2236 | $parsedxml = xmlize($presetxml, 0); |
50194545 | 2237 | |
2238 | /* First, do settings. Put in user friendly array. */ | |
2239 | $settingsarray = $parsedxml['preset']['#']['settings'][0]['#']; | |
cba87c36 | 2240 | $result->settings = new StdClass(); |
50194545 | 2241 | foreach ($settingsarray as $setting => $value) { |
cba87c36 | 2242 | if (!is_array($value) || !in_array($setting, $allowed_settings)) { |
eaa30818 | 2243 | // unsupported setting |
2244 | continue; | |
2245 | } | |
cba87c36 | 2246 | $result->settings->$setting = $value[0]['#']; |
50194545 | 2247 | } |
2248 | ||
2249 | /* Now work out fields to user friendly array */ | |
2250 | $fieldsarray = $parsedxml['preset']['#']['field']; | |
50194545 | 2251 | foreach ($fieldsarray as $field) { |
02007b01 | 2252 | if (!is_array($field)) { |
2253 | continue; | |
2254 | } | |
50194545 | 2255 | $f = new StdClass(); |
2256 | foreach ($field['#'] as $param => $value) { | |
02007b01 | 2257 | if (!is_array($value)) { |
2258 | continue; | |
2259 | } | |
9c00b5d7 | 2260 | $f->$param = $value[0]['#']; |
50194545 | 2261 | } |
cba87c36 | 2262 | $f->dataid = $this->module->id; |
50194545 | 2263 | $f->type = clean_param($f->type, PARAM_ALPHA); |
cba87c36 | 2264 | $result->importfields[] = $f; |
50194545 | 2265 | } |
50194545 | 2266 | /* Now add the HTML templates to the settings array so we can update d */ |
263819c8 AD |
2267 | $result->settings->singletemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"singletemplate.html"); |
2268 | $result->settings->listtemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"listtemplate.html"); | |
2269 | $result->settings->listtemplateheader = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"listtemplateheader.html"); | |
2270 | $result->settings->listtemplatefooter = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"listtemplatefooter.html"); | |
2271 | $result->settings->addtemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"addtemplate.html"); | |
2272 | $result->settings->rsstemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"rsstemplate.html"); | |
2273 | $result->settings->rsstitletemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"rsstitletemplate.html"); | |
2274 | $result->settings->csstemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"csstemplate.css"); | |
2275 | $result->settings->jstemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"jstemplate.js"); | |
50194545 | 2276 | |
2dc6be3f | 2277 | //optional |
cba87c36 | 2278 | if (file_exists($this->directory."/asearchtemplate.html")) { |
263819c8 | 2279 | $result->settings->asearchtemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"asearchtemplate.html"); |
2dc6be3f | 2280 | } else { |
cba87c36 | 2281 | $result->settings->asearchtemplate = NULL; |
50194545 | 2282 | } |
cba87c36 | 2283 | $result->settings->instance = $this->module->id; |
b572ce19 | 2284 | |
cba87c36 | 2285 | return $result; |
50194545 | 2286 | } |
2287 | ||
4636bf83 | 2288 | /** |
cba87c36 | 2289 | * Import the preset into the given database module |
4636bf83 | 2290 | * @return bool |
2291 | */ | |
cba87c36 | 2292 | function import($overwritesettings) { |
fe9d5f7e | 2293 | global $DB, $CFG; |
50194545 | 2294 | |
cba87c36 SH |
2295 | $params = $this->get_preset_settings(); |
2296 | $settings = $params->settings; | |
2297 | $newfields = $params->importfields; | |
2298 | $currentfields = $params->currentfields; | |
50194545 | 2299 | $preservedfields = array(); |
b572ce19 | 2300 | |
50194545 | 2301 | /* Maps fields and makes new ones */ |
2302 | if (!empty($newfields)) { | |
2303 | /* We require an injective mapping, and need to know what to protect */ | |
2304 | foreach ($newfields as $nid => $newfield) { | |
2305 | $cid = optional_param("field_$nid", -1, PARAM_INT); | |
cba87c36 SH |
2306 | if ($cid == -1) { |
2307 | continue; | |
2308 | } | |
29c1bb15 | 2309 | if (array_key_exists($cid, $preservedfields)){ |
2310 | print_error('notinjectivemap', 'data'); | |
8429163d | 2311 | } |
50194545 | 2312 | else $preservedfields[$cid] = true; |
2313 | } | |
b572ce19 | 2314 | |
50194545 | 2315 | foreach ($newfields as $nid => $newfield) { |
2316 | $cid = optional_param("field_$nid", -1, PARAM_INT); | |
b572ce19 | 2317 | |
50194545 | 2318 | /* A mapping. Just need to change field params. Data kept. */ |
2319 | if ($cid != -1 and isset($currentfields[$cid])) { | |
cba87c36 | 2320 | $fieldobject = data_get_field_from_id($currentfields[$cid]->id, $this->module); |
50194545 | 2321 | foreach ($newfield as $param => $value) { |
2322 | if ($param != "id") { | |
2323 | $fieldobject->field->$param = $value; | |
2324 | } | |
2325 | } | |
2326 | unset($fieldobject->field->similarfield); | |
2327 | $fieldobject->update_field(); | |
2328 | unset($fieldobject); | |
cba87c36 SH |
2329 | } else { |
2330 | /* Make a new field */ | |
50194545 | 2331 | include_once("field/$newfield->type/field.class.php"); |
b572ce19 | 2332 | |
50194545 | 2333 | if (!isset($newfield->description)) { |
2334 | $newfield->description = ''; | |
2335 | } | |
2336 | $classname = 'data_field_'.$newfield->type; | |
cba87c36 | 2337 | $fieldclass = new $classname($newfield, $this->module); |
50194545 | 2338 | $fieldclass->insert_field(); |
2339 | unset($fieldclass); | |
2340 | } | |
2341 | } | |
2342 | } | |
2343 | ||
2344 | /* Get rid of all old unused data */ | |
2345 | if (!empty($preservedfields)) { | |
2346 | foreach ($currentfields as $cid => $currentfield) { | |
2347 | if (!array_key_exists($cid, $preservedfields)) { | |
2348 | /* Data not used anymore so wipe! */ | |
2349 | print "Deleting field $currentfield->name<br />"; | |
b572ce19 | 2350 | |
50194545 | 2351 | $id = $currentfield->id; |
2352 | //Why delete existing data records and related comments/ratings?? | |
9c00b5d7 | 2353 | $DB->delete_records('data_content', array('fieldid'=>$id)); |
2354 | $DB->delete_records('data_fields', array('id'=>$id)); | |
50194545 | 2355 | } |
2356 | } | |
2357 | } | |
2358 | ||
cba87c36 | 2359 | // handle special settings here |
eaa30818 | 2360 | if (!empty($settings->defaultsort)) { |
2361 | if (is_numeric($settings->defaultsort)) { | |
668fc89a | 2362 | // old broken value |
eaa30818 | 2363 | $settings->defaultsort = 0; |
2364 | } else { | |
cba87c36 | 2365 | $settings->defaultsort = (int)$DB->get_field('data_fields', 'id', array('dataid'=>$this->module->id, 'name'=>$settings->defaultsort)); |
eaa30818 | 2366 | } |
2367 | } else { | |
2368 | $settings->defaultsort = 0; | |
2369 | } | |
2370 | ||
2371 | // do we want to overwrite all current database settings? | |
8528bf26 | 2372 | if ($overwritesettings) { |
eaa30818 | 2373 | // all supported settings |
8528bf26 | 2374 | $overwrite = array_keys((array)$settings); |
2375 | } else { | |
eaa30818 | 2376 | // only templates and sorting |
8528bf26 | 2377 | $overwrite = array('singletemplate', 'listtemplate', 'listtemplateheader', 'listtemplatefooter', |
2378 | 'addtemplate', 'rsstemplate', 'rsstitletemplate', 'csstemplate', 'jstemplate', | |
eaa30818 | 2379 | 'asearchtemplate', 'defaultsortdir', 'defaultsort'); |
8528bf26 | 2380 | } |
2381 | ||
eaa30818 | 2382 | // now overwrite current data settings |
cba87c36 | 2383 | foreach ($this->module as $prop=>$unused) { |
8528bf26 | 2384 | if (in_array($prop, $overwrite)) { |
cba87c36 | 2385 | $this->module->$prop = $settings->$prop; |
13534ef7 ML |
2386 | } |
2387 | } | |
db0f2a44 | 2388 | |
cba87c36 | 2389 | data_update_instance($this->module); |
50194545 | 2390 | |
cba87c36 SH |
2391 | return $this->cleanup(); |
2392 | } | |
b572ce19 | 2393 | |
cba87c36 SH |
2394 | /** |
2395 | * Any clean up routines should go here | |
2396 | * @return bool | |
2397 | */ | |
2398 | public function cleanup() { | |
50194545 | 2399 | return true; |
2400 | } | |
2401 | } | |
2402 | ||
cba87c36 SH |
2403 | /** |
2404 | * Data preset importer for uploaded presets | |
2405 | */ | |
2406 | class data_preset_upload_importer extends data_preset_importer { | |
2407 | public function __construct($course, $cm, $module, $filepath) { | |
2408 | global $USER; | |
2409 | if (is_file($filepath)) { | |
2410 | $fp = get_file_packer(); | |
2411 | if ($fp->extract_to_pathname($filepath, $filepath.'_extracted')) { | |
2412 | fulldelete($filepath); | |
2413 | } | |
2414 | $filepath .= '_extracted'; | |
2415 | } | |
2416 | parent::__construct($course, $cm, $module, $filepath); | |
2417 | } | |
2418 | public function cleanup() { | |
2419 | return fulldelete($this->directory); | |
2420 | } | |
2421 | } | |
2422 | ||
2423 | /** | |
2424 | * Data preset importer for existing presets | |
2425 | */ | |
2426 | class data_preset_existing_importer extends data_preset_importer { | |
2427 | protected $userid; | |
2428 | public function __construct($course, $cm, $module, $fullname) { | |
2429 | global $USER; | |
2430 | list($userid, $shortname) = explode('/', $fullname, 2); | |
2431 | $context = get_context_instance(CONTEXT_MODULE, $cm->id); | |
2432 | if ($userid && ($userid != $USER->id) && !has_capability('mod/data:manageuserpresets', $context) && !has_capability('mod/data:viewalluserpresets', $context)) { | |
2433 | throw new coding_exception('Invalid preset provided'); | |
2434 | } | |
2435 | ||
2436 | $this->userid = $userid; | |
2437 | $filepath = data_preset_path($course, $userid, $shortname); | |
2438 | parent::__construct($course, $cm, $module, $filepath); | |
2439 | } | |
2440 | public function get_userid() { | |
2441 | return $this->userid; | |
2442 | } | |
2443 | } | |
2444 | ||
4636bf83 | 2445 | /** |
2446 | * @global object | |
2447 | * @global object | |
2448 | * @param object $course | |
2449 | * @param int $userid | |
2450 | * @param string $shortname | |
2451 | * @return string | |
2452 | */ | |
50194545 | 2453 | function data_preset_path($course, $userid, $shortname) { |
2454 | global $USER, $CFG; | |
b572ce19 | 2455 | |
50194545 | 2456 | $context = get_context_instance(CONTEXT_COURSE, $course->id); |
b572ce19 | 2457 | |
50194545 | 2458 | $userid = (int)$userid; |
b572ce19 | 2459 | |
263819c8 | 2460 | $path = null; |
50194545 | 2461 | if ($userid > 0 && ($userid == $USER->id || has_capability('mod/data:viewalluserpresets', $context))) { |
263819c8 | 2462 | $path = $CFG->dataroot.'/data/preset/'.$userid.'/'.$shortname; |
50194545 | 2463 | } else if ($userid == 0) { |
263819c8 | 2464 | $path = $CFG->dirroot.'/mod/data/preset/'.$shortname; |
50194545 | 2465 | } else if ($userid < 0) { |
263819c8 | 2466 | $path = $CFG->dataroot.'/temp/data/'.-$userid.'/'.$shortname; |
50194545 | 2467 | } |
b572ce19 | 2468 | |
263819c8 | 2469 | return $path; |
50194545 | 2470 | } |
0b5a80a1 | 2471 | |
2472 | /** | |
2473 | * Implementation of the function for printing the form elements that control | |
2474 | * whether the course reset functionality affects the data. | |
4636bf83 | 2475 | * |
0b5a80a1 | 2476 | * @param $mform form passed by reference |
2477 | */ | |
2478 | function data_reset_course_form_definition(&$mform) { | |
2479 | $mform->addElement('header', 'dataheader', get_string('modulenameplural', 'data')); | |
2480 | $mform->addElement('checkbox', 'reset_data', get_string('deleteallentries','data')); | |
2481 | ||
2482 | $mform->addElement('checkbox', 'reset_data_notenrolled', get_string('deletenotenrolled', 'data')); | |
2483 | $mform->disabledIf('reset_data_notenrolled', 'reset_data', 'checked'); | |
2484 | ||
2485 | $mform->addElement('checkbox', 'reset_data_ratings', get_string('deleteallratings')); | |
2486 | $mform->disabledIf('reset_data_ratings', 'reset_data', 'checked'); | |
2487 | ||
2488 | $mform->addElement('checkbox', 'reset_data_comments', get_string('deleteallcomments')); | |
2489 | $mform->disabledIf('reset_data_comments', 'reset_data', 'checked'); | |
2490 | } | |
2491 | ||
2492 | /** | |
2493 | * Course reset form defaults. | |
4636bf83 | 2494 | * @return array |
0b5a80a1 | 2495 | */ |
2496 | function data_reset_course_form_defaults($course) { | |
2497 | return array('reset_data'=>0, 'reset_data_ratings'=>1, 'reset_data_comments'=>1, 'reset_data_notenrolled'=>0); | |
2498 | } | |
2499 | ||
2500 | /** | |
2501 | * Removes all grades from gradebook | |
4636bf83 | 2502 | * |
2503 | * @global object | |
2504 | * @global object | |
0b5a80a1 | 2505 | * @param int $courseid |
4636bf83 | 2506 | * @param string $type optional type |
0b5a80a1 | 2507 | */ |
2508 | function data_reset_gradebook($courseid, $type='') { | |
9c00b5d7 | 2509 | global $CFG, $DB; |
0b5a80a1 | 2510 | |
2511 | $sql = "SELECT d.*, cm.idnumber as cmidnumber, d.course as courseid | |
9c00b5d7 | 2512 | FROM {data} d, {course_modules} cm, {modules} m |
2513 | WHERE m.name='data' AND m.id=cm.module AND cm.instance=d.id AND d.course=?"; | |
0b5a80a1 | 2514 | |
9c00b5d7 | 2515 | if ($datas = $DB->get_records_sql($sql, array($courseid))) { |
0b5a80a1 | 2516 | foreach ($datas as $data) { |
2517 | data_grade_item_update($data, 'reset'); | |
2518 | } | |
2519 | } | |
2520 | } | |
2521 | ||
2522 | /** | |
72d2982e | 2523 | * Actual implementation of the reset course functionality, delete all the |
0b5a80a1 | 2524 | * data responses for course $data->courseid. |
4636bf83 | 2525 | * |
2526 | * @global object | |
2527 | * @global object | |
2528 | * @param object $data the data submitted from the reset course. | |
0b5a80a1 | 2529 | * @return array status array |
2530 | */ | |
2531 | function data_reset_userdata($data) { | |
9c00b5d7 | 2532 | global $CFG, $DB; |
0b5a80a1 | 2533 | require_once($CFG->libdir.'/filelib.php'); |
d251b259 | 2534 | require_once($CFG->dirroot.'/rating/lib.php'); |
b572ce19 | 2535 | |
0b5a80a1 | 2536 | $componentstr = get_string('modulenameplural', 'data'); |
2537 | $status = array(); | |
b572ce19 | 2538 | |
0b5a80a1 | 2539 | $allrecordssql = "SELECT r.id |
9c00b5d7 | 2540 | FROM {data_records} r |
2541 | INNER JOIN {data} d ON r.dataid = d.id | |
2542 | WHERE d.course = ?"; | |
0b5a80a1 | 2543 | |
2544 | $alldatassql = "SELECT d.id | |
9c00b5d7 | 2545 | FROM {data} d |
2546 | WHERE d.course=?"; | |
0b5a80a1 | 2547 | |
d251b259 | 2548 | $rm = new rating_manager(); |
2b04c41c SH |
2549 | $ratingdeloptions = new stdClass; |
2550 | $ratingdeloptions->component = 'mod_data'; | |
2551 | $ratingdeloptions->ratingarea = 'entry'; | |
d251b259 | 2552 | |
0b5a80a1 | 2553 | // delete entries if requested |
2554 | if (!empty($data->reset_data)) { | |
e998effa | 2555 | $DB->delete_records_select('comments', "itemid IN ($allrecordssql) AND commentarea='database_entry'", array($data->courseid)); |
9c00b5d7 | 2556 | $DB->delete_records_select('data_content', "recordid IN ($allrecordssql)", array($data->courseid)); |
2557 | $DB->delete_records_select('data_records', "dataid IN ($alldatassql)", array($data->courseid)); | |
0b5a80a1 | 2558 | |
9c00b5d7 | 2559 | if ($datas = $DB->get_records_sql($alldatassql, array($data->courseid))) { |
0b5a80a1 | 2560 | foreach ($datas as $dataid=>$unused) { |
2561 | fulldelete("$CFG->dataroot/$data->courseid/moddata/data/$dataid"); | |
d251b259 AD |
2562 | |
2563 | if (!$cm = get_coursemodule_from_instance('data', $dataid)) { | |
2564 | continue; | |
2565 | } | |
2566 | $datacontext = get_context_instance(CONTEXT_MODULE, $cm->id); | |
2567 | ||
2568 | $ratingdeloptions->contextid = $datacontext->id; | |
2569 | $rm->delete_ratings($ratingdeloptions); | |
0b5a80a1 | 2570 | } |
2571 | } | |
b572ce19 | 2572 | |
0b5a80a1 | 2573 | if (empty($data->reset_gradebook_grades)) { |
2574 | // remove all grades from gradebook | |
2575 | data_reset_gradebook($data->courseid); | |
2576 | } | |
2577 | $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallentries', 'data'), 'error'=>false); | |
2578 | } | |
2579 | ||
2580 | // remove entries by users not enrolled into course | |
2581 | if (!empty($data->reset_data_notenrolled)) { | |
2582 | $recordssql = "SELECT r.id, r.userid, r.dataid, u.id AS userexists, u.deleted AS userdeleted | |
9c00b5d7 | 2583 | FROM {data_records} r |
2584 | JOIN {data} d ON r.dataid = d.id | |
2585 | LEFT JOIN {user} u ON r.userid = u.id | |
2586 | WHERE d.course = ? AND r.userid > 0"; | |
0b5a80a1 | 2587 | |
2588 | $course_context = get_context_instance(CONTEXT_COURSE, $data->courseid); | |
2589 | $notenrolled = array(); | |
2590 | $fields = array(); | |
6b1b1d03 EL |
2591 | $rs = $DB->get_recordset_sql($recordssql, array($data->courseid)); |
2592 | foreach ($rs as $record) { | |
2593 | if (array_key_exists($record->userid, $notenrolled) or !$record->userexists or $record->userdeleted | |
2594 | or !is_enrolled($course_context, $record->userid)) { | |
2595 | //delete ratings | |
2596 | if (!$cm = get_coursemodule_from_instance('data', $record->dataid)) { | |
2597 | continue; | |
2598 | } | |
2599 | $datacontext = get_context_instance(CONTEXT_MODULE, $cm->id); | |
2600 | $ratingdeloptions->contextid = $datacontext->id; | |
2601 | $ratingdeloptions->itemid = $record->id; | |
2602 | $rm->delete_ratings($ratingdeloptions); | |
2603 | ||
2604 | $DB->delete_records('comments', array('itemid'=>$record->id, 'commentarea'=>'database_entry')); | |
2605 | $DB->delete_records('data_content', array('recordid'=>$record->id)); | |
2606 | $DB->delete_records('data_records', array('id'=>$record->id)); | |
2607 | // HACK: this is ugly - the recordid should be before the fieldid! | |
2608 | if (!array_key_exists($record->dataid, $fields)) { | |
2609 | if ($fs = $DB->get_records('data_fields', array('dataid'=>$record->dataid))) { | |
2610 | $fields[$record->dataid] = array_keys($fs); | |
2611 | } else { | |
2612 | $fields[$record->dataid] = array(); | |
0b5a80a1 | 2613 | } |
0b5a80a1 | 2614 | } |
6b1b1d03 EL |
2615 | foreach($fields[$record->dataid] as $fieldid) { |
2616 | fulldelete("$CFG->dataroot/$data->courseid/moddata/data/$record->dataid/$fieldid/$record->id"); | |
2617 | } | |
2618 | $notenrolled[$record->userid] = true; | |
0b5a80a1 | 2619 | } |
0b5a80a1 | 2620 | } |
6b1b1d03 EL |
2621 | $rs->close(); |
2622 | $status[] = array('component'=>$componentstr, 'item'=>get_string('deletenotenrolled', 'data'), 'error'=>false); | |
0b5a80a1 | 2623 | } |
2624 | ||
2625 | // remove all ratings | |
2626 | if (!empty($data->reset_data_ratings)) { | |
d251b259 AD |
2627 | if ($datas = $DB->get_records_sql($alldatassql, array($data->courseid))) { |
2628 | foreach ($datas as $dataid=>$unused) { | |
2629 | if (!$cm = get_coursemodule_from_instance('data', $dataid)) { | |
2630 | continue; | |
2631 | } | |
2632 | $datacontext = get_context_instance(CONTEXT_MODULE, $cm->id); | |
2633 | ||
2634 | $ratingdeloptions->contextid = $datacontext->id; | |
2635 | $rm->delete_ratings($ratingdeloptions); | |
2636 | } | |
2637 | } | |
0b5a80a1 | 2638 | |
2639 | if (empty($data->reset_gradebook_grades)) { | |
2640 | // remove all grades from gradebook | |
2641 | data_reset_gradebook($data->courseid); | |
2642 | } | |
b572ce19 | 2643 | |
0b5a80a1 | 2644 | $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallratings'), 'error'=>false); |
2645 | } | |
2646 | ||
2647 | // remove all comments | |
2648 | if (!empty($data->reset_data_comments)) { | |
e998effa | 2649 | $DB->delete_records_select('comments', "itemid IN ($allrecordssql) AND commentarea='database_entry'", array($data->courseid)); |
0b5a80a1 | 2650 | $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallcomments'), 'error'=>false); |
2651 | } | |
2652 | ||
b8b554ac | 2653 | // updating dates - shift may be negative too |
0b5a80a1 | 2654 | if ($data->timeshift) { |
2655 | shift_course_mod_dates('data', array('timeavailablefrom', 'timeavailableto', 'timeviewfrom', 'timeviewto'), $data->timeshift, $data->courseid); | |
2656 | $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged'), 'error'=>false); | |
2657 | } | |
b572ce19 | 2658 | |
0b5a80a1 | 2659 | return $status; |
2660 | } | |
f432bebf | 2661 | |
2662 | /** | |
2663 | * Returns all other caps used in module | |
4636bf83 | 2664 | * |
2665 | * @return array | |
f432bebf | 2666 | */ |
2667 | function data_get_extra_capabilities() { | |
16b86ae4 | 2668 | return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames', 'moodle/rating:view', 'moodle/rating:viewany', 'moodle/rating:viewall', 'moodle/rating:rate', 'moodle/comment:view', 'moodle/comment:post', 'moodle/comment:delete'); |
f432bebf | 2669 | } |
2670 | ||
18a2a0cb | 2671 | /** |
2672 | * @param string $feature FEATURE_xx constant for requested feature | |
2673 | * @return mixed True if module supports feature, null if doesn't know | |
2674 | */ | |
2675 | function data_supports($feature) { | |
2676 | switch($feature) { | |
42f103be | 2677 | case FEATURE_GROUPS: return true; |
2678 | case FEATURE_GROUPINGS: return true; | |
2679 | case FEATURE_GROUPMEMBERSONLY: return true; | |
dc5c2bd9 | 2680 | case FEATURE_MOD_INTRO: return true; |
18a2a0cb | 2681 | case FEATURE_COMPLETION_TRACKS_VIEWS: return true; |
42f103be | 2682 | case FEATURE_GRADE_HAS_GRADE: return true; |
2683 | case FEATURE_GRADE_OUTCOMES: return true; | |
d251b259 | 2684 | case FEATURE_RATE: return true; |
fd3f6bf9 | 2685 | case FEATURE_BACKUP_MOODLE2: return true; |
42f103be | 2686 | |
18a2a0cb | 2687 | default: return null; |
17da2e6f | 2688 | } |
18a2a0cb | 2689 | } |
4636bf83 | 2690 | /** |
2691 | * @global object | |
2692 | * @param array $export | |
2693 | * @param string $delimiter_name | |
2694 | * @param object $database | |
2695 | * @param int $count | |
2696 | * @param bool $return | |
2697 | * @return string|void | |
2698 | */ | |
1bf8c6b2 | 2699 | function data_export_csv($export, $delimiter_name, $dataname, $count, $return=false) { |
ecd06483 | 2700 | global $CFG; |
2701 | require_once($CFG->libdir . '/csvlib.class.php'); | |
20988152 | 2702 | $delimiter = csv_import_reader::get_delimiter($delimiter_name); |
fa7f82be | 2703 | $filename = clean_filename("{$dataname}-{$count}_record"); |
20988152 | 2704 | if ($count > 1) { |
2705 | $filename .= 's'; | |
2706 | } | |
2707 | $filename .= clean_filename('-' . gmdate("Ymd_Hi")); | |
fa7f82be | 2708 | $filename .= clean_filename("-{$delimiter_name}_separated"); |
20988152 | 2709 | $filename .= '.csv'; |
1bf8c6b2 | 2710 | if (empty($return)) { |
ecd06483 | 2711 | header("Content-Type: application/download\n"); |
2712 | header("Content-Disposition: attachment; filename=$filename"); | |
2713 | header('Expires: 0'); | |
2714 | header('Cache-Control: must-revalidate,post-check=0,pre-check=0'); | |
2715 | header('Pragma: public'); | |
2716 | } | |
20988152 | 2717 | $encdelim = '&#' . ord($delimiter) . ';'; |
ecd06483 | 2718 | $returnstr = ''; |
20988152 | 2719 | foreach($export as $row) { |
2720 | foreach($row as $key => $column) { | |
2721 | $row[$key] = str_replace($delimiter, $encdelim, $column); | |
2722 | } | |
ecd06483 | 2723 | $returnstr .= implode($delimiter, $row) . "\n"; |
2724 | } | |
1bf8c6b2 | 2725 | if (empty($return)) { |
ecd06483 | 2726 | echo $returnstr; |
2727 | return; | |
20988152 | 2728 | } |
1bf8c6b2 | 2729 | return $returnstr; |
20988152 | 2730 | } |
2731 | ||
4636bf83 | 2732 | /** |
2733 | * @global object | |
2734 | * @param array $export | |
2735 | * @param string $dataname | |
2736 | * @param int $count | |
2737 | * @return string | |
2738 | */ | |
1bf8c6b2 | 2739 | function data_export_xls($export, $dataname, $count) { |
20988152 | 2740 | global $CFG; |
2741 | require_once("$CFG->libdir/excellib.class.php"); | |
fa7f82be | 2742 | $filename = clean_filename("{$dataname}-{$count}_record"); |
20988152 | 2743 | if ($count > 1) { |
2744 | $filename .= 's'; | |
2745 | } | |
2746 | $filename .= clean_filename('-' . gmdate("Ymd_Hi")); | |
2747 | $filename .= '.xls'; | |
ecd06483 | 2748 | |
2749 | $filearg = '-'; | |
ecd06483 | 2750 | $workbook = new MoodleExcelWorkbook($filearg); |
1bf8c6b2 | 2751 | $workbook->send($filename); |
20988152 | 2752 | $worksheet = array(); |
2753 | $worksheet[0] =& $workbook->add_worksheet(''); | |
2754 | $rowno = 0; | |
2755 | foreach ($export as $row) { | |
2756 | $colno = 0; | |
2757 | foreach($row as $col) { | |
2758 | $worksheet[0]->write($rowno, $colno, $col); | |
2759 | $colno++; | |
2760 | } | |
2761 | $rowno++; | |
2762 | } | |
2763 | $workbook->close(); | |
ecd06483 | 2764 | return $filename; |
20988152 | 2765 | } |
2766 | ||
4636bf83 | 2767 | /** |
2768 | * @global object | |
2769 | * @param array $export | |
2770 | * @param string $dataname | |
2771 | * @param int $count | |
2772 | * @param string | |
2773 | */ | |
1bf8c6b2 | 2774 | function data_export_ods($export, $dataname, $count) { |
20988152 | 2775 | global $CFG; |
2776 | require_once("$CFG->libdir/odslib.class.php"); | |
fa7f82be | 2777 | $filename = clean_filename("{$dataname}-{$count}_record"); |
20988152 | 2778 | if ($count > 1) { |
2779 | $filename .= 's'; | |
2780 | } | |
2781 | $filename .= clean_filename('-' . gmdate("Ymd_Hi")); | |
2782 | $filename .= '.ods'; | |
ecd06483 | 2783 | $filearg = '-'; |
1bf8c6b2 | 2784 | $workbook = new MoodleODSWorkbook($filearg); |
2785 | $workbook->send($filename); | |
20988152 | 2786 | $worksheet = array(); |
2787 | $worksheet[0] =& $workbook->add_worksheet(''); | |
2788 | $rowno = 0; | |
2789 | foreach ($export as $row) { | |
2790 | $colno = 0; | |
2791 | foreach($row as $col) { | |
2792 | $worksheet[0]->write($rowno, $colno, $col); | |
2793 | $colno++; | |
2794 | } | |
2795 | $rowno++; | |
2796 | } | |
2797 | $workbook->close(); | |
ecd06483 | 2798 | return $filename; |
2799 | } | |
2800 | ||
4636bf83 | 2801 | /** |
2802 | * @global object | |
2803 | * @param int $dataid | |
2804 | * @param array $fields | |
2805 | * @param array $selectedfields | |
2806 | * @return array | |
2807 | */ | |
ecd06483 | 2808 | function data_get_exportdata($dataid, $fields, $selectedfields) { |
2809 | global $DB; | |
2810 | ||
2811 | $exportdata = array(); | |
2812 | ||
2813 | // populate the header in first row of export | |
2814 | foreach($fields as $key => $field) { | |
2815 | if (!in_array($field->field->id, $selectedfields)) { | |
2816 | // ignore values we aren't exporting | |
2817 | unset($fields[$key]); | |
2818 | } else { | |
2819 | $exportdata[0][] = $field->field->name; | |
2820 | } | |
2821 | } | |
2822 | ||
2823 | $datarecords = $DB->get_records('data_records', array('dataid'=>$dataid)); | |
2824 | ksort($datarecords); | |
2825 | $line = 1; | |
2826 | foreach($datarecords as $record) { | |
2827 | // get content indexed by fieldid | |
2828 | if( $content = $DB->get_records('data_content', array('recordid'=>$record->id), 'fieldid', 'fieldid, content, content1, content2, content3, content4') ) { | |
2829 | foreach($fields as $field) { | |
2830 | $contents = ''; | |
2831 | if(isset($content[$field->field->id])) { | |
2832 | $contents = $field->export_text_value($content[$field->field->id]); | |
2833 | } | |
2834 | $exportdata[$line][] = $contents; | |
2835 | } | |
2836 | } | |
2837 | $line++; | |
2838 | } | |
2839 | $line--; | |
2840 | return $exportdata; | |
2841 | } | |
2842 | ||
8429163d | 2843 | /** |
2844 | * Lists all browsable file areas | |
4636bf83 | 2845 | * |
2846 | * @param object $course | |
2847 | * @param object $cm | |
2848 | * @param object $context | |
2849 | * @return array | |
8429163d | 2850 | */ |
2851 | function data_get_file_areas($course, $cm, $context) { | |
2852 | $areas = array(); | |
8429163d | 2853 | return $areas; |
2854 | } | |
2855 | ||
2856 | /** | |
2857 | * Serves the data attachments. Implements needed access control ;-) | |
4636bf83 | 2858 | * |
4636bf83 | 2859 | * @param object $course |
64f93798 | 2860 | * @param object $cm |
4636bf83 | 2861 | * @param object $context |
86900a93 | 2862 | * @param string $filearea |
4636bf83 | 2863 | * @param array $args |
86900a93 | 2864 | * @param bool $forcedownload |
2865 | * @return bool false if file not found, does not return if found - justsend the file | |
8429163d | 2866 | */ |
64f93798 | 2867 | function data_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) { |
8429163d | 2868 | global $CFG, $DB; |
2869 | ||
64f93798 | 2870 | if ($context->contextlevel != CONTEXT_MODULE) { |
8429163d | 2871 | return false; |
2872 | } | |
2873 | ||
375053ed | 2874 | require_course_login($course, true, $cm); |
64f93798 PS |
2875 | |
2876 | if ($filearea === 'content') { | |
8429163d | 2877 | $contentid = (int)array_shift($args); |
2878 | ||
2879 | if (!$content = $DB->get_record('data_content', array('id'=>$contentid))) { | |
2880 | return false; | |
2881 | } | |
2882 | ||
2883 | if (!$field = $DB->get_record('data_fields', array('id'=>$content->fieldid))) { | |
2884 | return false; | |
2885 | } | |
2886 | ||
2887 | if (!$record = $DB->get_record('data_records', array('id'=>$content->recordid))) { | |
2888 | return false; | |
2889 | } | |
2890 | ||
2891 | if (!$data = $DB->get_record('data', array('id'=>$field->dataid))) { | |
2892 | return false; | |
2893 | } | |
2894 | ||
f011a8fb PS |
2895 | if ($data->id != $cm->instance) { |
2896 | // hacker attempt - context does not match the contentid | |
2897 | return false; | |
2898 | } | |
2899 | ||
8429163d | 2900 | //check if approved |
f011a8fb | 2901 | if ($data->approval and !$record->approved and !data_isowner($record) and !has_capability('mod/data:approve', $context)) { |
8429163d | 2902 | return false; |
2903 | } | |
2904 | ||
2905 | // group access | |
2906 | if ($record->groupid) { | |
0a8a7b6c | 2907 | $groupmode = groups_get_activity_groupmode($cm, $course); |
8429163d | 2908 | if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) { |
2909 | if (!groups_is_member($record->groupid)) { | |
2910 | return false; | |
2911 | } | |
2912 | } | |
2913 | } | |
2914 | ||
0a8a7b6c | 2915 | $fieldobj = data_get_field($field, $data, $cm); |
8429163d | 2916 | |
64f93798 PS |
2917 | $relativepath = implode('/', $args); |
2918 | $fullpath = "/$context->id/mod_data/content/$content->id/$relativepath"; | |
8429163d | 2919 | |
2920 | if (!$fieldobj->file_ok($relativepath)) { | |
2921 | return false; | |
2922 | } | |
2923 | ||
2924 | $fs = get_file_storage(); | |
2925 | if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { | |
2926 | return false; | |
2927 | } | |
2928 | ||
2929 | // finally send the file | |
2930 | send_stored_file($file, 0, 0, true); // download MUST be forced - security! | |
2931 | } | |
2932 | ||
2933 | return false; | |
2934 | } | |
2935 | ||
29b64a22 | 2936 | |
2937 | function data_extend_navigation($navigation, $course, $module, $cm) { | |
2938 | global $CFG, $OUTPUT, $USER, $DB; | |
2939 | ||
2940 | $rid = optional_param('rid', 0, PARAM_INT); | |
2941 | ||
2942 | $data = $DB->get_record('data', array('id'=>$cm->instance)); | |
2943 | $currentgroup = groups_get_activity_group($cm); | |
2944 | $groupmode = groups_get_activity_groupmode($cm); | |
2945 | ||
2946 | $numentries = data_numentries($data); | |
2947 | /// Check the number of entries required against the number of entries already made (doesn't apply to teachers) | |
4f0c2d00 | 2948 | if ($data->requiredentries > 0 && $numentries < $data->requiredentries && !has_capability('mod/data:manageentries', get_context_instance(CONTEXT_MODULE, $cm->id))) { |
29b64a22 | 2949 | $data->entriesleft = $data->requiredentries - $numentries; |
3406acde SH |
2950 | $entriesnode = $navigation->add(get_string('entrieslefttoadd', 'data', $data)); |
2951 | $entriesnode->add_class('note'); | |
29b64a22 | 2952 | } |
2953 | ||
a6855934 | 2954 | $navigation->add(get_string('list', 'data'), new moodle_url('/mod/data/view.php', array('d'=>$cm->instance))); |
29b64a22 | 2955 | if (!empty($rid)) { |
a6855934 | 2956 | $navigation->add(get_string('single', 'data'), new moodle_url('/mod/data/view.php', array('d'=>$cm->instance, 'rid'=>$rid))); |
29b64a22 | 2957 | } else { |
a6855934 | 2958 | $navigation->add(get_string('single', 'data'), new moodle_url('/mod/data/view.php', array('d'=>$cm->instance, 'mode'=>'single'))); |
29b64a22 | 2959 | } |
ea2052ab | 2960 | $navigation->add(get_string('search', 'data'), new moodle_url('/mod/data/view.php', array('d'=>$cm->instance, 'mode'=>'asearch'))); |
29b64a22 | 2961 | } |
2962 | ||
0b29477b SH |
2963 | /** |
2964 | * Adds module specific settings to the settings block | |
2965 | * | |
2966 | * @param settings_navigation $settings The settings navigation object | |
2967 | * @param navigation_node $datanode The node to add module settings to | |
2968 | */ | |
2969 | function data_extend_settings_navigation(settings_navigation $settings, navigation_node $datanode) { | |
9e86f2e7 | 2970 | global $PAGE, $DB, $CFG, $USER; |
56115eea | 2971 | |
9e86f2e7 | 2972 | $data = $DB->get_record('data', array("id" => $PAGE->cm->instance)); |
29b64a22 | 2973 | |
29b64a22 | 2974 | $currentgroup = groups_get_activity_group($PAGE->cm); |
2975 | $groupmode = groups_get_activity_groupmode($PAGE->cm); | |
2976 | ||
e4e96115 | 2977 | if (data_user_can_add_entry($data, $currentgroup, $groupmode, $PAGE->cm->context)) { // took out participation list here! |
fa7f82be | 2978 | if (empty($editentry)) { //TODO: undefined |
29b64a22 | 2979 | $addstring = get_string('add', 'data'); |
2980 | } else { | |
2981 | $addstring = get_string('editentry', 'data'); | |
2982 | } | |
0b29477b | 2983 | $datanode->add($addstring, new moodle_url('/mod/data/edit.php', array('d'=>$PAGE->cm->instance))); |
29b64a22 | 2984 | } |
2985 | ||
2986 | if (has_capability(DATA_CAP_EXPORT, $PAGE->cm->context)) { | |
2987 | // The capability required to Export database records is centrally defined in 'lib.php' | |
2988 | // and should be weaker than those required to edit Templates, Fields and Presets. | |
dd8ab1fb | 2989 | $datanode->add(get_string('exportentries', 'data'), new moodle_url('/mod/data/export.php', array('d'=>$data->id))); |
29b64a22 | 2990 | } |
bbdfd8ce | 2991 | if (has_capability('mod/data:manageentries', $PAGE->cm->context)) { |
dd8ab1fb | 2992 | $datanode->add(get_string('importentries', 'data'), new moodle_url('/mod/data/import.php', array('d'=>$data->id))); |
bbdfd8ce | 2993 | } |
29b64a22 | 2994 | |
2995 | if (has_capability('mod/data:managetemplates', $PAGE->cm->context)) { | |
2996 | $currenttab = ''; | |
2997 | if ($currenttab == 'list') { | |
2998 | $defaultemplate = 'listtemplate'; | |
2999 | } else if ($currenttab == 'add') { | |
3000 | $defaultemplate = 'addtemplate'; | |
3001 | } else if ($currenttab == 'asearch') { | |
3002 | $defaultemplate = 'asearchtemplate'; | |
3003 | } else { | |
3004 | $defaultemplate = 'singletemplate'; | |
3005 | } | |
3006 | ||
3406acde | 3007 | $templates = $datanode->add(get_string('templates', 'data')); |
29b64a22 | 3008 | |
3009 | $templatelist = array ('listtemplate', 'singletemplate', 'asearchtemplate', 'addtemplate', 'rsstemplate', 'csstemplate', 'jstemplate'); | |
3010 | foreach ($templatelist as $template) { | |
a6855934 | 3011 | $templates->add(get_string($template, 'data'), new moodle_url('/mod/data/templates.php', array('d'=>$data->id,'mode'=>$template))); |
29b64a22 | 3012 | } |
3013 | ||
0b29477b SH |
3014 | $datanode->add(get_string('fields', 'data'), new moodle_url('/mod/data/field.php', array('d'=>$data->id))); |
3015 | $datanode->add(get_string('presets', 'data'), new moodle_url('/mod/data/preset.php', array('d'=>$data->id))); | |
29b64a22 | 3016 | } |
9e86f2e7 AD |
3017 | |
3018 | if (!empty($CFG->enablerssfeeds) && !empty($CFG->data_enablerssfeeds) && $data->rssarticles > 0) { | |
3019 | require_once("$CFG->libdir/rsslib.php"); | |
3020 | ||
3021 | $string = get_string('rsstype','forum'); | |
3022 | ||
aa60291e | 3023 | $url = new moodle_url(rss_get_url($PAGE->cm->context->id, $USER->id, 'mod_data', $data->id)); |
9e86f2e7 AD |
3024 | $datanode->add($string, $url, settings_navigation::TYPE_SETTING, null, null, new pix_icon('i/rss', '')); |
3025 | } | |
7719b4db | 3026 | } |
cba87c36 | 3027 | |
8aff1574 SH |
3028 | /** |
3029 | * Save the database configuration as a preset. | |
3030 | * | |
3031 | * @param stdClass $course The course the database module belongs to. | |
3032 | * @param stdClass $cm The course module record | |
3033 | * @param stdClass $data The database record | |
3034 | * @param string $path | |
3035 | * @return bool | |
3036 | */ | |
3037 | function data_presets_save($course, $cm, $data, $path) { | |
3038 | $fs = get_file_storage(); | |
3039 | $filerecord = new stdClass; | |
3040 | $filerecord->contextid = DATA_PRESET_CONTEXT; | |
3041 | $filerecord->component = DATA_PRESET_COMPONENT; | |
3042 | $filerecord->filearea = DATA_PRESET_FILEAREA; | |
3043 | $filerecord->itemid = 0; | |
3044 | $filerecord->filepath = '/'.$path.'/'; | |
3045 | ||
3046 | $filerecord->filename = 'preset.xml'; | |
3047 | $fs->create_file_from_string($filerecord, data_presets_generate_xml($course, $cm, $data)); | |
3048 | ||
3049 | $filerecord->filename = 'singletemplate.html'; | |
3050 | $fs->create_file_from_string($filerecord, $data->singletemplate); | |
3051 | ||
3052 | $filerecord->filename = 'listtemplateheader.html'; | |
3053 | $fs->create_file_from_string($filerecord, $data->listtemplateheader); | |
3054 | ||
3055 | $filerecord->filename = 'listtemplate.html'; | |
3056 | $fs->create_file_from_string($filerecord, $data->listtemplate); | |
3057 | ||
3058 | $filerecord->filename = 'listtemplatefooter.html'; | |
3059 | $fs->create_file_from_string($filerecord, $data->listtemplatefooter); | |
3060 | ||
3061 | $filerecord->filename = 'addtemplate.html'; | |
3062 | $fs->create_file_from_string($filerecord, $data->addtemplate); | |
3063 | ||
3064 | $filerecord->filename = 'rsstemplate.html'; | |
3065 | $fs->create_file_from_string($filerecord, $data->rsstemplate); | |
3066 | ||
3067 | $filerecord->filename = 'rsstitletemplate.html'; | |
3068 | $fs->create_file_from_string($filerecord, $data->rsstitletemplate); | |
3069 | ||
3070 | $filerecord->filename = 'csstemplate.css'; | |
3071 | $fs->create_file_from_string($filerecord, $data->csstemplate); | |
3072 | ||
3073 | $filerecord->filename = 'jstemplate.js'; | |
3074 | $fs->create_file_from_string($filerecord, $data->jstemplate); | |
3075 | ||
3076 | $filerecord->filename = 'asearchtemplate.html'; | |
3077 | $fs->create_file_from_string($filerecord, $data->asearchtemplate); | |
3078 | ||
3079 | return true; | |
3080 | } | |
cba87c36 | 3081 | |
8aff1574 SH |
3082 | /** |
3083 | * Generates the XML for the database module provided | |
3084 | * | |
3085 | * @global moodle_database $DB | |
3086 | * @param stdClass $course The course the database module belongs to. | |
3087 | * @param stdClass $cm The course module record | |
3088 | * @param stdClass $data The database record | |
3089 | * @return string The XML for the preset | |
3090 | */ | |
3091 | function data_presets_generate_xml($course, $cm, $data) { | |
3092 | global $DB; | |
800bb0f7 | 3093 | |
cba87c36 SH |
3094 | // Assemble "preset.xml": |
3095 | $presetxmldata = "<preset>\n\n"; | |
3096 | ||
3097 | // Raw settings are not preprocessed during saving of presets | |
3098 | $raw_settings = array( | |
3099 | 'intro', | |
3100 | 'comments', | |
3101 | 'requiredentries', | |
3102 | 'requiredentriestoview', | |
3103 | 'maxentries', | |
3104 | 'rssarticles', | |
3105 | 'approval', | |
3106 | 'defaultsortdir' | |
3107 | ); | |
3108 | ||
3109 | $presetxmldata .= "<settings>\n"; | |
3110 | // First, settings that do not require any conversion | |
3111 | foreach ($raw_settings as $setting) { | |
3112 | $presetxmldata .= "<$setting>" . htmlspecialchars($data->$setting) . "</$setting>\n"; | |
3113 | } | |
3114 | ||
3115 | // Now specific settings | |
3116 | if ($data->defaultsort > 0 && $sortfield = data_get_field_from_id($data->defaultsort, $data)) { | |
3117 | $presetxmldata .= '<defaultsort>' . htmlspecialchars($sortfield->field->name) . "</defaultsort>\n"; | |
3118 | } else { | |
3119 | $presetxmldata .= "<defaultsort>0</defaultsort>\n"; | |
3120 | } | |
3121 | $presetxmldata .= "</settings>\n\n"; | |
cba87c36 SH |
3122 | // Now for the fields. Grab all that are non-empty |
3123 | $fields = $DB->get_records('data_fields', array('dataid'=>$data->id)); | |
3124 | ksort($fields); | |
3125 | if (!empty($fields)) { | |
3126 | foreach ($fields as $field) { | |
3127 | $presetxmldata .= "<field>\n"; | |
3128 | foreach ($field as $key => $value) { | |
3129 | if ($value != '' && $key != 'id' && $key != 'dataid') { | |
3130 | $presetxmldata .= "<$key>" . htmlspecialchars($value) . "</$key>\n"; | |
3131 | } | |
3132 | } | |
3133 | $presetxmldata .= "</field>\n\n"; | |
3134 | } | |
3135 | } | |
3136 | $presetxmldata .= '</preset>'; | |
8aff1574 SH |
3137 | return $presetxmldata; |
3138 | } | |
3139 | ||
3140 | function data_presets_export($course, $cm, $data, $tostorage=false) { | |
3141 | global $CFG, $DB; | |
3142 | ||
3143 | $presetname = clean_filename($data->name) . '-preset-' . gmdate("Ymd_Hi"); | |
3144 | $exportsubdir = "temp/mod_data/presetexport/$presetname"; | |
3145 | make_upload_directory($exportsubdir); | |
3146 | $exportdir = "$CFG->dataroot/$exportsubdir"; | |
3147 | ||
3148 | // Assemble "preset.xml": | |
3149 | $presetxmldata = data_presets_generate_xml($course, $cm, $data); | |
cba87c36 SH |
3150 | |
3151 | // After opening a file in write mode, close it asap | |
3152 | $presetxmlfile = fopen($exportdir . '/preset.xml', 'w'); | |
3153 | fwrite($presetxmlfile, $presetxmldata); | |
3154 | fclose($presetxmlfile); | |
3155 | ||
3156 | // Now write the template files | |
3157 | $singletemplate = fopen($exportdir . '/singletemplate.html', 'w'); | |
3158 | fwrite($singletemplate, $data->singletemplate); | |
3159 | fclose($singletemplate); | |
3160 | ||
3161 | $listtemplateheader = fopen($exportdir . '/listtemplateheader.html', 'w'); | |
3162 | fwrite($listtemplateheader, $data->listtemplateheader); | |
3163 | fclose($listtemplateheader); | |
3164 | ||
3165 | $listtemplate = fopen($exportdir . '/listtemplate.html', 'w'); | |
3166 | fwrite($listtemplate, $data->listtemplate); | |
3167 | fclose($listtemplate); | |
3168 | ||
3169 | $listtemplatefooter = fopen($exportdir . '/listtemplatefooter.html', 'w'); | |
3170 | fwrite($listtemplatefooter, $data->listtemplatefooter); | |
3171 | fclose($listtemplatefooter); | |
3172 | ||
3173 | $addtemplate = fopen($exportdir . '/addtemplate.html', 'w'); | |
3174 | fwrite($addtemplate, $data->addtemplate); | |
3175 | fclose($addtemplate); | |
3176 | ||
3177 | $rsstemplate = fopen($exportdir . '/rsstemplate.html', 'w'); | |
3178 | fwrite($rsstemplate, $data->rsstemplate); | |
3179 | fclose($rsstemplate); | |
3180 | ||
3181 | $rsstitletemplate = fopen($exportdir . '/rsstitletemplate.html', 'w'); | |
3182 | fwrite($rsstitletemplate, $data->rsstitletemplate); | |
3183 | fclose($rsstitletemplate); | |
3184 | ||
3185 | $csstemplate = fopen($exportdir . '/csstemplate.css', 'w'); | |
3186 | fwrite($csstemplate, $data->csstemplate); | |
3187 | fclose($csstemplate); | |
3188 | ||
3189 | $jstemplate = fopen($exportdir . '/jstemplate.js', 'w'); | |
3190 | fwrite($jstemplate, $data->jstemplate); | |
3191 | fclose($jstemplate); | |
3192 | ||
3193 | $asearchtemplate = fopen($exportdir . '/asearchtemplate.html', 'w'); | |
3194 | fwrite($asearchtemplate, $data->asearchtemplate); | |
3195 | fclose($asearchtemplate); | |
3196 | ||
3197 | // Check if all files have been generated | |
3198 | if (! is_directory_a_preset($exportdir)) { | |
3199 | print_error('generateerror', 'data'); | |
3200 | } | |
3201 | ||
60a1a25c | 3202 | $filenames = array( |
cba87c36 SH |
3203 | 'preset.xml', |
3204 | 'singletemplate.html', | |
3205 | 'listtemplateheader.html', | |
3206 | 'listtemplate.html', | |
3207 | 'listtemplatefooter.html', | |
3208 | 'addtemplate.html', | |
3209 | 'rsstemplate.html', | |
3210 | 'rsstitletemplate.html', | |
3211 | 'csstemplate.css', | |
3212 | 'jstemplate.js', | |
3213 | 'asearchtemplate.html' | |
3214 | ); | |
3215 | ||
60a1a25c AD |
3216 | $filelist = array(); |
3217 | foreach ($filenames as $filename) { | |
3218 | $filelist[$filename] = $exportdir . '/' . $filename; | |
cba87c36 SH |
3219 | } |
3220 | ||
8aff1574 | 3221 | $exportfile = $exportdir.'.zip'; |
cba87c36 | 3222 | file_exists($exportfile) && unlink($exportfile); |
8aff1574 | 3223 | |
cf792cfc PS |
3224 | $fp = get_file_packer('application/zip'); |
3225 | $fp->archive_to_pathname($filelist, $exportfile); | |
8aff1574 | 3226 | |
cba87c36 SH |
3227 | foreach ($filelist as $file) { |
3228 | unlink($file); | |
3229 | } | |
3230 | rmdir($exportdir); | |
3231 | ||
3232 | // Return the full path to the exported preset file: | |
3233 | return $exportfile; | |
d846488e | 3234 | } |
c1951ea9 DC |
3235 | |
3236 | /** | |
3237 | * Running addtional permission check on plugin, for example, plugins | |
3238 | * may have switch to turn on/off comments option, this callback will | |
3239 | * affect UI display, not like pluginname_comment_validate only throw | |
3240 | * exceptions. | |
3241 | * Capability check has been done in comment->check_permissions(), we | |
3242 | * don't need to do it again here. | |
3243 | * | |
3244 | * @param stdClass $comment_param { | |
3245 | * context => context the context object | |
3246 | * courseid => int course id | |
3247 | * cm => stdClass course module object | |
3248 | * commentarea => string comment area | |
3249 | * itemid => int itemid | |
3250 | * } | |
3251 | * @return array | |
3252 | */ | |
3253 | function data_comment_permissions($comment_param) { | |
3254 | global $CFG, $DB; | |
3255 | if (!$record = $DB->get_record('data_records', array('id'=>$comment_param->itemid))) { | |
3256 | throw new comment_exception('invalidcommentitemid'); | |
3257 | } | |
3258 | if (!$data = $DB->get_record('data', array('id'=>$record->dataid))) { | |
3259 | throw new comment_exception('invalidid', 'data'); | |
3260 | } | |
3261 | if ($data->comments) { | |