MDL-14635 fix for user profil help icons
[moodle-linuxchix.git] / mod / data / lib.php
blobd3c33fe4c5788e06a464b975f93d0f11aea39cad
1 <?php // $Id$
2 ///////////////////////////////////////////////////////////////////////////
3 // //
4 // NOTICE OF COPYRIGHT //
5 // //
6 // Moodle - Modular Object-Oriented Dynamic Learning Environment //
7 // http://moodle.org //
8 // //
9 // Copyright (C) 2005 Moodle Pty Ltd http://moodle.com //
10 // //
11 // This program is free software; you can redistribute it and/or modify //
12 // it under the terms of the GNU General Public License as published by //
13 // the Free Software Foundation; either version 2 of the License, or //
14 // (at your option) any later version. //
15 // //
16 // This program is distributed in the hope that it will be useful, //
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
19 // GNU General Public License for more details: //
20 // //
21 // http://www.gnu.org/copyleft/gpl.html //
22 // //
23 ///////////////////////////////////////////////////////////////////////////
25 // Some constants
26 define ('DATA_MAX_ENTRIES', 50);
27 define ('DATA_PERPAGE_SINGLE', 1);
28 define ('DATA_FIRSTNAME', -1);
29 define ('DATA_LASTNAME', -2);
30 define ('DATA_APPROVED', -3);
31 define ('DATA_TIMEADDED', 0);
32 define ('DATA_TIMEMODIFIED', -4);
34 define ('DATA_CAP_EXPORT', 'mod/data:viewalluserpresets');
35 // Users having assigned the default role "Non-editing teacher" can export database records
36 // Using the mod/data capability "viewalluserpresets" for Moodle 1.9.x, so no change in the role system is required.
37 // In Moodle >= 2, new roles may be introduced and used instead.
39 class data_field_base { // Base class for Database Field Types (see field/*/field.class.php)
41 var $type = 'unknown'; // Subclasses must override the type with their name
42 var $data = NULL; // The database object that this field belongs to
43 var $field = NULL; // The field object itself, if we know it
45 var $iconwidth = 16; // Width of the icon for this fieldtype
46 var $iconheight = 16; // Width of the icon for this fieldtype
49 // Constructor function
50 function data_field_base($field=0, $data=0) { // Field or data or both, each can be id or object
51 if (empty($field) && empty($data)) {
52 error('Programmer error: You must specify field and/or data when defining field class. ');
54 if (!empty($field)) {
55 if (is_object($field)) {
56 $this->field = $field; // Programmer knows what they are doing, we hope
57 } else if (!$this->field = get_record('data_fields','id',$field)) {
58 error('Bad field ID encountered: '.$field);
60 if (empty($data)) {
61 if (!$this->data = get_record('data','id',$this->field->dataid)) {
62 error('Bad data ID encountered in field data');
66 if (empty($this->data)) { // We need to define this properly
67 if (!empty($data)) {
68 if (is_object($data)) {
69 $this->data = $data; // Programmer knows what they are doing, we hope
70 } else if (!$this->data = get_record('data','id',$data)) {
71 error('Bad data ID encountered: '.$data);
73 } else { // No way to define it!
74 error('Data id or object must be provided to field class');
77 if (empty($this->field)) { // We need to define some default values
78 $this->define_default_field();
83 // This field just sets up a default field object
84 function define_default_field() {
85 if (empty($this->data->id)) {
86 notify('Programmer error: dataid not defined in field class');
88 $this->field = new object;
89 $this->field->id = 0;
90 $this->field->dataid = $this->data->id;
91 $this->field->type = $this->type;
92 $this->field->param1 = '';
93 $this->field->param2 = '';
94 $this->field->param3 = '';
95 $this->field->name = '';
96 $this->field->description = '';
97 return true;
100 // Set up the field object according to data in an object. Now is the time to clean it!
101 function define_field($data) {
102 $this->field->type = $this->type;
103 $this->field->dataid = $this->data->id;
105 $this->field->name = trim($data->name);
106 $this->field->description = trim($data->description);
108 if (isset($data->param1)) {
109 $this->field->param1 = trim($data->param1);
111 if (isset($data->param2)) {
112 $this->field->param2 = trim($data->param2);
114 if (isset($data->param3)) {
115 $this->field->param3 = trim($data->param3);
117 if (isset($data->param4)) {
118 $this->field->param4 = trim($data->param4);
120 if (isset($data->param5)) {
121 $this->field->param5 = trim($data->param5);
124 return true;
127 // Insert a new field in the database
128 // We assume the field object is already defined as $this->field
129 function insert_field() {
130 if (empty($this->field)) {
131 notify('Programmer error: Field has not been defined yet! See define_field()');
132 return false;
135 if (!$this->field->id = insert_record('data_fields',$this->field)){
136 notify('Insertion of new field failed!');
137 return false;
139 return true;
143 // Update a field in the database
144 function update_field() {
145 if (!update_record('data_fields', $this->field)) {
146 notify('updating of new field failed!');
147 return false;
149 return true;
152 // Delete a field completely
153 function delete_field() {
154 if (!empty($this->field->id)) {
155 delete_records('data_fields', 'id', $this->field->id);
156 $this->delete_content();
158 return true;
161 // Print the relevant form element in the ADD template for this field
162 function display_add_field($recordid=0){
163 if ($recordid){
164 $content = get_field('data_content', 'content', 'fieldid', $this->field->id, 'recordid', $recordid);
165 } else {
166 $content = '';
169 $str = '<div title="'.s($this->field->description).'">';
170 $str .= '<input style="width:300px;" type="text" name="field_'.$this->field->id.'" id="field_'.$this->field->id.'" value="'.s($content).'" />';
171 $str .= '</div>';
173 return $str;
176 // Print the relevant form element to define the attributes for this field
177 // viewable by teachers only.
178 function display_edit_field() {
179 global $CFG;
181 if (empty($this->field)) { // No field has been defined yet, try and make one
182 $this->define_default_field();
184 print_simple_box_start('center','80%');
186 echo '<form id="editfield" action="'.$CFG->wwwroot.'/mod/data/field.php" method="post">'."\n";
187 echo '<input type="hidden" name="d" value="'.$this->data->id.'" />'."\n";
188 if (empty($this->field->id)) {
189 echo '<input type="hidden" name="mode" value="add" />'."\n";
190 $savebutton = get_string('add');
191 } else {
192 echo '<input type="hidden" name="fid" value="'.$this->field->id.'" />'."\n";
193 echo '<input type="hidden" name="mode" value="update" />'."\n";
194 $savebutton = get_string('savechanges');
196 echo '<input type="hidden" name="type" value="'.$this->type.'" />'."\n";
197 echo '<input name="sesskey" value="'.sesskey().'" type="hidden" />'."\n";
199 print_heading($this->name());
201 require_once($CFG->dirroot.'/mod/data/field/'.$this->type.'/mod.html');
203 echo '<div align="center">';
204 echo '<input type="submit" value="'.$savebutton.'" />'."\n";
205 echo '<input type="submit" name="cancel" value="'.get_string('cancel').'" />'."\n";
206 echo '</div>';
208 echo '</form>';
210 print_simple_box_end();
213 // Display the content of the field in browse mode
214 function display_browse_field($recordid, $template) {
215 if ($content = get_record('data_content','fieldid', $this->field->id, 'recordid', $recordid)) {
216 if (isset($content->content)) {
217 $options = new object();
218 if ($this->field->param1 == '1') { // We are autolinking this field, so disable linking within us
219 //$content->content = '<span class="nolink">'.$content->content.'</span>';
220 //$content->content1 = FORMAT_HTML;
221 $options->filter=false;
223 $options->para = false;
224 $str = format_text($content->content, $content->content1, $options);
225 } else {
226 $str = '';
228 return $str;
230 return false;
233 // Update the content of one data field in the data_content table
234 function update_content($recordid, $value, $name='') {
235 $content = new object();
236 $content->fieldid = $this->field->id;
237 $content->recordid = $recordid;
238 $content->content = clean_param($value, PARAM_NOTAGS);
240 if ($oldcontent = get_record('data_content','fieldid', $this->field->id, 'recordid', $recordid)) {
241 $content->id = $oldcontent->id;
242 return update_record('data_content', $content);
243 } else {
244 return insert_record('data_content', $content);
248 // Delete all content associated with the field
249 function delete_content($recordid=0) {
251 $this->delete_content_files($recordid);
253 if ($recordid) {
254 return delete_records('data_content', 'fieldid', $this->field->id, 'recordid', $recordid);
255 } else {
256 return delete_records('data_content', 'fieldid', $this->field->id);
260 // Deletes any files associated with this field
261 function delete_content_files($recordid='') {
262 global $CFG;
264 require_once($CFG->libdir.'/filelib.php');
266 $dir = $CFG->dataroot.'/'.$this->data->course.'/'.$CFG->moddata.'/data/'.$this->data->id.'/'.$this->field->id;
267 if ($recordid) {
268 $dir .= '/'.$recordid;
271 return fulldelete($dir);
275 // Check if a field from an add form is empty
276 function notemptyfield($value, $name) {
277 return !empty($value);
280 // Just in case a field needs to print something before the whole form
281 function print_before_form() {
284 // Just in case a field needs to print something after the whole form
285 function print_after_form() {
289 // Returns the sortable field for the content. By default, it's just content
290 // but for some plugins, it could be content 1 - content4
291 function get_sort_field() {
292 return 'content';
295 // Returns the SQL needed to refer to the column. Some fields may need to CAST() etc.
296 function get_sort_sql($fieldname) {
297 return $fieldname;
300 // Returns the name/type of the field
301 function name() {
302 return get_string('name'.$this->type, 'data');
305 // Prints the respective type icon
306 function image() {
307 global $CFG;
309 $str = '<a href="field.php?d='.$this->data->id.'&amp;fid='.$this->field->id.'&amp;mode=display&amp;sesskey='.sesskey().'">';
310 $str .= '<img src="'.$CFG->modpixpath.'/data/field/'.$this->type.'/icon.gif" ';
311 $str .= 'height="'.$this->iconheight.'" width="'.$this->iconwidth.'" alt="'.$this->type.'" title="'.$this->type.'" /></a>';
312 return $str;
315 // Per default, it is assumed that fields support text exporting. Override this (return false) on fields not supporting text exporting.
316 function text_export_supported() {
317 return true;
320 // Per default, return the record's text value only from the "content" field. Override this in fields class if necesarry.
321 function export_text_value($record) {
322 if ($this->text_export_supported()) {
323 return $record->content;
331 /* Given a template and a dataid, generate a default case template
332 * input @param template - addtemplate, singletemplate, listtempalte, rsstemplate
333 * @param dataid
334 * output null
336 function data_generate_default_template(&$data, $template, $recordid=0, $form=false, $update=true) {
338 if (!$data && !$template) {
339 return false;
341 if ($template == 'csstemplate' or $template == 'jstemplate' ) {
342 return '';
345 // get all the fields for that database
346 if ($fields = get_records('data_fields', 'dataid', $data->id, 'id')) {
348 $str = '<div class="defaulttemplate">';
349 $str .= '<table cellpadding="5">';
351 foreach ($fields as $field) {
353 $str .= '<tr><td valign="top" align="right">';
354 // Yu: commenting this out, the id was wrong and will fix later
355 //if ($template == 'addtemplate') {
356 //$str .= '<label';
357 //if (!in_array($field->type, array('picture', 'checkbox', 'date', 'latlong', 'radiobutton'))) {
358 // $str .= ' for="[['.$field->name.'#id]]"';
360 //$str .= '>'.$field->name.'</label>';
362 //} else {
363 $str .= $field->name.': ';
365 $str .= '</td>';
367 $str .='<td>';
368 if ($form) { // Print forms instead of data
369 $fieldobj = data_get_field($field, $data);
370 $str .= $fieldobj->display_add_field($recordid);
372 } else { // Just print the tag
373 $str .= '[['.$field->name.']]';
375 $str .= '</td></tr>';
378 if ($template == 'listtemplate') {
379 $str .= '<tr><td align="center" colspan="2">##edit## ##more## ##delete## ##approve##</td></tr>';
380 } else if ($template == 'singletemplate') {
381 $str .= '<tr><td align="center" colspan="2">##edit## ##delete## ##approve##</td></tr>';
382 } else if ($template == 'asearchtemplate') {
383 $str .= '<tr><td valign="top" align="right">'.get_string('authorfirstname', 'data').': </td><td>##firstname##</td></tr>';
384 $str .= '<tr><td valign="top" align="right">'.get_string('authorlastname', 'data').': </td><td>##lastname##</td></tr>';
387 $str .= '</table>';
388 $str .= '</div>';
390 if ($template == 'listtemplate'){
391 $str .= '<hr />';
394 if ($update) {
395 $newdata = new object();
396 $newdata->id = $data->id;
397 $newdata->{$template} = $str;
398 if (!update_record('data', $newdata)) {
399 notify('Error updating template');
400 } else {
401 $data->{$template} = $str;
405 return $str;
410 /***********************************************************************
411 * Search for a field name and replaces it with another one in all the *
412 * form templates. Set $newfieldname as '' if you want to delete the *
413 * field from the form. *
414 ***********************************************************************/
415 function data_replace_field_in_templates($data, $searchfieldname, $newfieldname) {
416 if (!empty($newfieldname)) {
417 $prestring = '[[';
418 $poststring = ']]';
419 $idpart = '#id';
421 } else {
422 $prestring = '';
423 $poststring = '';
424 $idpart = '';
427 $newdata = new object();
428 $newdata->id = $data->id;
429 $newdata->singletemplate = addslashes(str_ireplace('[['.$searchfieldname.']]',
430 $prestring.$newfieldname.$poststring, $data->singletemplate));
432 $newdata->listtemplate = addslashes(str_ireplace('[['.$searchfieldname.']]',
433 $prestring.$newfieldname.$poststring, $data->listtemplate));
435 $newdata->addtemplate = addslashes(str_ireplace('[['.$searchfieldname.']]',
436 $prestring.$newfieldname.$poststring, $data->addtemplate));
438 $newdata->addtemplate = addslashes(str_ireplace('[['.$searchfieldname.'#id]]',
439 $prestring.$newfieldname.$idpart.$poststring, $data->addtemplate));
441 $newdata->rsstemplate = addslashes(str_ireplace('[['.$searchfieldname.']]',
442 $prestring.$newfieldname.$poststring, $data->rsstemplate));
444 return update_record('data', $newdata);
448 /********************************************************
449 * Appends a new field at the end of the form template. *
450 ********************************************************/
451 function data_append_new_field_to_templates($data, $newfieldname) {
453 $newdata = new object();
454 $newdata->id = $data->id;
455 $change = false;
457 if (!empty($data->singletemplate)) {
458 $newdata->singletemplate = addslashes($data->singletemplate.' [[' . $newfieldname .']]');
459 $change = true;
461 if (!empty($data->addtemplate)) {
462 $newdata->addtemplate = addslashes($data->addtemplate.' [[' . $newfieldname . ']]');
463 $change = true;
465 if (!empty($data->rsstemplate)) {
466 $newdata->rsstemplate = addslashes($data->singletemplate.' [[' . $newfieldname . ']]');
467 $change = true;
469 if ($change) {
470 update_record('data', $newdata);
475 /************************************************************************
476 * given a field name *
477 * this function creates an instance of the particular subfield class *
478 ************************************************************************/
479 function data_get_field_from_name($name, $data){
480 $field = get_record('data_fields','name',$name);
481 if ($field) {
482 return data_get_field($field, $data);
483 } else {
484 return false;
488 /************************************************************************
489 * given a field id *
490 * this function creates an instance of the particular subfield class *
491 ************************************************************************/
492 function data_get_field_from_id($fieldid, $data) {
493 $field = get_record('data_fields','id',$fieldid);
494 if ($field) {
495 return data_get_field($field, $data);
496 } else {
497 return false;
501 /************************************************************************
502 * given a field id *
503 * this function creates an instance of the particular subfield class *
504 ************************************************************************/
505 function data_get_field_new($type, $data) {
506 global $CFG;
507 require_once($CFG->dirroot.'/mod/data/field/'.$type.'/field.class.php');
508 $newfield = 'data_field_'.$type;
509 $newfield = new $newfield(0, $data);
510 return $newfield;
513 /************************************************************************
514 * returns a subclass field object given a record of the field, used to *
515 * invoke plugin methods *
516 * input: $param $field - record from db *
517 ************************************************************************/
518 function data_get_field($field, $data) {
519 global $CFG;
520 if ($field) {
521 require_once('field/'.$field->type.'/field.class.php');
522 $newfield = 'data_field_'.$field->type;
523 $newfield = new $newfield($field, $data);
524 return $newfield;
529 /***************************************************************************
530 * given record id, returns true if the record belongs to the current user *
531 * input @param $rid - record id *
532 * output bool *
533 ***************************************************************************/
534 function data_isowner($rid){
535 global $USER;
536 if (empty($USER->id)) {
537 return false;
540 if ($record = get_record('data_records','id',$rid)) {
541 return ($record->userid == $USER->id);
544 return false;
547 /***********************************************************************
548 * has a user reached the max number of entries? *
549 * input object $data *
550 * output bool *
551 ***********************************************************************/
552 function data_atmaxentries($data) {
553 if (!$data->maxentries) {
554 return false;
555 } else {
556 return (data_numentries($data) >= $data->maxentries);
560 /**********************************************************************
561 * returns the number of entries already made by this user *
562 * input @param object $data *
563 * uses global $CFG, $USER *
564 * output int *
565 **********************************************************************/
566 function data_numentries($data) {
567 global $USER;
568 global $CFG;
569 $sql = 'SELECT COUNT(*) FROM '.$CFG->prefix.'data_records WHERE dataid='.$data->id.' AND userid='.$USER->id;
570 return count_records_sql($sql);
573 /****************************************************************
574 * function that takes in a dataid and adds a record *
575 * this is used everytime an add template is submitted *
576 * input @param int $dataid, $groupid *
577 * output bool *
578 ****************************************************************/
579 function data_add_record($data, $groupid=0) {
580 global $USER;
581 $cm = get_coursemodule_from_instance('data', $data->id);
582 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
583 $record = new object();
584 $record->userid = $USER->id;
585 $record->dataid = $data->id;
586 $record->groupid = $groupid;
587 $record->timecreated = $record->timemodified = time();
588 if (has_capability('mod/data:approve', $context)) {
589 $record->approved = 1;
590 } else {
591 $record->approved = 0;
593 return insert_record('data_records',$record);
596 /*******************************************************************
597 * check the multple existence any tag in a template *
598 * input @param string *
599 * output true-valid, false-invalid *
600 * check to see if there are 2 or more of the same tag being used. *
601 * input @param int $dataid, *
602 * @param string $template *
603 * output bool *
604 *******************************************************************/
605 function data_tags_check($dataid, $template) {
606 // first get all the possible tags
607 $fields = get_records('data_fields','dataid',$dataid);
608 // then we generate strings to replace
609 $tagsok = true; // let's be optimistic
610 foreach ($fields as $field) {
611 $pattern="/\[\[".$field->name."\]\]/i";
612 if (preg_match_all($pattern, $template, $dummy)>1) {
613 $tagsok = false;
614 notify ('[['.$field->name.']] - '.get_string('multipletags','data'));
617 // else return true
618 return $tagsok;
621 /************************************************************************
622 * Adds an instance of a data *
623 ************************************************************************/
624 function data_add_instance($data) {
625 global $CFG;
626 if (empty($data->assessed)) {
627 $data->assessed = 0;
630 $data->timemodified = time();
631 if (! $data->id = insert_record('data', $data)) {
632 return false;
635 $data = stripslashes_recursive($data);
636 data_grade_item_update($data);
637 return $data->id;
640 /************************************************************************
641 * updates an instance of a data *
642 ************************************************************************/
643 function data_update_instance($data) {
644 global $CFG;
645 $data->timemodified = time();
646 $data->id = $data->instance;
648 if (empty($data->assessed)) {
649 $data->assessed = 0;
651 if (empty($data->notification)) {
652 $data->notification = 0;
654 if (! update_record('data', $data)) {
655 return false;
658 $data = stripslashes_recursive($data);
659 data_grade_item_update($data);
660 return true;
663 /************************************************************************
664 * deletes an instance of a data *
665 ************************************************************************/
666 function data_delete_instance($id) { // takes the dataid
668 global $CFG;
669 if (! $data = get_record('data', 'id', $id)) {
670 return false;
673 // Delete all the associated information
674 // get all the records in this data
675 $sql = 'SELECT c.* FROM '.$CFG->prefix.'data_records r LEFT JOIN '.
676 $CFG->prefix.'data_content c ON c.recordid = r.id WHERE r.dataid = '.$id;
678 if ($contents = get_records_sql($sql)) {
679 foreach($contents as $content) {
680 $field = get_record('data_fields','id',$content->fieldid);
681 if ($g = data_get_field($field, $data)) {
682 $g->delete_content_files($id, $content->recordid, $content->content);
684 //delete the content itself
685 delete_records('data_content','id', $content->id);
689 // delete all the records and fields
690 delete_records('data_records', 'dataid', $id);
691 delete_records('data_fields','dataid',$id);
693 // Delete the instance itself
694 $result = delete_records('data', 'id', $id);
695 data_grade_item_delete($data);
696 return $result;
699 /************************************************************************
700 * returns a summary of data activity of this user *
701 ************************************************************************/
702 function data_user_outline($course, $user, $mod, $data) {
703 global $CFG;
704 if ($countrecords = count_records('data_records', 'dataid', $data->id, 'userid', $user->id)) {
705 $result = new object();
706 $result->info = get_string('numrecords', 'data', $countrecords);
707 $lastrecord = get_record_sql('SELECT id,timemodified FROM '.$CFG->prefix.'data_records
708 WHERE dataid = '.$data->id.' AND userid = '.$user->id.'
709 ORDER BY timemodified DESC', true);
710 $result->time = $lastrecord->timemodified;
711 return $result;
713 return NULL;
716 /************************************************************************
717 * Prints all the records uploaded by this user *
718 ************************************************************************/
719 function data_user_complete($course, $user, $mod, $data) {
720 if ($records = get_records_select('data_records', 'dataid = '.$data->id.' AND userid = '.$user->id,
721 'timemodified DESC')) {
722 data_print_template('singletemplate', $records, $data);
727 * Return grade for given user or all users.
729 * @param int $dataid id of data
730 * @param int $userid optional user id, 0 means all users
731 * @return array array of grades, false if none
733 function data_get_user_grades($data, $userid=0) {
734 global $CFG;
735 $user = $userid ? "AND u.id = $userid" : "";
736 $sql = "SELECT u.id, u.id AS userid, avg(drt.rating) AS rawgrade
737 FROM {$CFG->prefix}user u, {$CFG->prefix}data_records dr,
738 {$CFG->prefix}data_ratings drt
739 WHERE u.id = dr.userid AND dr.id = drt.recordid
740 AND drt.userid != u.id AND dr.dataid = $data->id
741 $user
742 GROUP BY u.id";
743 return get_records_sql($sql);
747 * Update grades by firing grade_updated event
749 * @param object $data null means all databases
750 * @param int $userid specific user only, 0 mean all
752 function data_update_grades($data=null, $userid=0, $nullifnone=true) {
753 global $CFG;
754 if (!function_exists('grade_update')) { //workaround for buggy PHP versions
755 require_once($CFG->libdir.'/gradelib.php');
758 if ($data != null) {
759 if ($grades = data_get_user_grades($data, $userid)) {
760 data_grade_item_update($data, $grades);
761 } else if ($userid and $nullifnone) {
762 $grade = new object();
763 $grade->userid = $userid;
764 $grade->rawgrade = NULL;
765 data_grade_item_update($data, $grade);
766 } else {
767 data_grade_item_update($data);
769 } else {
770 $sql = "SELECT d.*, cm.idnumber as cmidnumber
771 FROM {$CFG->prefix}data d, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m
772 WHERE m.name='data' AND m.id=cm.module AND cm.instance=d.id";
773 if ($rs = get_recordset_sql($sql)) {
774 while ($data = rs_fetch_next_record($rs)) {
775 if ($data->assessed) {
776 data_update_grades($data, 0, false);
777 } else {
778 data_grade_item_update($data);
781 rs_close($rs);
787 * Update/create grade item for given data
789 * @param object $data object with extra cmidnumber
790 * @param mixed optional array/object of grade(s); 'reset' means reset grades in gradebook
791 * @return object grade_item
793 function data_grade_item_update($data, $grades=NULL) {
794 global $CFG;
795 if (!function_exists('grade_update')) { //workaround for buggy PHP versions
796 require_once($CFG->libdir.'/gradelib.php');
798 $params = array('itemname'=>$data->name, 'idnumber'=>$data->cmidnumber);
799 if (!$data->assessed or $data->scale == 0) {
800 $params['gradetype'] = GRADE_TYPE_NONE;
801 } else if ($data->scale > 0) {
802 $params['gradetype'] = GRADE_TYPE_VALUE;
803 $params['grademax'] = $data->scale;
804 $params['grademin'] = 0;
805 } else if ($data->scale < 0) {
806 $params['gradetype'] = GRADE_TYPE_SCALE;
807 $params['scaleid'] = -$data->scale;
809 if ($grades === 'reset') {
810 $params['reset'] = true;
811 $grades = NULL;
814 return grade_update('mod/data', $data->course, 'mod', 'data', $data->id, 0, $grades, $params);
818 * Delete grade item for given data
820 * @param object $data object
821 * @return object grade_item
823 function data_grade_item_delete($data) {
824 global $CFG;
825 require_once($CFG->libdir.'/gradelib.php');
826 return grade_update('mod/data', $data->course, 'mod', 'data', $data->id, 0, NULL, array('deleted'=>1));
829 /************************************************************************
830 * returns a list of participants of this database *
831 ************************************************************************/
832 function data_get_participants($dataid) {
833 // Returns the users with data in one data
834 // (users with records in data_records, data_comments and data_ratings)
835 global $CFG;
836 $records = get_records_sql("SELECT DISTINCT u.id, u.id
837 FROM {$CFG->prefix}user u,
838 {$CFG->prefix}data_records r
839 WHERE r.dataid = '$dataid'
840 AND u.id = r.userid");
841 $comments = get_records_sql("SELECT DISTINCT u.id, u.id
842 FROM {$CFG->prefix}user u,
843 {$CFG->prefix}data_records r,
844 {$CFG->prefix}data_comments c
845 WHERE r.dataid = '$dataid'
846 AND u.id = r.userid
847 AND r.id = c.recordid");
848 $ratings = get_records_sql("SELECT DISTINCT u.id, u.id
849 FROM {$CFG->prefix}user u,
850 {$CFG->prefix}data_records r,
851 {$CFG->prefix}data_ratings a
852 WHERE r.dataid = '$dataid'
853 AND u.id = r.userid
854 AND r.id = a.recordid");
855 $participants = array();
856 if ($records) {
857 foreach ($records as $record) {
858 $participants[$record->id] = $record;
861 if ($comments) {
862 foreach ($comments as $comment) {
863 $participants[$comment->id] = $comment;
866 if ($ratings) {
867 foreach ($ratings as $rating) {
868 $participants[$rating->id] = $rating;
871 return $participants;
874 // junk functions
875 /************************************************************************
876 * takes a list of records, the current data, a search string, *
877 * and mode to display prints the translated template *
878 * input @param array $records *
879 * @param object $data *
880 * @param string $search *
881 * @param string $template *
882 * output null *
883 ************************************************************************/
884 function data_print_template($template, $records, $data, $search='',$page=0, $return=false) {
885 global $CFG;
886 $cm = get_coursemodule_from_instance('data', $data->id);
887 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
888 static $fields = NULL;
889 static $isteacher;
890 static $dataid = NULL;
891 if (empty($dataid)) {
892 $dataid = $data->id;
893 } else if ($dataid != $data->id) {
894 $fields = NULL;
896 if (empty($fields)) {
897 $fieldrecords = get_records('data_fields','dataid', $data->id);
898 foreach ($fieldrecords as $fieldrecord) {
899 $fields[]= data_get_field($fieldrecord, $data);
901 $isteacher = has_capability('mod/data:managetemplates', $context);
903 if (empty($records)) {
904 return;
906 foreach ($records as $record) { // Might be just one for the single template
907 // Replacing tags
908 $patterns = array();
909 $replacement = array();
910 // Then we generate strings to replace for normal tags
911 foreach ($fields as $field) {
912 $patterns[]='[['.$field->field->name.']]';
913 $replacement[] = highlight($search, $field->display_browse_field($record->id, $template));
915 // Replacing special tags (##Edit##, ##Delete##, ##More##)
916 $patterns[]='##edit##';
917 $patterns[]='##delete##';
918 if (has_capability('mod/data:manageentries', $context) or data_isowner($record->id)) {
919 $replacement[] = '<a href="'.$CFG->wwwroot.'/mod/data/edit.php?d='
920 .$data->id.'&amp;rid='.$record->id.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/edit.gif" class="iconsmall" alt="'.get_string('edit').'" title="'.get_string('edit').'" /></a>';
921 $replacement[] = '<a href="'.$CFG->wwwroot.'/mod/data/view.php?d='
922 .$data->id.'&amp;delete='.$record->id.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/delete.gif" class="iconsmall" alt="'.get_string('delete').'" title="'.get_string('delete').'" /></a>';
923 } else {
924 $replacement[] = '';
925 $replacement[] = '';
927 $patterns[]='##more##';
928 $replacement[] = '<a href="'.$CFG->wwwroot.'/mod/data/view.php?d='.$data->id.'&amp;rid='.$record->id.'"><img src="'.$CFG->pixpath.'/i/search.gif" class="iconsmall" alt="'.get_string('more', 'data').'" title="'.get_string('more', 'data').'" /></a>';
930 $patterns[]='##moreurl##';
931 $replacement[] = $CFG->wwwroot.'/mod/data/view.php?d='.$data->id.'&amp;rid='.$record->id;
933 $patterns[]='##user##';
934 $replacement[] = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$record->userid.
935 '&amp;course='.$data->course.'">'.fullname($record).'</a>';
937 $patterns[] = '##timeadded##';
938 $replacement[] = userdate($record->timecreated);
940 $patterns[] = '##timemodified##';
941 $replacement [] = userdate($record->timemodified);
943 $patterns[]='##approve##';
944 if (has_capability('mod/data:approve', $context) && ($data->approval) && (!$record->approved)) {
945 $replacement[] = '<span class="approve"><a href="'.$CFG->wwwroot.'/mod/data/view.php?d='.$data->id.'&amp;approve='.$record->id.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/i/approve.gif" class="icon" alt="'.get_string('approve').'" /></a></span>';
946 } else {
947 $replacement[] = '';
950 $patterns[]='##comments##';
951 if (($template == 'listtemplate') && ($data->comments)) {
952 $comments = count_records('data_comments','recordid',$record->id);
953 $replacement[] = '<a href="view.php?rid='.$record->id.'#comments">'.get_string('commentsn','data', $comments).'</a>';
954 } else {
955 $replacement[] = '';
958 // actual replacement of the tags
959 $newtext = str_ireplace($patterns, $replacement, $data->{$template});
961 // no more html formatting and filtering - see MDL-6635
962 if ($return) {
963 return $newtext;
964 } else {
965 echo $newtext;
966 // hack alert - return is always false in singletemplate anyway ;-)
967 /**********************************
968 * Printing Ratings Form *
969 *********************************/
970 if ($template == 'singletemplate') { //prints ratings options
971 data_print_ratings($data, $record);
973 /**********************************
974 * Printing Ratings Form *
975 *********************************/
976 if (($template == 'singletemplate') && ($data->comments)) { //prints ratings options
977 data_print_comments($data, $record, $page);
984 /************************************************************************
985 * function that takes in the current data, number of items per page, *
986 * a search string and prints a preference box in view.php *
988 * This preference box prints a searchable advanced search template if *
989 * a) A template is defined *
990 * b) The advanced search checkbox is checked. *
992 * input @param object $data *
993 * @param int $perpage *
994 * @param string $search *
995 * output null *
996 ************************************************************************/
997 function data_print_preference_form($data, $perpage, $search, $sort='', $order='ASC', $search_array = '', $advanced = 0, $mode= '') {
998 global $CFG;
999 $cm = get_coursemodule_from_instance('data', $data->id);
1000 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
1001 echo '<br /><div class="datapreferences">';
1002 echo '<form id="options" action="view.php" method="get">';
1003 echo '<div>';
1004 echo '<input type="hidden" name="d" value="'.$data->id.'" />';
1005 if ($mode =='asearch') {
1006 $advanced = 1;
1007 echo '<input type="hidden" name="mode" value="list" />';
1009 echo '<label for="pref_perpage">'.get_string('pagesize','data').'</label> ';
1010 $pagesizes = array(2=>2,3=>3,4=>4,5=>5,6=>6,7=>7,8=>8,9=>9,10=>10,15=>15,
1011 20=>20,30=>30,40=>40,50=>50,100=>100,200=>200,300=>300,400=>400,500=>500,1000=>1000);
1012 choose_from_menu($pagesizes, 'perpage', $perpage, '', '', '0', false, false, 0, 'pref_perpage');
1013 echo '<div id="reg_search" style="display: ';
1014 if ($advanced) {
1015 echo 'none';
1017 else {
1018 echo 'inline';
1020 echo ';" >&nbsp;&nbsp;&nbsp;<label for="pref_search">'.get_string('search').'</label> <input type="text" size="16" name="search" id= "pref_search" value="'.s($search).'" /></div>';
1021 echo '&nbsp;&nbsp;&nbsp;<label for="pref_sortby">'.get_string('sortby').'</label> ';
1022 // foreach field, print the option
1023 echo '<select name="sort" id="pref_sortby">';
1024 if ($fields = get_records('data_fields','dataid',$data->id, 'name')) {
1025 echo '<optgroup label="'.get_string('fields', 'data').'">';
1026 foreach ($fields as $field) {
1027 if ($field->id == $sort) {
1028 echo '<option value="'.$field->id.'" selected="selected">'.$field->name.'</option>';
1029 } else {
1030 echo '<option value="'.$field->id.'">'.$field->name.'</option>';
1033 echo '</optgroup>';
1035 $options = array();
1036 $options[DATA_TIMEADDED] = get_string('timeadded', 'data');
1037 $options[DATA_TIMEMODIFIED] = get_string('timemodified', 'data');
1038 $options[DATA_FIRSTNAME] = get_string('authorfirstname', 'data');
1039 $options[DATA_LASTNAME] = get_string('authorlastname', 'data');
1040 if ($data->approval and has_capability('mod/data:approve', $context)) {
1041 $options[DATA_APPROVED] = get_string('approved', 'data');
1043 echo '<optgroup label="'.get_string('other', 'data').'">';
1044 foreach ($options as $key => $name) {
1045 if ($key == $sort) {
1046 echo '<option value="'.$key.'" selected="selected">'.$name.'</option>';
1047 } else {
1048 echo '<option value="'.$key.'">'.$name.'</option>';
1051 echo '</optgroup>';
1052 echo '</select>';
1053 echo '<label for="pref_order" class="accesshide">'.get_string('order').'</label>';
1054 echo '<select id="pref_order" name="order">';
1055 if ($order == 'ASC') {
1056 echo '<option value="ASC" selected="selected">'.get_string('ascending','data').'</option>';
1057 } else {
1058 echo '<option value="ASC">'.get_string('ascending','data').'</option>';
1060 if ($order == 'DESC') {
1061 echo '<option value="DESC" selected="selected">'.get_string('descending','data').'</option>';
1062 } else {
1063 echo '<option value="DESC">'.get_string('descending','data').'</option>';
1065 echo '</select>';
1067 if ($advanced) {
1068 $checked = ' checked="checked" ';
1070 else {
1071 $checked = '';
1073 print '
1074 <script type="text/javascript">
1075 //<![CDATA[
1076 <!-- Start
1077 // javascript for hiding/displaying advanced search form
1079 function showHideAdvSearch(checked) {
1080 var divs = document.getElementsByTagName(\'div\');
1081 for(i=0;i<divs.length;i++) {
1082 if(divs[i].id.match(\'data_adv_form\')) {
1083 if(checked) {
1084 divs[i].style.display = \'inline\';
1086 else {
1087 divs[i].style.display = \'none\';
1090 else if (divs[i].id.match(\'reg_search\')) {
1091 if (!checked) {
1092 divs[i].style.display = \'inline\';
1094 else {
1095 divs[i].style.display = \'none\';
1100 // End -->
1101 //]]>
1102 </script>';
1103 echo '&nbsp;<input type="hidden" name="advanced" value="0" />';
1104 echo '&nbsp;<input type="checkbox" id="advancedcheckbox" name="advanced" value="1" '.$checked.' onchange="showHideAdvSearch(this.checked);" /><label for="advancedcheckbox">'.get_string('advancedsearch', 'data').'</label>';
1105 echo '&nbsp;<input type="submit" value="'.get_string('savesettings','data').'" />';
1106 echo '<br />';
1107 echo '<div class="dataadvancedsearch" id="data_adv_form" style="display: ';
1108 if ($advanced) {
1109 echo 'inline';
1111 else {
1112 echo 'none';
1114 echo ';margin-left:auto;margin-right:auto;" >';
1115 echo '<table class="boxaligncenter">';
1116 // print ASC or DESC
1117 echo '<tr><td colspan="2">&nbsp;</td></tr>';
1118 $i = 0;
1120 // Determine if we are printing all fields for advanced search, or the template for advanced search
1121 // If a template is not defined, use the deafault template and display all fields.
1122 if(empty($data->asearchtemplate)) {
1123 data_generate_default_template($data, 'asearchtemplate');
1126 static $fields = NULL;
1127 static $isteacher;
1128 static $dataid = NULL;
1129 if (empty($dataid)) {
1130 $dataid = $data->id;
1131 } else if ($dataid != $data->id) {
1132 $fields = NULL;
1135 if (empty($fields)) {
1136 $fieldrecords = get_records('data_fields','dataid', $data->id);
1137 foreach ($fieldrecords as $fieldrecord) {
1138 $fields[]= data_get_field($fieldrecord, $data);
1140 $isteacher = has_capability('mod/data:managetemplates', $context);
1143 // Replacing tags
1144 $patterns = array();
1145 $replacement = array();
1147 // Then we generate strings to replace for normal tags
1148 foreach ($fields as $field) {
1149 $fieldname = $field->field->name;
1150 $fieldname = preg_quote($fieldname, '/');
1151 $patterns[] = "/\[\[$fieldname\]\]/i";
1152 $searchfield = data_get_field_from_id($field->field->id, $data);
1153 if (!empty($search_array[$field->field->id]->data)) {
1154 $replacement[] = $searchfield->display_search_field($search_array[$field->field->id]->data);
1155 } else {
1156 $replacement[] = $searchfield->display_search_field();
1159 $fn = !empty($search_array[DATA_FIRSTNAME]->data) ? $search_array[DATA_FIRSTNAME]->data : '';
1160 $ln = !empty($search_array[DATA_LASTNAME]->data) ? $search_array[DATA_LASTNAME]->data : '';
1161 $patterns[] = '/##firstname##/';
1162 $replacement[] = '<input type="text" size="16" name="u_fn" value="'.$fn.'" />';
1163 $patterns[] = '/##lastname##/';
1164 $replacement[] = '<input type="text" size="16" name="u_ln" value="'.$ln.'" />';
1166 // actual replacement of the tags
1167 $newtext = preg_replace($patterns, $replacement, $data->asearchtemplate);
1168 $options = new object();
1169 $options->para=false;
1170 $options->noclean=true;
1171 echo '<tr><td>';
1172 echo format_text($newtext, FORMAT_HTML, $options);
1173 echo '</td></tr>';
1174 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>';
1175 echo '</table>';
1176 echo '</div>';
1177 echo '</div>';
1178 echo '</form>';
1179 echo '</div>';
1182 function data_print_ratings($data, $record) {
1183 global $USER;
1185 $cm = get_coursemodule_from_instance('data', $data->id);
1186 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
1187 if ($data->assessed and !empty($USER->id) and (has_capability('mod/data:rate', $context) or has_capability('mod/data:viewrating', $context) or data_isowner($record->id))) {
1188 if ($ratingsscale = make_grades_menu($data->scale)) {
1189 $ratingsmenuused = false;
1190 echo '<div class="ratings" style="text-align:center">';
1191 echo '<form id="form" method="post" action="rate.php">';
1192 echo '<input type="hidden" name="dataid" value="'.$data->id.'" />';
1193 if (has_capability('mod/data:rate', $context) and !data_isowner($record->id)) {
1194 data_print_ratings_mean($record->id, $ratingsscale, has_capability('mod/data:viewrating', $context));
1195 echo '&nbsp;';
1196 data_print_rating_menu($record->id, $USER->id, $ratingsscale);
1197 $ratingsmenuused = true;
1198 } else {
1199 data_print_ratings_mean($record->id, $ratingsscale, true);
1201 if ($data->scale < 0) {
1202 if ($scale = get_record('scale', 'id', abs($data->scale))) {
1203 print_scale_menu_helpbutton($data->course, $scale );
1207 if ($ratingsmenuused) {
1208 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
1209 echo '<input type="submit" value="'.get_string('sendinratings', 'data').'" />';
1211 echo '</form>';
1212 echo '</div>';
1217 function data_print_ratings_mean($recordid, $scale, $link=true) {
1218 // Print the multiple ratings on a post given to the current user by others.
1219 // Scale is an array of ratings
1221 static $strrate;
1222 $mean = data_get_ratings_mean($recordid, $scale);
1223 if ($mean !== "") {
1224 if (empty($strratings)) {
1225 $strratings = get_string("ratings", "data");
1227 echo "$strratings: ";
1228 if ($link) {
1229 link_to_popup_window ("/mod/data/report.php?id=$recordid", "ratings", $mean, 400, 600);
1230 } else {
1231 echo "$mean ";
1237 function data_get_ratings_mean($recordid, $scale, $ratings=NULL) {
1238 // Return the mean rating of a post given to the current user by others.
1239 // Scale is an array of possible ratings in the scale
1240 // Ratings is an optional simple array of actual ratings (just integers)
1241 if (!$ratings) {
1242 $ratings = array();
1243 if ($rates = get_records("data_ratings", "recordid", $recordid)) {
1244 foreach ($rates as $rate) {
1245 $ratings[] = $rate->rating;
1249 $count = count($ratings);
1250 if ($count == 0) {
1251 return "";
1252 } else if ($count == 1) {
1253 return $scale[$ratings[0]];
1254 } else {
1255 $total = 0;
1256 foreach ($ratings as $rating) {
1257 $total += $rating;
1259 $mean = round( ((float)$total/(float)$count) + 0.001); // Little fudge factor so that 0.5 goes UP
1260 if (isset($scale[$mean])) {
1261 return $scale[$mean]." ($count)";
1262 } else {
1263 return "$mean ($count)"; // Should never happen, hopefully
1269 function data_print_rating_menu($recordid, $userid, $scale) {
1270 // Print the menu of ratings as part of a larger form.
1271 // If the post has already been - set that value.
1272 // Scale is an array of ratings
1273 static $strrate;
1274 if (!$rating = get_record("data_ratings", "userid", $userid, "recordid", $recordid)) {
1275 $rating->rating = -999;
1277 if (empty($strrate)) {
1278 $strrate = get_string("rate", "data");
1280 choose_from_menu($scale, $recordid, $rating->rating, "$strrate...", '', -999);
1284 function data_get_ratings($recordid, $sort="u.firstname ASC") {
1285 // Returns a list of ratings for a particular post - sorted.
1286 global $CFG;
1287 return get_records_sql("SELECT u.*, r.rating
1288 FROM {$CFG->prefix}data_ratings r,
1289 {$CFG->prefix}user u
1290 WHERE r.recordid = $recordid
1291 AND r.userid = u.id
1292 ORDER BY $sort");
1296 // prints all comments + a text box for adding additional comment
1297 function data_print_comments($data, $record, $page=0, $mform=false) {
1298 global $CFG;
1299 echo '<a name="comments"></a>';
1300 if ($comments = get_records('data_comments','recordid',$record->id)) {
1301 foreach ($comments as $comment) {
1302 data_print_comment($data, $comment, $page);
1304 echo '<br />';
1306 if (!isloggedin() or isguest()) {
1307 return;
1309 $editor = optional_param('addcomment', 0, PARAM_BOOL);
1310 if (!$mform and !$editor) {
1311 echo '<div class="newcomment" style="text-align:center">';
1312 echo '<a href="view.php?d='.$data->id.'&amp;page='.$page.'&amp;mode=single&amp;addcomment=1">'.get_string('addcomment', 'data').'</a>';
1313 echo '</div>';
1314 } else {
1315 if (!$mform) {
1316 require_once('comment_form.php');
1317 $mform = new mod_data_comment_form('comment.php');
1318 $mform->set_data(array('mode'=>'add', 'page'=>$page, 'rid'=>$record->id));
1320 echo '<div class="newcomment" style="text-align:center">';
1321 $mform->display();
1322 echo '</div>';
1326 // prints a single comment entry
1327 function data_print_comment($data, $comment, $page=0) {
1328 global $USER, $CFG;
1329 $cm = get_coursemodule_from_instance('data', $data->id);
1330 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
1331 $stredit = get_string('edit');
1332 $strdelete = get_string('delete');
1333 $user = get_record('user','id',$comment->userid);
1334 echo '<table cellspacing="0" align="center" width="50%" class="datacomment forumpost">';
1335 echo '<tr class="header"><td class="picture left">';
1336 print_user_picture($user, $data->course, $user->picture);
1337 echo '</td>';
1338 echo '<td class="topic starter" align="left"><div class="author">';
1339 $fullname = fullname($user, has_capability('moodle/site:viewfullnames', $context));
1340 $by = new object();
1341 $by->name = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.
1342 $user->id.'&amp;course='.$data->course.'">'.$fullname.'</a>';
1343 $by->date = userdate($comment->modified);
1344 print_string('bynameondate', 'data', $by);
1345 echo '</div></td></tr>';
1346 echo '<tr><td class="left side">';
1347 if ($groups = groups_get_all_groups($data->course, $comment->userid, $cm->groupingid)) {
1348 print_group_picture($groups, $data->course, false, false, true);
1349 } else {
1350 echo '&nbsp;';
1353 // Actual content
1354 echo '</td><td class="content" align="left">'."\n";
1355 // Print whole message
1356 echo format_text($comment->content, $comment->format);
1358 // Commands
1359 echo '<div class="commands">';
1360 if (data_isowner($comment->recordid) or has_capability('mod/data:managecomments', $context)) {
1361 echo '<a href="'.$CFG->wwwroot.'/mod/data/comment.php?rid='.$comment->recordid.'&amp;mode=edit&amp;commentid='.$comment->id.'&amp;page='.$page.'">'.$stredit.'</a>';
1362 echo '| <a href="'.$CFG->wwwroot.'/mod/data/comment.php?rid='.$comment->recordid.'&amp;mode=delete&amp;commentid='.$comment->id.'&amp;page='.$page.'">'.$strdelete.'</a>';
1365 echo '</div>';
1366 echo '</td></tr></table>'."\n\n";
1370 // For Participantion Reports
1371 function data_get_view_actions() {
1372 return array('view');
1375 function data_get_post_actions() {
1376 return array('add','update','record delete');
1379 function data_fieldname_exists($name, $dataid, $fieldid=0) {
1380 global $CFG;
1381 $LIKE = sql_ilike();
1382 if ($fieldid) {
1383 return record_exists_sql("SELECT * from {$CFG->prefix}data_fields df
1384 WHERE df.name $LIKE '$name' AND df.dataid = $dataid
1385 AND ((df.id < $fieldid) OR (df.id > $fieldid))");
1386 } else {
1387 return record_exists_sql("SELECT * from {$CFG->prefix}data_fields df
1388 WHERE df.name $LIKE '$name' AND df.dataid = $dataid");
1392 function data_convert_arrays_to_strings(&$fieldinput) {
1393 foreach ($fieldinput as $key => $val) {
1394 if (is_array($val)) {
1395 $str = '';
1396 foreach ($val as $inner) {
1397 $str .= $inner . ',';
1399 $str = substr($str, 0, -1);
1400 $fieldinput->$key = $str;
1407 * Converts a database (module instance) to use the Roles System
1408 * @param $data - a data object with the same attributes as a record
1409 * from the data database table
1410 * @param $datamodid - the id of the data module, from the modules table
1411 * @param $teacherroles - array of roles that have moodle/legacy:teacher
1412 * @param $studentroles - array of roles that have moodle/legacy:student
1413 * @param $guestroles - array of roles that have moodle/legacy:guest
1414 * @param $cmid - the course_module id for this data instance
1415 * @return boolean - data module was converted or not
1417 function data_convert_to_roles($data, $teacherroles=array(), $studentroles=array(), $cmid=NULL) {
1418 global $CFG;
1419 if (!isset($data->participants) && !isset($data->assesspublic)
1420 && !isset($data->groupmode)) {
1421 // We assume that this database has already been converted to use the
1422 // Roles System. above fields get dropped the data module has been
1423 // upgraded to use Roles.
1424 return false;
1426 if (empty($cmid)) {
1427 // We were not given the course_module id. Try to find it.
1428 if (!$cm = get_coursemodule_from_instance('data', $data->id)) {
1429 notify('Could not get the course module for the data');
1430 return false;
1431 } else {
1432 $cmid = $cm->id;
1435 $context = get_context_instance(CONTEXT_MODULE, $cmid);
1437 // $data->participants:
1438 // 1 - Only teachers can add entries
1439 // 3 - Teachers and students can add entries
1440 switch ($data->participants) {
1441 case 1:
1442 foreach ($studentroles as $studentrole) {
1443 assign_capability('mod/data:writeentry', CAP_PREVENT, $studentrole->id, $context->id);
1445 foreach ($teacherroles as $teacherrole) {
1446 assign_capability('mod/data:writeentry', CAP_ALLOW, $teacherrole->id, $context->id);
1448 break;
1449 case 3:
1450 foreach ($studentroles as $studentrole) {
1451 assign_capability('mod/data:writeentry', CAP_ALLOW, $studentrole->id, $context->id);
1453 foreach ($teacherroles as $teacherrole) {
1454 assign_capability('mod/data:writeentry', CAP_ALLOW, $teacherrole->id, $context->id);
1456 break;
1459 // $data->assessed:
1460 // 2 - Only teachers can rate posts
1461 // 1 - Everyone can rate posts
1462 // 0 - No one can rate posts
1463 switch ($data->assessed) {
1464 case 0:
1465 foreach ($studentroles as $studentrole) {
1466 assign_capability('mod/data:rate', CAP_PREVENT, $studentrole->id, $context->id);
1468 foreach ($teacherroles as $teacherrole) {
1469 assign_capability('mod/data:rate', CAP_PREVENT, $teacherrole->id, $context->id);
1471 break;
1472 case 1:
1473 foreach ($studentroles as $studentrole) {
1474 assign_capability('mod/data:rate', CAP_ALLOW, $studentrole->id, $context->id);
1476 foreach ($teacherroles as $teacherrole) {
1477 assign_capability('mod/data:rate', CAP_ALLOW, $teacherrole->id, $context->id);
1479 break;
1480 case 2:
1481 foreach ($studentroles as $studentrole) {
1482 assign_capability('mod/data:rate', CAP_PREVENT, $studentrole->id, $context->id);
1484 foreach ($teacherroles as $teacherrole) {
1485 assign_capability('mod/data:rate', CAP_ALLOW, $teacherrole->id, $context->id);
1487 break;
1490 // $data->assesspublic:
1491 // 0 - Students can only see their own ratings
1492 // 1 - Students can see everyone's ratings
1493 switch ($data->assesspublic) {
1494 case 0:
1495 foreach ($studentroles as $studentrole) {
1496 assign_capability('mod/data:viewrating', CAP_PREVENT, $studentrole->id, $context->id);
1498 foreach ($teacherroles as $teacherrole) {
1499 assign_capability('mod/data:viewrating', CAP_ALLOW, $teacherrole->id, $context->id);
1501 break;
1502 case 1:
1503 foreach ($studentroles as $studentrole) {
1504 assign_capability('mod/data:viewrating', CAP_ALLOW, $studentrole->id, $context->id);
1506 foreach ($teacherroles as $teacherrole) {
1507 assign_capability('mod/data:viewrating', CAP_ALLOW, $teacherrole->id, $context->id);
1509 break;
1512 if (empty($cm)) {
1513 $cm = get_record('course_modules', 'id', $cmid);
1516 switch ($cm->groupmode) {
1517 case NOGROUPS:
1518 break;
1519 case SEPARATEGROUPS:
1520 foreach ($studentroles as $studentrole) {
1521 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $studentrole->id, $context->id);
1523 foreach ($teacherroles as $teacherrole) {
1524 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $teacherrole->id, $context->id);
1526 break;
1527 case VISIBLEGROUPS:
1528 foreach ($studentroles as $studentrole) {
1529 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $studentrole->id, $context->id);
1531 foreach ($teacherroles as $teacherrole) {
1532 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $teacherrole->id, $context->id);
1534 break;
1536 return true;
1540 * Returns the best name to show for a preset
1542 function data_preset_name($shortname, $path) {
1544 // We are looking inside the preset itself as a first choice, but also in normal data directory
1545 $string = get_string('modulename', 'datapreset_'.$shortname);
1547 if (substr($string, 0, 1) == '[') {
1548 return $shortname;
1549 } else {
1550 return $string;
1555 * Returns an array of all the available presets
1557 function data_get_available_presets($context) {
1558 global $CFG, $USER;
1559 $presets = array();
1560 if ($dirs = get_list_of_plugins('mod/data/preset')) {
1561 foreach ($dirs as $dir) {
1562 $fulldir = $CFG->dirroot.'/mod/data/preset/'.$dir;
1563 if (is_directory_a_preset($fulldir)) {
1564 $preset = new object;
1565 $preset->path = $fulldir;
1566 $preset->userid = 0;
1567 $preset->shortname = $dir;
1568 $preset->name = data_preset_name($dir, $fulldir);
1569 if (file_exists($fulldir.'/screenshot.jpg')) {
1570 $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.jpg';
1571 } else if (file_exists($fulldir.'/screenshot.png')) {
1572 $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.png';
1573 } else if (file_exists($fulldir.'/screenshot.gif')) {
1574 $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.gif';
1576 $presets[] = $preset;
1581 if ($userids = get_list_of_plugins('data/preset', '', $CFG->dataroot)) {
1582 foreach ($userids as $userid) {
1583 $fulldir = $CFG->dataroot.'/data/preset/'.$userid;
1584 if ($userid == 0 || $USER->id == $userid || has_capability('mod/data:viewalluserpresets', $context)) {
1585 if ($dirs = get_list_of_plugins('data/preset/'.$userid, '', $CFG->dataroot)) {
1586 foreach ($dirs as $dir) {
1587 $fulldir = $CFG->dataroot.'/data/preset/'.$userid.'/'.$dir;
1588 if (is_directory_a_preset($fulldir)) {
1589 $preset = new object;
1590 $preset->path = $fulldir;
1591 $preset->userid = $userid;
1592 $preset->shortname = $dir;
1593 $preset->name = data_preset_name($dir, $fulldir);
1594 if (file_exists($fulldir.'/screenshot.jpg')) {
1595 $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.jpg';
1596 } else if (file_exists($fulldir.'/screenshot.png')) {
1597 $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.png';
1598 } else if (file_exists($fulldir.'/screenshot.gif')) {
1599 $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.gif';
1601 $presets[] = $preset;
1608 return $presets;
1612 function data_print_header($course, $cm, $data, $currenttab='') {
1613 global $CFG, $displaynoticegood, $displaynoticebad;
1614 $navigation = build_navigation('', $cm);
1615 print_header_simple($data->name, '', $navigation,
1616 '', '', true, update_module_button($cm->id, $course->id, get_string('modulename', 'data')),
1617 navmenu($course, $cm));
1618 print_heading(format_string($data->name));
1620 // Groups needed for Add entry tab
1621 $currentgroup = groups_get_activity_group($cm);
1622 $groupmode = groups_get_activity_groupmode($cm);
1623 // Print the tabs
1624 if ($currenttab) {
1625 include('tabs.php');
1627 // Print any notices
1628 if (!empty($displaynoticegood)) {
1629 notify($displaynoticegood, 'notifysuccess'); // good (usually green)
1630 } else if (!empty($displaynoticebad)) {
1631 notify($displaynoticebad); // bad (usuually red)
1635 function data_user_can_add_entry($data, $currentgroup, $groupmode) {
1636 global $USER;
1637 if (!$cm = get_coursemodule_from_instance('data', $data->id)) {
1638 error('Course Module ID was incorrect');
1640 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
1641 if (!has_capability('mod/data:writeentry', $context) and !has_capability('mod/data:manageentries',$context)) {
1642 return false;
1644 if (!$groupmode or has_capability('moodle/site:accessallgroups', $context)) {
1645 return true;
1648 if ($currentgroup) {
1649 return groups_is_member($currentgroup);
1650 } else {
1651 //else it might be group 0 in visible mode
1652 if ($groupmode == VISIBLEGROUPS){
1653 return true;
1654 } else {
1655 return false;
1661 function is_directory_a_preset($directory) {
1662 $directory = rtrim($directory, '/\\') . '/';
1663 $status = file_exists($directory.'singletemplate.html') &&
1664 file_exists($directory.'listtemplate.html') &&
1665 file_exists($directory.'listtemplateheader.html') &&
1666 file_exists($directory.'listtemplatefooter.html') &&
1667 file_exists($directory.'addtemplate.html') &&
1668 file_exists($directory.'rsstemplate.html') &&
1669 file_exists($directory.'rsstitletemplate.html') &&
1670 file_exists($directory.'csstemplate.css') &&
1671 file_exists($directory.'jstemplate.js') &&
1672 file_exists($directory.'preset.xml');
1673 return $status;
1677 function clean_preset($folder) {
1678 $status = @unlink($folder.'/singletemplate.html') &&
1679 @unlink($folder.'/listtemplate.html') &&
1680 @unlink($folder.'/listtemplateheader.html') &&
1681 @unlink($folder.'/listtemplatefooter.html') &&
1682 @unlink($folder.'/addtemplate.html') &&
1683 @unlink($folder.'/rsstemplate.html') &&
1684 @unlink($folder.'/rsstitletemplate.html') &&
1685 @unlink($folder.'/csstemplate.css') &&
1686 @unlink($folder.'/jstemplate.js') &&
1687 @unlink($folder.'/preset.xml');
1689 // optional
1690 @unlink($folder.'/asearchtemplate.html');
1691 return $status;
1695 class PresetImporter {
1696 function PresetImporter($course, $cm, $data, $userid, $shortname) {
1697 global $CFG;
1698 $this->course = $course;
1699 $this->cm = $cm;
1700 $this->data = $data;
1701 $this->userid = $userid;
1702 $this->shortname = $shortname;
1703 $this->folder = data_preset_path($course, $userid, $shortname);
1706 function get_settings() {
1707 global $CFG;
1709 if (!is_directory_a_preset($this->folder)) {
1710 error("$this->userid/$this->shortname Not a preset");
1713 /* Grab XML */
1714 $presetxml = file_get_contents($this->folder.'/preset.xml');
1715 $parsedxml = xmlize($presetxml, 0);
1717 $allowed_settings = array('intro', 'comments', 'requiredentries', 'requiredentriestoview',
1718 'maxentries', 'rssarticles', 'approval', 'defaultsortdir', 'defaultsort');
1720 /* First, do settings. Put in user friendly array. */
1721 $settingsarray = $parsedxml['preset']['#']['settings'][0]['#'];
1722 $settings = new StdClass();
1724 foreach ($settingsarray as $setting => $value) {
1725 if (!is_array($value)) {
1726 continue;
1728 if (!in_array($setting, $allowed_settings)) {
1729 // unsupported setting
1730 continue;
1732 $settings->$setting = $value[0]['#'];
1735 /* Now work out fields to user friendly array */
1736 $fieldsarray = $parsedxml['preset']['#']['field'];
1737 $fields = array();
1738 foreach ($fieldsarray as $field) {
1739 if (!is_array($field)) {
1740 continue;
1742 $f = new StdClass();
1743 foreach ($field['#'] as $param => $value) {
1744 if (!is_array($value)) {
1745 continue;
1747 $f->$param = addslashes($value[0]['#']);
1749 $f->dataid = $this->data->id;
1750 $f->type = clean_param($f->type, PARAM_ALPHA);
1751 $fields[] = $f;
1753 /* Now add the HTML templates to the settings array so we can update d */
1754 $settings->singletemplate = file_get_contents($this->folder."/singletemplate.html");
1755 $settings->listtemplate = file_get_contents($this->folder."/listtemplate.html");
1756 $settings->listtemplateheader = file_get_contents($this->folder."/listtemplateheader.html");
1757 $settings->listtemplatefooter = file_get_contents($this->folder."/listtemplatefooter.html");
1758 $settings->addtemplate = file_get_contents($this->folder."/addtemplate.html");
1759 $settings->rsstemplate = file_get_contents($this->folder."/rsstemplate.html");
1760 $settings->rsstitletemplate = file_get_contents($this->folder."/rsstitletemplate.html");
1761 $settings->csstemplate = file_get_contents($this->folder."/csstemplate.css");
1762 $settings->jstemplate = file_get_contents($this->folder."/jstemplate.js");
1764 //optional
1765 if (file_exists($this->folder."/asearchtemplate.html")) {
1766 $settings->asearchtemplate = file_get_contents($this->folder."/asearchtemplate.html");
1767 } else {
1768 $settings->asearchtemplate = NULL;
1771 $settings->instance = $this->data->id;
1773 /* Now we look at the current structure (if any) to work out whether we need to clear db
1774 or save the data */
1775 if (!$currentfields = get_records('data_fields', 'dataid', $this->data->id)) {
1776 $currentfields = array();
1779 return array($settings, $fields, $currentfields);
1782 function import_options() {
1783 if (!confirm_sesskey()) {
1784 error("Sesskey Invalid");
1786 $strblank = get_string('blank', 'data');
1787 $strcontinue = get_string('continue');
1788 $strwarning = get_string('mappingwarning', 'data');
1789 $strfieldmappings = get_string('fieldmappings', 'data');
1790 $strnew = get_string('new');
1791 $sesskey = sesskey();
1792 list($settings, $newfields, $currentfields) = $this->get_settings();
1793 echo '<div class="presetmapping"><form action="preset.php" method="post">';
1794 echo '<div>';
1795 echo '<input type="hidden" name="action" value="finishimport" />';
1796 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
1797 echo '<input type="hidden" name="d" value="'.$this->data->id.'" />';
1798 echo '<input type="hidden" name="fullname" value="'.$this->userid.'/'.$this->shortname.'" />';
1799 if (!empty($currentfields) && !empty($newfields)) {
1800 echo "<h3>$strfieldmappings ";
1801 helpbutton('fieldmappings', $strfieldmappings, 'data');
1802 echo '</h3><table>';
1803 foreach ($newfields as $nid => $newfield) {
1804 echo "<tr><td><label for=\"id_$newfield->name\">$newfield->name</label></td>";
1805 echo '<td><select name="field_'.$nid.'" id="id_'.$newfield->name.'">';
1806 $selected = false;
1807 foreach ($currentfields as $cid => $currentfield) {
1808 if ($currentfield->type == $newfield->type) {
1809 if ($currentfield->name == $newfield->name) {
1810 echo '<option value="'.$cid.'" selected="selected">'.$currentfield->name.'</option>';
1811 $selected=true;
1813 else {
1814 echo '<option value="'.$cid.'">'.$currentfield->name.'</option>';
1818 if ($selected)
1819 echo '<option value="-1">-</option>';
1820 else
1821 echo '<option value="-1" selected="selected">-</option>';
1822 echo '</select></td></tr>';
1824 echo '</table>';
1825 echo "<p>$strwarning</p>";
1826 } else if (empty($newfields)) {
1827 error("New preset has no defined fields!");
1829 echo '<div class="overwritesettings"><label for="overwritesettings">'.get_string('overwritesettings', 'data').'</label>';
1830 echo '<input id="overwritesettings" name="overwritesettings" type="checkbox" /></label></div>';
1831 echo '<input class="button" type="submit" value="'.$strcontinue.'" /></div></form></div>';
1834 function import() {
1835 global $CFG;
1836 list($settings, $newfields, $currentfields) = $this->get_settings();
1837 $preservedfields = array();
1838 $overwritesettings = optional_param('overwritesettings', 0, PARAM_BOOL);
1839 /* Maps fields and makes new ones */
1840 if (!empty($newfields)) {
1841 /* We require an injective mapping, and need to know what to protect */
1842 foreach ($newfields as $nid => $newfield) {
1843 $cid = optional_param("field_$nid", -1, PARAM_INT);
1844 if ($cid == -1) continue;
1845 if (array_key_exists($cid, $preservedfields)) error("Not an injective map");
1846 else $preservedfields[$cid] = true;
1848 foreach ($newfields as $nid => $newfield) {
1849 $cid = optional_param("field_$nid", -1, PARAM_INT);
1850 /* A mapping. Just need to change field params. Data kept. */
1851 if ($cid != -1 and isset($currentfields[$cid])) {
1852 $fieldobject = data_get_field_from_id($currentfields[$cid]->id, $this->data);
1853 foreach ($newfield as $param => $value) {
1854 if ($param != "id") {
1855 $fieldobject->field->$param = $value;
1858 unset($fieldobject->field->similarfield);
1859 $fieldobject->update_field();
1860 unset($fieldobject);
1862 /* Make a new field */
1863 else {
1864 include_once("field/$newfield->type/field.class.php");
1865 if (!isset($newfield->description)) {
1866 $newfield->description = '';
1868 $classname = 'data_field_'.$newfield->type;
1869 $fieldclass = new $classname($newfield, $this->data);
1870 $fieldclass->insert_field();
1871 unset($fieldclass);
1876 /* Get rid of all old unused data */
1877 if (!empty($preservedfields)) {
1878 foreach ($currentfields as $cid => $currentfield) {
1879 if (!array_key_exists($cid, $preservedfields)) {
1880 /* Data not used anymore so wipe! */
1881 print "Deleting field $currentfield->name<br />";
1882 $id = $currentfield->id;
1883 //Why delete existing data records and related comments/ratings??
1885 if ($content = get_records('data_content', 'fieldid', $id)) {
1886 foreach ($content as $item) {
1887 delete_records('data_ratings', 'recordid', $item->recordid);
1888 delete_records('data_comments', 'recordid', $item->recordid);
1889 delete_records('data_records', 'id', $item->recordid);
1892 delete_records('data_content', 'fieldid', $id);
1893 delete_records('data_fields', 'id', $id);
1898 // handle special settings here
1899 if (!empty($settings->defaultsort)) {
1900 if (is_numeric($settings->defaultsort)) {
1901 // old broken value
1902 $settings->defaultsort = 0;
1903 } else {
1904 $settings->defaultsort = (int)get_field('data_fields', 'id', 'dataid', $this->data->id, 'name', addslashes($settings->defaultsort));
1906 } else {
1907 $settings->defaultsort = 0;
1910 // do we want to overwrite all current database settings?
1911 if ($overwritesettings) {
1912 // all supported settings
1913 $overwrite = array_keys((array)$settings);
1914 } else {
1915 // only templates and sorting
1916 $overwrite = array('singletemplate', 'listtemplate', 'listtemplateheader', 'listtemplatefooter',
1917 'addtemplate', 'rsstemplate', 'rsstitletemplate', 'csstemplate', 'jstemplate',
1918 'asearchtemplate', 'defaultsortdir', 'defaultsort');
1921 // now overwrite current data settings
1922 foreach ($this->data as $prop=>$unused) {
1923 if (in_array($prop, $overwrite)) {
1924 $this->data->$prop = $settings->$prop;
1928 data_update_instance(addslashes_object($this->data));
1929 if (strstr($this->folder, '/temp/')) {
1930 // Removes the temporary files
1931 clean_preset($this->folder);
1933 return true;
1937 function data_preset_path($course, $userid, $shortname) {
1938 global $USER, $CFG;
1939 $context = get_context_instance(CONTEXT_COURSE, $course->id);
1940 $userid = (int)$userid;
1941 if ($userid > 0 && ($userid == $USER->id || has_capability('mod/data:viewalluserpresets', $context))) {
1942 return $CFG->dataroot.'/data/preset/'.$userid.'/'.$shortname;
1943 } else if ($userid == 0) {
1944 return $CFG->dirroot.'/mod/data/preset/'.$shortname;
1945 } else if ($userid < 0) {
1946 return $CFG->dataroot.'/temp/data/'.-$userid.'/'.$shortname;
1948 return 'Does it disturb you that this code will never run?';
1952 * Implementation of the function for printing the form elements that control
1953 * whether the course reset functionality affects the data.
1954 * @param $mform form passed by reference
1956 function data_reset_course_form_definition(&$mform) {
1957 $mform->addElement('header', 'dataheader', get_string('modulenameplural', 'data'));
1958 $mform->addElement('checkbox', 'reset_data', get_string('deleteallentries','data'));
1960 $mform->addElement('checkbox', 'reset_data_notenrolled', get_string('deletenotenrolled', 'data'));
1961 $mform->disabledIf('reset_data_notenrolled', 'reset_data', 'checked');
1963 $mform->addElement('checkbox', 'reset_data_ratings', get_string('deleteallratings'));
1964 $mform->disabledIf('reset_data_ratings', 'reset_data', 'checked');
1966 $mform->addElement('checkbox', 'reset_data_comments', get_string('deleteallcomments'));
1967 $mform->disabledIf('reset_data_comments', 'reset_data', 'checked');
1971 * Course reset form defaults.
1973 function data_reset_course_form_defaults($course) {
1974 return array('reset_data'=>0, 'reset_data_ratings'=>1, 'reset_data_comments'=>1, 'reset_data_notenrolled'=>0);
1978 * Removes all grades from gradebook
1979 * @param int $courseid
1980 * @param string optional type
1982 function data_reset_gradebook($courseid, $type='') {
1983 global $CFG;
1984 $sql = "SELECT d.*, cm.idnumber as cmidnumber, d.course as courseid
1985 FROM {$CFG->prefix}data d, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m
1986 WHERE m.name='data' AND m.id=cm.module AND cm.instance=d.id AND d.course=$courseid";
1987 if ($datas = get_records_sql($sql)) {
1988 foreach ($datas as $data) {
1989 data_grade_item_update($data, 'reset');
1995 * Actual implementation of the rest coures functionality, delete all the
1996 * data responses for course $data->courseid.
1997 * @param $data the data submitted from the reset course.
1998 * @return array status array
2000 function data_reset_userdata($data) {
2001 global $CFG;
2002 require_once($CFG->libdir.'/filelib.php');
2003 $componentstr = get_string('modulenameplural', 'data');
2004 $status = array();
2005 $allrecordssql = "SELECT r.id
2006 FROM {$CFG->prefix}data_records r
2007 INNER JOIN {$CFG->prefix}data d ON r.dataid = d.id
2008 WHERE d.course = {$data->courseid}";
2009 $alldatassql = "SELECT d.id
2010 FROM {$CFG->prefix}data d
2011 WHERE d.course={$data->courseid}";
2012 // delete entries if requested
2013 if (!empty($data->reset_data)) {
2014 delete_records_select('data_ratings', "recordid IN ($allrecordssql)");
2015 delete_records_select('data_comments', "recordid IN ($allrecordssql)");
2016 delete_records_select('data_content', "recordid IN ($allrecordssql)");
2017 delete_records_select('data_records', "dataid IN ($alldatassql)");
2018 if ($datas = get_records_sql($alldatassql)) {
2019 foreach ($datas as $dataid=>$unused) {
2020 fulldelete("$CFG->dataroot/$data->courseid/moddata/data/$dataid");
2023 if (empty($data->reset_gradebook_grades)) {
2024 // remove all grades from gradebook
2025 data_reset_gradebook($data->courseid);
2027 $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallentries', 'data'), 'error'=>false);
2030 // remove entries by users not enrolled into course
2031 if (!empty($data->reset_data_notenrolled)) {
2032 $recordssql = "SELECT r.id, r.userid, r.dataid, u.id AS userexists, u.deleted AS userdeleted
2033 FROM {$CFG->prefix}data_records r
2034 INNER JOIN {$CFG->prefix}data d ON r.dataid = d.id
2035 LEFT OUTER JOIN {$CFG->prefix}user u ON r.userid = u.id
2036 WHERE d.course = {$data->courseid} AND r.userid > 0";
2037 $course_context = get_context_instance(CONTEXT_COURSE, $data->courseid);
2038 $notenrolled = array();
2039 $fields = array();
2040 if ($rs = get_recordset_sql($recordssql)) {
2041 while ($record = rs_fetch_next_record($rs)) {
2042 if (array_key_exists($record->userid, $notenrolled) or !$record->userexists or $record->userdeleted
2043 or !has_capability('moodle/course:view', $course_context , $record->userid)) {
2044 delete_records('data_ratings', 'recordid', $record->id);
2045 delete_records('data_comments', 'recordid', $record->id);
2046 delete_records('data_content', 'recordid', $record->id);
2047 delete_records('data_records', 'id', $record->id);
2048 // HACK: this is ugly - the recordid should be before the fieldid!
2049 if (!array_key_exists($record->dataid, $fields)) {
2050 if ($fs = get_records('data_fields', 'dataid', $record->dataid)) {
2051 $fields[$record->dataid] = array_keys($fs);
2052 } else {
2053 $fields[$record->dataid] = array();
2056 foreach($fields[$record->dataid] as $fieldid) {
2057 fulldelete("$CFG->dataroot/$data->courseid/moddata/data/$record->dataid/$fieldid/$record->id");
2059 $notenrolled[$record->userid] = true;
2062 rs_close($rs);
2063 $status[] = array('component'=>$componentstr, 'item'=>get_string('deletenotenrolled', 'data'), 'error'=>false);
2067 // remove all ratings
2068 if (!empty($data->reset_data_ratings)) {
2069 delete_records_select('data_ratings', "recordid IN ($allrecordssql)");
2070 if (empty($data->reset_gradebook_grades)) {
2071 // remove all grades from gradebook
2072 data_reset_gradebook($data->courseid);
2074 $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallratings'), 'error'=>false);
2077 // remove all comments
2078 if (!empty($data->reset_data_comments)) {
2079 delete_records_select('data_comments', "recordid IN ($allrecordssql)");
2080 $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallcomments'), 'error'=>false);
2083 // updating dates - shift may be negative too
2084 if ($data->timeshift) {
2085 shift_course_mod_dates('data', array('timeavailablefrom', 'timeavailableto', 'timeviewfrom', 'timeviewto'), $data->timeshift, $data->courseid);
2086 $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged'), 'error'=>false);
2088 return $status;