|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00024 // Some constants 00025 define ('DATA_MAX_ENTRIES', 50); 00026 define ('DATA_PERPAGE_SINGLE', 1); 00027 00028 define ('DATA_FIRSTNAME', -1); 00029 define ('DATA_LASTNAME', -2); 00030 define ('DATA_APPROVED', -3); 00031 define ('DATA_TIMEADDED', 0); 00032 define ('DATA_TIMEMODIFIED', -4); 00033 00034 define ('DATA_CAP_EXPORT', 'mod/data:viewalluserpresets'); 00035 00036 define('DATA_PRESET_COMPONENT', 'mod_data'); 00037 define('DATA_PRESET_FILEAREA', 'site_presets'); 00038 define('DATA_PRESET_CONTEXT', SYSCONTEXTID); 00039 00040 // Users having assigned the default role "Non-editing teacher" can export database records 00041 // Using the mod/data capability "viewalluserpresets" existing in Moodle 1.9.x. 00042 // In Moodle >= 2, new roles may be introduced and used instead. 00043 00049 class data_field_base { // Base class for Database Field Types (see field/*/field.class.php) 00050 00052 var $type = 'unknown'; 00054 var $data = NULL; 00056 var $field = NULL; 00058 var $iconwidth = 16; 00060 var $iconheight = 16; 00062 var $cm; 00064 var $context; 00065 00075 function __construct($field=0, $data=0, $cm=0) { // Field or data or both, each can be id or object 00076 global $DB; 00077 00078 if (empty($field) && empty($data)) { 00079 print_error('missingfield', 'data'); 00080 } 00081 00082 if (!empty($field)) { 00083 if (is_object($field)) { 00084 $this->field = $field; // Programmer knows what they are doing, we hope 00085 } else if (!$this->field = $DB->get_record('data_fields', array('id'=>$field))) { 00086 print_error('invalidfieldid', 'data'); 00087 } 00088 if (empty($data)) { 00089 if (!$this->data = $DB->get_record('data', array('id'=>$this->field->dataid))) { 00090 print_error('invalidid', 'data'); 00091 } 00092 } 00093 } 00094 00095 if (empty($this->data)) { // We need to define this properly 00096 if (!empty($data)) { 00097 if (is_object($data)) { 00098 $this->data = $data; // Programmer knows what they are doing, we hope 00099 } else if (!$this->data = $DB->get_record('data', array('id'=>$data))) { 00100 print_error('invalidid', 'data'); 00101 } 00102 } else { // No way to define it! 00103 print_error('missingdata', 'data'); 00104 } 00105 } 00106 00107 if ($cm) { 00108 $this->cm = $cm; 00109 } else { 00110 $this->cm = get_coursemodule_from_instance('data', $this->data->id); 00111 } 00112 00113 if (empty($this->field)) { // We need to define some default values 00114 $this->define_default_field(); 00115 } 00116 00117 $this->context = get_context_instance(CONTEXT_MODULE, $this->cm->id); 00118 } 00119 00120 00126 function define_default_field() { 00127 global $OUTPUT; 00128 if (empty($this->data->id)) { 00129 echo $OUTPUT->notification('Programmer error: dataid not defined in field class'); 00130 } 00131 $this->field = new stdClass(); 00132 $this->field->id = 0; 00133 $this->field->dataid = $this->data->id; 00134 $this->field->type = $this->type; 00135 $this->field->param1 = ''; 00136 $this->field->param2 = ''; 00137 $this->field->param3 = ''; 00138 $this->field->name = ''; 00139 $this->field->description = ''; 00140 00141 return true; 00142 } 00143 00149 function define_field($data) { 00150 $this->field->type = $this->type; 00151 $this->field->dataid = $this->data->id; 00152 00153 $this->field->name = trim($data->name); 00154 $this->field->description = trim($data->description); 00155 00156 if (isset($data->param1)) { 00157 $this->field->param1 = trim($data->param1); 00158 } 00159 if (isset($data->param2)) { 00160 $this->field->param2 = trim($data->param2); 00161 } 00162 if (isset($data->param3)) { 00163 $this->field->param3 = trim($data->param3); 00164 } 00165 if (isset($data->param4)) { 00166 $this->field->param4 = trim($data->param4); 00167 } 00168 if (isset($data->param5)) { 00169 $this->field->param5 = trim($data->param5); 00170 } 00171 00172 return true; 00173 } 00174 00182 function insert_field() { 00183 global $DB, $OUTPUT; 00184 00185 if (empty($this->field)) { 00186 echo $OUTPUT->notification('Programmer error: Field has not been defined yet! See define_field()'); 00187 return false; 00188 } 00189 00190 $this->field->id = $DB->insert_record('data_fields',$this->field); 00191 return true; 00192 } 00193 00194 00201 function update_field() { 00202 global $DB; 00203 00204 $DB->update_record('data_fields', $this->field); 00205 return true; 00206 } 00207 00214 function delete_field() { 00215 global $DB; 00216 00217 if (!empty($this->field->id)) { 00218 $this->delete_content(); 00219 $DB->delete_records('data_fields', array('id'=>$this->field->id)); 00220 } 00221 return true; 00222 } 00223 00231 function display_add_field($recordid=0){ 00232 global $DB; 00233 00234 if ($recordid){ 00235 $content = $DB->get_field('data_content', 'content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid)); 00236 } else { 00237 $content = ''; 00238 } 00239 00240 // beware get_field returns false for new, empty records MDL-18567 00241 if ($content===false) { 00242 $content=''; 00243 } 00244 00245 $str = '<div title="'.s($this->field->description).'">'; 00246 $str .= '<input style="width:300px;" type="text" name="field_'.$this->field->id.'" id="field_'.$this->field->id.'" value="'.s($content).'" />'; 00247 $str .= '</div>'; 00248 00249 return $str; 00250 } 00251 00260 function display_edit_field() { 00261 global $CFG, $DB, $OUTPUT; 00262 00263 if (empty($this->field)) { // No field has been defined yet, try and make one 00264 $this->define_default_field(); 00265 } 00266 echo $OUTPUT->box_start('generalbox boxaligncenter boxwidthwide'); 00267 00268 echo '<form id="editfield" action="'.$CFG->wwwroot.'/mod/data/field.php" method="post">'."\n"; 00269 echo '<input type="hidden" name="d" value="'.$this->data->id.'" />'."\n"; 00270 if (empty($this->field->id)) { 00271 echo '<input type="hidden" name="mode" value="add" />'."\n"; 00272 $savebutton = get_string('add'); 00273 } else { 00274 echo '<input type="hidden" name="fid" value="'.$this->field->id.'" />'."\n"; 00275 echo '<input type="hidden" name="mode" value="update" />'."\n"; 00276 $savebutton = get_string('savechanges'); 00277 } 00278 echo '<input type="hidden" name="type" value="'.$this->type.'" />'."\n"; 00279 echo '<input name="sesskey" value="'.sesskey().'" type="hidden" />'."\n"; 00280 00281 echo $OUTPUT->heading($this->name()); 00282 00283 require_once($CFG->dirroot.'/mod/data/field/'.$this->type.'/mod.html'); 00284 00285 echo '<div class="mdl-align">'; 00286 echo '<input type="submit" value="'.$savebutton.'" />'."\n"; 00287 echo '<input type="submit" name="cancel" value="'.get_string('cancel').'" />'."\n"; 00288 echo '</div>'; 00289 00290 echo '</form>'; 00291 00292 echo $OUTPUT->box_end(); 00293 } 00294 00303 function display_browse_field($recordid, $template) { 00304 global $DB; 00305 00306 if ($content = $DB->get_record('data_content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid))) { 00307 if (isset($content->content)) { 00308 $options = new stdClass(); 00309 if ($this->field->param1 == '1') { // We are autolinking this field, so disable linking within us 00310 //$content->content = '<span class="nolink">'.$content->content.'</span>'; 00311 //$content->content1 = FORMAT_HTML; 00312 $options->filter=false; 00313 } 00314 $options->para = false; 00315 $str = format_text($content->content, $content->content1, $options); 00316 } else { 00317 $str = ''; 00318 } 00319 return $str; 00320 } 00321 return false; 00322 } 00323 00332 function update_content($recordid, $value, $name=''){ 00333 global $DB; 00334 00335 $content = new stdClass(); 00336 $content->fieldid = $this->field->id; 00337 $content->recordid = $recordid; 00338 $content->content = clean_param($value, PARAM_NOTAGS); 00339 00340 if ($oldcontent = $DB->get_record('data_content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid))) { 00341 $content->id = $oldcontent->id; 00342 return $DB->update_record('data_content', $content); 00343 } else { 00344 return $DB->insert_record('data_content', $content); 00345 } 00346 } 00347 00355 function delete_content($recordid=0) { 00356 global $DB; 00357 00358 if ($recordid) { 00359 $conditions = array('fieldid'=>$this->field->id, 'recordid'=>$recordid); 00360 } else { 00361 $conditions = array('fieldid'=>$this->field->id); 00362 } 00363 00364 $rs = $DB->get_recordset('data_content', $conditions); 00365 if ($rs->valid()) { 00366 $fs = get_file_storage(); 00367 foreach ($rs as $content) { 00368 $fs->delete_area_files($this->context->id, 'mod_data', 'content', $content->id); 00369 } 00370 } 00371 $rs->close(); 00372 00373 return $DB->delete_records('data_content', $conditions); 00374 } 00375 00383 function notemptyfield($value, $name) { 00384 return !empty($value); 00385 } 00386 00390 function print_before_form() { 00391 } 00392 00396 function print_after_form() { 00397 } 00398 00399 00406 function get_sort_field() { 00407 return 'content'; 00408 } 00409 00416 function get_sort_sql($fieldname) { 00417 return $fieldname; 00418 } 00419 00425 function name() { 00426 return get_string('name'.$this->type, 'data'); 00427 } 00428 00435 function image() { 00436 global $OUTPUT; 00437 00438 $params = array('d'=>$this->data->id, 'fid'=>$this->field->id, 'mode'=>'display', 'sesskey'=>sesskey()); 00439 $link = new moodle_url('/mod/data/field.php', $params); 00440 $str = '<a href="'.$link->out().'">'; 00441 $str .= '<img src="'.$OUTPUT->pix_url('field/'.$this->type, 'data') . '" '; 00442 $str .= 'height="'.$this->iconheight.'" width="'.$this->iconwidth.'" alt="'.$this->type.'" title="'.$this->type.'" /></a>'; 00443 return $str; 00444 } 00445 00452 function text_export_supported() { 00453 return true; 00454 } 00455 00463 function export_text_value($record) { 00464 if ($this->text_export_supported()) { 00465 return $record->content; 00466 } 00467 } 00468 00473 function file_ok($relativepath) { 00474 return false; 00475 } 00476 } 00477 00478 00490 function data_generate_default_template(&$data, $template, $recordid=0, $form=false, $update=true) { 00491 global $DB; 00492 00493 if (!$data && !$template) { 00494 return false; 00495 } 00496 if ($template == 'csstemplate' or $template == 'jstemplate' ) { 00497 return ''; 00498 } 00499 00500 // get all the fields for that database 00501 if ($fields = $DB->get_records('data_fields', array('dataid'=>$data->id), 'id')) { 00502 00503 $table = new html_table(); 00504 $table->attributes['class'] = 'mod-data-default-template'; 00505 $table->colclasses = array('template-field', 'template-token'); 00506 $table->data = array(); 00507 foreach ($fields as $field) { 00508 if ($form) { // Print forms instead of data 00509 $fieldobj = data_get_field($field, $data); 00510 $token = $fieldobj->display_add_field($recordid); 00511 } else { // Just print the tag 00512 $token = '[['.$field->name.']]'; 00513 } 00514 $table->data[] = array( 00515 $field->name.': ', 00516 $token 00517 ); 00518 } 00519 if ($template == 'listtemplate') { 00520 $cell = new html_table_cell('##edit## ##more## ##delete## ##approve## ##export##'); 00521 $cell->colspan = 2; 00522 $cell->attributes['class'] = 'controls'; 00523 $table->data[] = new html_table_row(array($cell)); 00524 } else if ($template == 'singletemplate') { 00525 $cell = new html_table_cell('##edit## ##delete## ##approve## ##export##'); 00526 $cell->colspan = 2; 00527 $cell->attributes['class'] = 'controls'; 00528 $table->data[] = new html_table_row(array($cell)); 00529 } else if ($template == 'asearchtemplate') { 00530 $row = new html_table_row(array(get_string('authorfirstname', 'data').': ', '##firstname##')); 00531 $row->attributes['class'] = 'searchcontrols'; 00532 $table->data[] = $row; 00533 $row = new html_table_row(array(get_string('authorlastname', 'data').': ', '##lastname##')); 00534 $row->attributes['class'] = 'searchcontrols'; 00535 $table->data[] = $row; 00536 } 00537 00538 $str = html_writer::start_tag('div', array('class' => 'defaulttemplate')); 00539 $str .= html_writer::table($table); 00540 $str .= html_writer::end_tag('div'); 00541 if ($template == 'listtemplate'){ 00542 $str .= html_writer::empty_tag('hr'); 00543 } 00544 00545 if ($update) { 00546 $newdata = new stdClass(); 00547 $newdata->id = $data->id; 00548 $newdata->{$template} = $str; 00549 $DB->update_record('data', $newdata); 00550 $data->{$template} = $str; 00551 } 00552 00553 return $str; 00554 } 00555 } 00556 00557 00569 function data_replace_field_in_templates($data, $searchfieldname, $newfieldname) { 00570 global $DB; 00571 00572 if (!empty($newfieldname)) { 00573 $prestring = '[['; 00574 $poststring = ']]'; 00575 $idpart = '#id'; 00576 00577 } else { 00578 $prestring = ''; 00579 $poststring = ''; 00580 $idpart = ''; 00581 } 00582 00583 $newdata = new stdClass(); 00584 $newdata->id = $data->id; 00585 $newdata->singletemplate = str_ireplace('[['.$searchfieldname.']]', 00586 $prestring.$newfieldname.$poststring, $data->singletemplate); 00587 00588 $newdata->listtemplate = str_ireplace('[['.$searchfieldname.']]', 00589 $prestring.$newfieldname.$poststring, $data->listtemplate); 00590 00591 $newdata->addtemplate = str_ireplace('[['.$searchfieldname.']]', 00592 $prestring.$newfieldname.$poststring, $data->addtemplate); 00593 00594 $newdata->addtemplate = str_ireplace('[['.$searchfieldname.'#id]]', 00595 $prestring.$newfieldname.$idpart.$poststring, $data->addtemplate); 00596 00597 $newdata->rsstemplate = str_ireplace('[['.$searchfieldname.']]', 00598 $prestring.$newfieldname.$poststring, $data->rsstemplate); 00599 00600 return $DB->update_record('data', $newdata); 00601 } 00602 00603 00611 function data_append_new_field_to_templates($data, $newfieldname) { 00612 global $DB; 00613 00614 $newdata = new stdClass(); 00615 $newdata->id = $data->id; 00616 $change = false; 00617 00618 if (!empty($data->singletemplate)) { 00619 $newdata->singletemplate = $data->singletemplate.' [[' . $newfieldname .']]'; 00620 $change = true; 00621 } 00622 if (!empty($data->addtemplate)) { 00623 $newdata->addtemplate = $data->addtemplate.' [[' . $newfieldname . ']]'; 00624 $change = true; 00625 } 00626 if (!empty($data->rsstemplate)) { 00627 $newdata->rsstemplate = $data->singletemplate.' [[' . $newfieldname . ']]'; 00628 $change = true; 00629 } 00630 if ($change) { 00631 $DB->update_record('data', $newdata); 00632 } 00633 } 00634 00635 00645 function data_get_field_from_name($name, $data){ 00646 global $DB; 00647 00648 $field = $DB->get_record('data_fields', array('name'=>$name, 'dataid'=>$data->id)); 00649 00650 if ($field) { 00651 return data_get_field($field, $data); 00652 } else { 00653 return false; 00654 } 00655 } 00656 00666 function data_get_field_from_id($fieldid, $data){ 00667 global $DB; 00668 00669 $field = $DB->get_record('data_fields', array('id'=>$fieldid, 'dataid'=>$data->id)); 00670 00671 if ($field) { 00672 return data_get_field($field, $data); 00673 } else { 00674 return false; 00675 } 00676 } 00677 00687 function data_get_field_new($type, $data) { 00688 global $CFG; 00689 00690 require_once($CFG->dirroot.'/mod/data/field/'.$type.'/field.class.php'); 00691 $newfield = 'data_field_'.$type; 00692 $newfield = new $newfield(0, $data); 00693 return $newfield; 00694 } 00695 00707 function data_get_field($field, $data, $cm=null) { 00708 global $CFG; 00709 00710 if ($field) { 00711 require_once('field/'.$field->type.'/field.class.php'); 00712 $newfield = 'data_field_'.$field->type; 00713 $newfield = new $newfield($field, $data, $cm); 00714 return $newfield; 00715 } 00716 } 00717 00718 00727 function data_isowner($record) { 00728 global $USER, $DB; 00729 00730 if (!isloggedin()) { // perf shortcut 00731 return false; 00732 } 00733 00734 if (!is_object($record)) { 00735 if (!$record = $DB->get_record('data_records', array('id'=>$record))) { 00736 return false; 00737 } 00738 } 00739 00740 return ($record->userid == $USER->id); 00741 } 00742 00749 function data_atmaxentries($data){ 00750 if (!$data->maxentries){ 00751 return false; 00752 00753 } else { 00754 return (data_numentries($data) >= $data->maxentries); 00755 } 00756 } 00757 00766 function data_numentries($data){ 00767 global $USER, $DB; 00768 $sql = 'SELECT COUNT(*) FROM {data_records} WHERE dataid=? AND userid=?'; 00769 return $DB->count_records_sql($sql, array($data->id, $USER->id)); 00770 } 00771 00782 function data_add_record($data, $groupid=0){ 00783 global $USER, $DB; 00784 00785 $cm = get_coursemodule_from_instance('data', $data->id); 00786 $context = get_context_instance(CONTEXT_MODULE, $cm->id); 00787 00788 $record = new stdClass(); 00789 $record->userid = $USER->id; 00790 $record->dataid = $data->id; 00791 $record->groupid = $groupid; 00792 $record->timecreated = $record->timemodified = time(); 00793 if (has_capability('mod/data:approve', $context)) { 00794 $record->approved = 1; 00795 } else { 00796 $record->approved = 0; 00797 } 00798 return $DB->insert_record('data_records', $record); 00799 } 00800 00811 function data_tags_check($dataid, $template) { 00812 global $DB, $OUTPUT; 00813 00814 // first get all the possible tags 00815 $fields = $DB->get_records('data_fields', array('dataid'=>$dataid)); 00816 // then we generate strings to replace 00817 $tagsok = true; // let's be optimistic 00818 foreach ($fields as $field){ 00819 $pattern="/\[\[".$field->name."\]\]/i"; 00820 if (preg_match_all($pattern, $template, $dummy)>1){ 00821 $tagsok = false; 00822 echo $OUTPUT->notification('[['.$field->name.']] - '.get_string('multipletags','data')); 00823 } 00824 } 00825 // else return true 00826 return $tagsok; 00827 } 00828 00836 function data_add_instance($data) { 00837 global $DB; 00838 00839 if (empty($data->assessed)) { 00840 $data->assessed = 0; 00841 } 00842 00843 $data->timemodified = time(); 00844 00845 $data->id = $DB->insert_record('data', $data); 00846 00847 data_grade_item_update($data); 00848 00849 return $data->id; 00850 } 00851 00859 function data_update_instance($data) { 00860 global $DB, $OUTPUT; 00861 00862 $data->timemodified = time(); 00863 $data->id = $data->instance; 00864 00865 if (empty($data->assessed)) { 00866 $data->assessed = 0; 00867 } 00868 00869 if (empty($data->ratingtime) or empty($data->assessed)) { 00870 $data->assesstimestart = 0; 00871 $data->assesstimefinish = 0; 00872 } 00873 00874 if (empty($data->notification)) { 00875 $data->notification = 0; 00876 } 00877 00878 $DB->update_record('data', $data); 00879 00880 data_grade_item_update($data); 00881 00882 return true; 00883 00884 } 00885 00893 function data_delete_instance($id) { // takes the dataid 00894 global $DB, $CFG; 00895 00896 if (!$data = $DB->get_record('data', array('id'=>$id))) { 00897 return false; 00898 } 00899 00900 $cm = get_coursemodule_from_instance('data', $data->id); 00901 $context = get_context_instance(CONTEXT_MODULE, $cm->id); 00902 00904 00905 // files 00906 $fs = get_file_storage(); 00907 $fs->delete_area_files($context->id, 'mod_data'); 00908 00909 // get all the records in this data 00910 $sql = "SELECT r.id 00911 FROM {data_records} r 00912 WHERE r.dataid = ?"; 00913 00914 $DB->delete_records_select('data_content', "recordid IN ($sql)", array($id)); 00915 00916 // delete all the records and fields 00917 $DB->delete_records('data_records', array('dataid'=>$id)); 00918 $DB->delete_records('data_fields', array('dataid'=>$id)); 00919 00920 // Delete the instance itself 00921 $result = $DB->delete_records('data', array('id'=>$id)); 00922 00923 // cleanup gradebook 00924 data_grade_item_delete($data); 00925 00926 return $result; 00927 } 00928 00939 function data_user_outline($course, $user, $mod, $data) { 00940 global $DB, $CFG; 00941 require_once("$CFG->libdir/gradelib.php"); 00942 00943 $grades = grade_get_grades($course->id, 'mod', 'data', $data->id, $user->id); 00944 if (empty($grades->items[0]->grades)) { 00945 $grade = false; 00946 } else { 00947 $grade = reset($grades->items[0]->grades); 00948 } 00949 00950 00951 if ($countrecords = $DB->count_records('data_records', array('dataid'=>$data->id, 'userid'=>$user->id))) { 00952 $result = new stdClass(); 00953 $result->info = get_string('numrecords', 'data', $countrecords); 00954 $lastrecord = $DB->get_record_sql('SELECT id,timemodified FROM {data_records} 00955 WHERE dataid = ? AND userid = ? 00956 ORDER BY timemodified DESC', array($data->id, $user->id), true); 00957 $result->time = $lastrecord->timemodified; 00958 if ($grade) { 00959 $result->info .= ', ' . get_string('grade') . ': ' . $grade->str_long_grade; 00960 } 00961 return $result; 00962 } else if ($grade) { 00963 $result = new stdClass(); 00964 $result->info = get_string('grade') . ': ' . $grade->str_long_grade; 00965 00966 //datesubmitted == time created. dategraded == time modified or time overridden 00967 //if grade was last modified by the user themselves use date graded. Otherwise use date submitted 00968 //TODO: move this copied & pasted code somewhere in the grades API. See MDL-26704 00969 if ($grade->usermodified == $user->id || empty($grade->datesubmitted)) { 00970 $result->time = $grade->dategraded; 00971 } else { 00972 $result->time = $grade->datesubmitted; 00973 } 00974 00975 return $result; 00976 } 00977 return NULL; 00978 } 00979 00989 function data_user_complete($course, $user, $mod, $data) { 00990 global $DB, $CFG, $OUTPUT; 00991 require_once("$CFG->libdir/gradelib.php"); 00992 00993 $grades = grade_get_grades($course->id, 'mod', 'data', $data->id, $user->id); 00994 if (!empty($grades->items[0]->grades)) { 00995 $grade = reset($grades->items[0]->grades); 00996 echo $OUTPUT->container(get_string('grade').': '.$grade->str_long_grade); 00997 if ($grade->str_feedback) { 00998 echo $OUTPUT->container(get_string('feedback').': '.$grade->str_feedback); 00999 } 01000 } 01001 01002 if ($records = $DB->get_records('data_records', array('dataid'=>$data->id,'userid'=>$user->id), 'timemodified DESC')) { 01003 data_print_template('singletemplate', $records, $data); 01004 } 01005 } 01006 01015 function data_get_user_grades($data, $userid=0) { 01016 global $CFG; 01017 01018 require_once($CFG->dirroot.'/rating/lib.php'); 01019 01020 $ratingoptions = new stdClass; 01021 $ratingoptions->component = 'mod_data'; 01022 $ratingoptions->ratingarea = 'entry'; 01023 $ratingoptions->modulename = 'data'; 01024 $ratingoptions->moduleid = $data->id; 01025 01026 $ratingoptions->userid = $userid; 01027 $ratingoptions->aggregationmethod = $data->assessed; 01028 $ratingoptions->scaleid = $data->scale; 01029 $ratingoptions->itemtable = 'data_records'; 01030 $ratingoptions->itemtableusercolumn = 'userid'; 01031 01032 $rm = new rating_manager(); 01033 return $rm->get_user_grades($ratingoptions); 01034 } 01035 01045 function data_update_grades($data, $userid=0, $nullifnone=true) { 01046 global $CFG, $DB; 01047 require_once($CFG->libdir.'/gradelib.php'); 01048 01049 if (!$data->assessed) { 01050 data_grade_item_update($data); 01051 01052 } else if ($grades = data_get_user_grades($data, $userid)) { 01053 data_grade_item_update($data, $grades); 01054 01055 } else if ($userid and $nullifnone) { 01056 $grade = new stdClass(); 01057 $grade->userid = $userid; 01058 $grade->rawgrade = NULL; 01059 data_grade_item_update($data, $grade); 01060 01061 } else { 01062 data_grade_item_update($data); 01063 } 01064 } 01065 01071 function data_upgrade_grades() { 01072 global $DB; 01073 01074 $sql = "SELECT COUNT('x') 01075 FROM {data} d, {course_modules} cm, {modules} m 01076 WHERE m.name='data' AND m.id=cm.module AND cm.instance=d.id"; 01077 $count = $DB->count_records_sql($sql); 01078 01079 $sql = "SELECT d.*, cm.idnumber AS cmidnumber, d.course AS courseid 01080 FROM {data} d, {course_modules} cm, {modules} m 01081 WHERE m.name='data' AND m.id=cm.module AND cm.instance=d.id"; 01082 $rs = $DB->get_recordset_sql($sql); 01083 if ($rs->valid()) { 01084 // too much debug output 01085 $pbar = new progress_bar('dataupgradegrades', 500, true); 01086 $i=0; 01087 foreach ($rs as $data) { 01088 $i++; 01089 upgrade_set_timeout(60*5); // set up timeout, may also abort execution 01090 data_update_grades($data, 0, false); 01091 $pbar->update($i, $count, "Updating Database grades ($i/$count)."); 01092 } 01093 } 01094 $rs->close(); 01095 } 01096 01105 function data_grade_item_update($data, $grades=NULL) { 01106 global $CFG; 01107 require_once($CFG->libdir.'/gradelib.php'); 01108 01109 $params = array('itemname'=>$data->name, 'idnumber'=>$data->cmidnumber); 01110 01111 if (!$data->assessed or $data->scale == 0) { 01112 $params['gradetype'] = GRADE_TYPE_NONE; 01113 01114 } else if ($data->scale > 0) { 01115 $params['gradetype'] = GRADE_TYPE_VALUE; 01116 $params['grademax'] = $data->scale; 01117 $params['grademin'] = 0; 01118 01119 } else if ($data->scale < 0) { 01120 $params['gradetype'] = GRADE_TYPE_SCALE; 01121 $params['scaleid'] = -$data->scale; 01122 } 01123 01124 if ($grades === 'reset') { 01125 $params['reset'] = true; 01126 $grades = NULL; 01127 } 01128 01129 return grade_update('mod/data', $data->course, 'mod', 'data', $data->id, 0, $grades, $params); 01130 } 01131 01139 function data_grade_item_delete($data) { 01140 global $CFG; 01141 require_once($CFG->libdir.'/gradelib.php'); 01142 01143 return grade_update('mod/data', $data->course, 'mod', 'data', $data->id, 0, NULL, array('deleted'=>1)); 01144 } 01145 01157 function data_get_participants($dataid) { 01158 global $DB; 01159 01160 $params = array('dataid' => $dataid); 01161 01162 $sql = "SELECT DISTINCT u.id, u.id 01163 FROM {user} u, 01164 {data_records} r 01165 WHERE r.dataid = :dataid AND 01166 u.id = r.userid"; 01167 $records = $DB->get_records_sql($sql, $params); 01168 01169 $sql = "SELECT DISTINCT u.id, u.id 01170 FROM {user} u, 01171 {data_records} r, 01172 {comments} c 01173 WHERE r.dataid = ? AND 01174 u.id = r.userid AND 01175 r.id = c.itemid AND 01176 c.commentarea = 'database_entry'"; 01177 $comments = $DB->get_records_sql($sql, $params); 01178 01179 $sql = "SELECT DISTINCT u.id, u.id 01180 FROM {user} u, 01181 {data_records} r, 01182 {ratings} a 01183 WHERE r.dataid = ? AND 01184 u.id = r.userid AND 01185 r.id = a.itemid AND 01186 a.component = 'mod_data' AND 01187 a.ratingarea = 'entry'"; 01188 $ratings = $DB->get_records_sql($sql, $params); 01189 01190 $participants = array(); 01191 01192 if ($records) { 01193 foreach ($records as $record) { 01194 $participants[$record->id] = $record; 01195 } 01196 } 01197 if ($comments) { 01198 foreach ($comments as $comment) { 01199 $participants[$comment->id] = $comment; 01200 } 01201 } 01202 if ($ratings) { 01203 foreach ($ratings as $rating) { 01204 $participants[$rating->id] = $rating; 01205 } 01206 } 01207 01208 return $participants; 01209 } 01210 01211 // junk functions 01226 function data_print_template($template, $records, $data, $search='', $page=0, $return=false) { 01227 global $CFG, $DB, $OUTPUT; 01228 $cm = get_coursemodule_from_instance('data', $data->id); 01229 $context = get_context_instance(CONTEXT_MODULE, $cm->id); 01230 01231 static $fields = NULL; 01232 static $isteacher; 01233 static $dataid = NULL; 01234 01235 if (empty($dataid)) { 01236 $dataid = $data->id; 01237 } else if ($dataid != $data->id) { 01238 $fields = NULL; 01239 } 01240 01241 if (empty($fields)) { 01242 $fieldrecords = $DB->get_records('data_fields', array('dataid'=>$data->id)); 01243 foreach ($fieldrecords as $fieldrecord) { 01244 $fields[]= data_get_field($fieldrecord, $data); 01245 } 01246 $isteacher = has_capability('mod/data:managetemplates', $context); 01247 } 01248 01249 if (empty($records)) { 01250 return; 01251 } 01252 01253 foreach ($records as $record) { // Might be just one for the single template 01254 01255 // Replacing tags 01256 $patterns = array(); 01257 $replacement = array(); 01258 01259 // Then we generate strings to replace for normal tags 01260 foreach ($fields as $field) { 01261 $patterns[]='[['.$field->field->name.']]'; 01262 $replacement[] = highlight($search, $field->display_browse_field($record->id, $template)); 01263 } 01264 01265 // Replacing special tags (##Edit##, ##Delete##, ##More##) 01266 $patterns[]='##edit##'; 01267 $patterns[]='##delete##'; 01268 if (has_capability('mod/data:manageentries', $context) or data_isowner($record->id)) { 01269 $replacement[] = '<a href="'.$CFG->wwwroot.'/mod/data/edit.php?d=' 01270 .$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>'; 01271 $replacement[] = '<a href="'.$CFG->wwwroot.'/mod/data/view.php?d=' 01272 .$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>'; 01273 } else { 01274 $replacement[] = ''; 01275 $replacement[] = ''; 01276 } 01277 01278 $moreurl = $CFG->wwwroot . '/mod/data/view.php?d=' . $data->id . '&rid=' . $record->id; 01279 if ($search) { 01280 $moreurl .= '&filter=1'; 01281 } 01282 $patterns[]='##more##'; 01283 $replacement[] = '<a href="' . $moreurl . '"><img src="' . $OUTPUT->pix_url('i/search') . '" class="iconsmall" alt="' . get_string('more', 'data') . '" title="' . get_string('more', 'data') . '" /></a>'; 01284 01285 $patterns[]='##moreurl##'; 01286 $replacement[] = $moreurl; 01287 01288 $patterns[]='##user##'; 01289 $replacement[] = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$record->userid. 01290 '&course='.$data->course.'">'.fullname($record).'</a>'; 01291 01292 $patterns[]='##export##'; 01293 01294 if (!empty($CFG->enableportfolios) && ($template == 'singletemplate' || $template == 'listtemplate') 01295 && ((has_capability('mod/data:exportentry', $context) 01296 || (data_isowner($record->id) && has_capability('mod/data:exportownentry', $context))))) { 01297 require_once($CFG->libdir . '/portfoliolib.php'); 01298 $button = new portfolio_add_button(); 01299 $button->set_callback_options('data_portfolio_caller', array('id' => $cm->id, 'recordid' => $record->id), '/mod/data/locallib.php'); 01300 list($formats, $files) = data_portfolio_caller::formats($fields, $record); 01301 $button->set_formats($formats); 01302 $replacement[] = $button->to_html(PORTFOLIO_ADD_ICON_LINK); 01303 } else { 01304 $replacement[] = ''; 01305 } 01306 01307 $patterns[] = '##timeadded##'; 01308 $replacement[] = userdate($record->timecreated); 01309 01310 $patterns[] = '##timemodified##'; 01311 $replacement [] = userdate($record->timemodified); 01312 01313 $patterns[]='##approve##'; 01314 if (has_capability('mod/data:approve', $context) && ($data->approval) && (!$record->approved)){ 01315 $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>'; 01316 } else { 01317 $replacement[] = ''; 01318 } 01319 01320 $patterns[]='##comments##'; 01321 if (($template == 'listtemplate') && ($data->comments)) { 01322 01323 if (!empty($CFG->usecomments)) { 01324 require_once($CFG->dirroot . '/comment/lib.php'); 01325 list($context, $course, $cm) = get_context_info_array($context->id); 01326 $cmt = new stdClass(); 01327 $cmt->context = $context; 01328 $cmt->course = $course; 01329 $cmt->cm = $cm; 01330 $cmt->area = 'database_entry'; 01331 $cmt->itemid = $record->id; 01332 $cmt->showcount = true; 01333 $cmt->component = 'mod_data'; 01334 $comment = new comment($cmt); 01335 $replacement[] = $comment->output(true); 01336 } 01337 } else { 01338 $replacement[] = ''; 01339 } 01340 01341 // actual replacement of the tags 01342 $newtext = str_ireplace($patterns, $replacement, $data->{$template}); 01343 01344 // no more html formatting and filtering - see MDL-6635 01345 if ($return) { 01346 return $newtext; 01347 } else { 01348 echo $newtext; 01349 01350 // hack alert - return is always false in singletemplate anyway ;-) 01351 /********************************** 01352 * Printing Ratings Form * 01353 *********************************/ 01354 if ($template == 'singletemplate') { //prints ratings options 01355 data_print_ratings($data, $record); 01356 } 01357 01358 /********************************** 01359 * Printing Comments Form * 01360 *********************************/ 01361 if (($template == 'singletemplate') && ($data->comments)) { 01362 if (!empty($CFG->usecomments)) { 01363 require_once($CFG->dirroot . '/comment/lib.php'); 01364 list($context, $course, $cm) = get_context_info_array($context->id); 01365 $cmt = new stdClass(); 01366 $cmt->context = $context; 01367 $cmt->course = $course; 01368 $cmt->cm = $cm; 01369 $cmt->area = 'database_entry'; 01370 $cmt->itemid = $record->id; 01371 $cmt->showcount = true; 01372 $cmt->component = 'mod_data'; 01373 $comment = new comment($cmt); 01374 $comment->output(false); 01375 } 01376 } 01377 } 01378 } 01379 } 01380 01389 function data_rating_permissions($contextid, $component, $ratingarea) { 01390 $context = get_context_instance_by_id($contextid, MUST_EXIST); 01391 if ($component != 'mod_data' || $ratingarea != 'entry') { 01392 return null; 01393 } 01394 return array( 01395 'view' => has_capability('mod/data:viewrating',$context), 01396 'viewany' => has_capability('mod/data:viewanyrating',$context), 01397 'viewall' => has_capability('mod/data:viewallratings',$context), 01398 'rate' => has_capability('mod/data:rate',$context) 01399 ); 01400 } 01401 01413 function data_rating_validate($params) { 01414 global $DB, $USER; 01415 01416 // Check the component is mod_data 01417 if ($params['component'] != 'mod_data') { 01418 throw new rating_exception('invalidcomponent'); 01419 } 01420 01421 // Check the ratingarea is entry (the only rating area in data module) 01422 if ($params['ratingarea'] != 'entry') { 01423 throw new rating_exception('invalidratingarea'); 01424 } 01425 01426 // Check the rateduserid is not the current user .. you can't rate your own entries 01427 if ($params['rateduserid'] == $USER->id) { 01428 throw new rating_exception('nopermissiontorate'); 01429 } 01430 01431 $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 01432 FROM {data_records} r 01433 JOIN {data} d ON r.dataid = d.id 01434 WHERE r.id = :itemid"; 01435 $dataparams = array('itemid'=>$params['itemid']); 01436 if (!$info = $DB->get_record_sql($datasql, $dataparams)) { 01437 //item doesn't exist 01438 throw new rating_exception('invaliditemid'); 01439 } 01440 01441 if ($info->scale != $params['scaleid']) { 01442 //the scale being submitted doesnt match the one in the database 01443 throw new rating_exception('invalidscaleid'); 01444 } 01445 01446 //check that the submitted rating is valid for the scale 01447 01448 // lower limit 01449 if ($params['rating'] < 0 && $params['rating'] != RATING_UNSET_RATING) { 01450 throw new rating_exception('invalidnum'); 01451 } 01452 01453 // upper limit 01454 if ($info->scale < 0) { 01455 //its a custom scale 01456 $scalerecord = $DB->get_record('scale', array('id' => -$info->scale)); 01457 if ($scalerecord) { 01458 $scalearray = explode(',', $scalerecord->scale); 01459 if ($params['rating'] > count($scalearray)) { 01460 throw new rating_exception('invalidnum'); 01461 } 01462 } else { 01463 throw new rating_exception('invalidscaleid'); 01464 } 01465 } else if ($params['rating'] > $info->scale) { 01466 //if its numeric and submitted rating is above maximum 01467 throw new rating_exception('invalidnum'); 01468 } 01469 01470 if ($info->approval && !$info->approved) { 01471 //database requires approval but this item isnt approved 01472 throw new rating_exception('nopermissiontorate'); 01473 } 01474 01475 // check the item we're rating was created in the assessable time window 01476 if (!empty($info->assesstimestart) && !empty($info->assesstimefinish)) { 01477 if ($info->timecreated < $info->assesstimestart || $info->timecreated > $info->assesstimefinish) { 01478 throw new rating_exception('notavailable'); 01479 } 01480 } 01481 01482 $course = $DB->get_record('course', array('id'=>$info->course), '*', MUST_EXIST); 01483 $cm = get_coursemodule_from_instance('data', $info->dataid, $course->id, false, MUST_EXIST); 01484 $context = get_context_instance(CONTEXT_MODULE, $cm->id, MUST_EXIST); 01485 01486 // if the supplied context doesnt match the item's context 01487 if ($context->id != $params['context']->id) { 01488 throw new rating_exception('invalidcontext'); 01489 } 01490 01491 // Make sure groups allow this user to see the item they're rating 01492 $groupid = $info->groupid; 01493 if ($groupid > 0 and $groupmode = groups_get_activity_groupmode($cm, $course)) { // Groups are being used 01494 if (!groups_group_exists($groupid)) { // Can't find group 01495 throw new rating_exception('cannotfindgroup');//something is wrong 01496 } 01497 01498 if (!groups_is_member($groupid) and !has_capability('moodle/site:accessallgroups', $context)) { 01499 // do not allow rating of posts from other groups when in SEPARATEGROUPS or VISIBLEGROUPS 01500 throw new rating_exception('notmemberofgroup'); 01501 } 01502 } 01503 01504 return true; 01505 } 01506 01507 01528 function data_print_preference_form($data, $perpage, $search, $sort='', $order='ASC', $search_array = '', $advanced = 0, $mode= ''){ 01529 global $CFG, $DB, $PAGE, $OUTPUT; 01530 01531 $cm = get_coursemodule_from_instance('data', $data->id); 01532 $context = get_context_instance(CONTEXT_MODULE, $cm->id); 01533 echo '<br /><div class="datapreferences">'; 01534 echo '<form id="options" action="view.php" method="get">'; 01535 echo '<div>'; 01536 echo '<input type="hidden" name="d" value="'.$data->id.'" />'; 01537 if ($mode =='asearch') { 01538 $advanced = 1; 01539 echo '<input type="hidden" name="mode" value="list" />'; 01540 } 01541 echo '<label for="pref_perpage">'.get_string('pagesize','data').'</label> '; 01542 $pagesizes = array(2=>2,3=>3,4=>4,5=>5,6=>6,7=>7,8=>8,9=>9,10=>10,15=>15, 01543 20=>20,30=>30,40=>40,50=>50,100=>100,200=>200,300=>300,400=>400,500=>500,1000=>1000); 01544 echo html_writer::select($pagesizes, 'perpage', $perpage, false, array('id'=>'pref_perpage')); 01545 echo '<div id="reg_search" style="display: '; 01546 if ($advanced) { 01547 echo 'none'; 01548 } 01549 else { 01550 echo 'inline'; 01551 } 01552 echo ';" > <label for="pref_search">'.get_string('search').'</label> <input type="text" size="16" name="search" id= "pref_search" value="'.s($search).'" /></div>'; 01553 echo ' <label for="pref_sortby">'.get_string('sortby').'</label> '; 01554 // foreach field, print the option 01555 echo '<select name="sort" id="pref_sortby">'; 01556 if ($fields = $DB->get_records('data_fields', array('dataid'=>$data->id), 'name')) { 01557 echo '<optgroup label="'.get_string('fields', 'data').'">'; 01558 foreach ($fields as $field) { 01559 if ($field->id == $sort) { 01560 echo '<option value="'.$field->id.'" selected="selected">'.$field->name.'</option>'; 01561 } else { 01562 echo '<option value="'.$field->id.'">'.$field->name.'</option>'; 01563 } 01564 } 01565 echo '</optgroup>'; 01566 } 01567 $options = array(); 01568 $options[DATA_TIMEADDED] = get_string('timeadded', 'data'); 01569 $options[DATA_TIMEMODIFIED] = get_string('timemodified', 'data'); 01570 $options[DATA_FIRSTNAME] = get_string('authorfirstname', 'data'); 01571 $options[DATA_LASTNAME] = get_string('authorlastname', 'data'); 01572 if ($data->approval and has_capability('mod/data:approve', $context)) { 01573 $options[DATA_APPROVED] = get_string('approved', 'data'); 01574 } 01575 echo '<optgroup label="'.get_string('other', 'data').'">'; 01576 foreach ($options as $key => $name) { 01577 if ($key == $sort) { 01578 echo '<option value="'.$key.'" selected="selected">'.$name.'</option>'; 01579 } else { 01580 echo '<option value="'.$key.'">'.$name.'</option>'; 01581 } 01582 } 01583 echo '</optgroup>'; 01584 echo '</select>'; 01585 echo '<label for="pref_order" class="accesshide">'.get_string('order').'</label>'; 01586 echo '<select id="pref_order" name="order">'; 01587 if ($order == 'ASC') { 01588 echo '<option value="ASC" selected="selected">'.get_string('ascending','data').'</option>'; 01589 } else { 01590 echo '<option value="ASC">'.get_string('ascending','data').'</option>'; 01591 } 01592 if ($order == 'DESC') { 01593 echo '<option value="DESC" selected="selected">'.get_string('descending','data').'</option>'; 01594 } else { 01595 echo '<option value="DESC">'.get_string('descending','data').'</option>'; 01596 } 01597 echo '</select>'; 01598 01599 if ($advanced) { 01600 $checked = ' checked="checked" '; 01601 } 01602 else { 01603 $checked = ''; 01604 } 01605 $PAGE->requires->js('/mod/data/data.js'); 01606 echo ' <input type="hidden" name="advanced" value="0" />'; 01607 echo ' <input type="hidden" name="filter" value="1" />'; 01608 echo ' <input type="checkbox" id="advancedcheckbox" name="advanced" value="1" '.$checked.' onchange="showHideAdvSearch(this.checked);" /><label for="advancedcheckbox">'.get_string('advancedsearch', 'data').'</label>'; 01609 echo ' <input type="submit" value="'.get_string('savesettings','data').'" />'; 01610 01611 echo '<br />'; 01612 echo '<div class="dataadvancedsearch" id="data_adv_form" style="display: '; 01613 01614 if ($advanced) { 01615 echo 'inline'; 01616 } 01617 else { 01618 echo 'none'; 01619 } 01620 echo ';margin-left:auto;margin-right:auto;" >'; 01621 echo '<table class="boxaligncenter">'; 01622 01623 // print ASC or DESC 01624 echo '<tr><td colspan="2"> </td></tr>'; 01625 $i = 0; 01626 01627 // Determine if we are printing all fields for advanced search, or the template for advanced search 01628 // If a template is not defined, use the deafault template and display all fields. 01629 if(empty($data->asearchtemplate)) { 01630 data_generate_default_template($data, 'asearchtemplate'); 01631 } 01632 01633 static $fields = NULL; 01634 static $isteacher; 01635 static $dataid = NULL; 01636 01637 if (empty($dataid)) { 01638 $dataid = $data->id; 01639 } else if ($dataid != $data->id) { 01640 $fields = NULL; 01641 } 01642 01643 if (empty($fields)) { 01644 $fieldrecords = $DB->get_records('data_fields', array('dataid'=>$data->id)); 01645 foreach ($fieldrecords as $fieldrecord) { 01646 $fields[]= data_get_field($fieldrecord, $data); 01647 } 01648 01649 $isteacher = has_capability('mod/data:managetemplates', $context); 01650 } 01651 01652 // Replacing tags 01653 $patterns = array(); 01654 $replacement = array(); 01655 01656 // Then we generate strings to replace for normal tags 01657 foreach ($fields as $field) { 01658 $fieldname = $field->field->name; 01659 $fieldname = preg_quote($fieldname, '/'); 01660 $patterns[] = "/\[\[$fieldname\]\]/i"; 01661 $searchfield = data_get_field_from_id($field->field->id, $data); 01662 if (!empty($search_array[$field->field->id]->data)) { 01663 $replacement[] = $searchfield->display_search_field($search_array[$field->field->id]->data); 01664 } else { 01665 $replacement[] = $searchfield->display_search_field(); 01666 } 01667 } 01668 $fn = !empty($search_array[DATA_FIRSTNAME]->data) ? $search_array[DATA_FIRSTNAME]->data : ''; 01669 $ln = !empty($search_array[DATA_LASTNAME]->data) ? $search_array[DATA_LASTNAME]->data : ''; 01670 $patterns[] = '/##firstname##/'; 01671 $replacement[] = '<input type="text" size="16" name="u_fn" value="'.$fn.'" />'; 01672 $patterns[] = '/##lastname##/'; 01673 $replacement[] = '<input type="text" size="16" name="u_ln" value="'.$ln.'" />'; 01674 01675 // actual replacement of the tags 01676 $newtext = preg_replace($patterns, $replacement, $data->asearchtemplate); 01677 01678 $options = new stdClass(); 01679 $options->para=false; 01680 $options->noclean=true; 01681 echo '<tr><td>'; 01682 echo format_text($newtext, FORMAT_HTML, $options); 01683 echo '</td></tr>'; 01684 01685 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>'; 01686 echo '</table>'; 01687 echo '</div>'; 01688 echo '</div>'; 01689 echo '</form>'; 01690 echo '</div>'; 01691 } 01692 01700 function data_print_ratings($data, $record) { 01701 global $OUTPUT; 01702 if (!empty($record->rating)){ 01703 echo $OUTPUT->render($record->rating); 01704 } 01705 } 01706 01712 function data_get_view_actions() { 01713 return array('view'); 01714 } 01715 01719 function data_get_post_actions() { 01720 return array('add','update','record delete'); 01721 } 01722 01729 function data_fieldname_exists($name, $dataid, $fieldid = 0) { 01730 global $DB; 01731 01732 if (!is_numeric($name)) { 01733 $like = $DB->sql_like('df.name', ':name', false); 01734 } else { 01735 $like = "df.name = :name"; 01736 } 01737 $params = array('name'=>$name); 01738 if ($fieldid) { 01739 $params['dataid'] = $dataid; 01740 $params['fieldid1'] = $fieldid; 01741 $params['fieldid2'] = $fieldid; 01742 return $DB->record_exists_sql("SELECT * FROM {data_fields} df 01743 WHERE $like AND df.dataid = :dataid 01744 AND ((df.id < :fieldid1) OR (df.id > :fieldid2))", $params); 01745 } else { 01746 $params['dataid'] = $dataid; 01747 return $DB->record_exists_sql("SELECT * FROM {data_fields} df 01748 WHERE $like AND df.dataid = :dataid", $params); 01749 } 01750 } 01751 01755 function data_convert_arrays_to_strings(&$fieldinput) { 01756 foreach ($fieldinput as $key => $val) { 01757 if (is_array($val)) { 01758 $str = ''; 01759 foreach ($val as $inner) { 01760 $str .= $inner . ','; 01761 } 01762 $str = substr($str, 0, -1); 01763 01764 $fieldinput->$key = $str; 01765 } 01766 } 01767 } 01768 01769 01787 function data_convert_to_roles($data, $teacherroles=array(), $studentroles=array(), $cmid=NULL) { 01788 global $CFG, $DB, $OUTPUT; 01789 01790 if (!isset($data->participants) && !isset($data->assesspublic) 01791 && !isset($data->groupmode)) { 01792 // We assume that this database has already been converted to use the 01793 // Roles System. above fields get dropped the data module has been 01794 // upgraded to use Roles. 01795 return false; 01796 } 01797 01798 if (empty($cmid)) { 01799 // We were not given the course_module id. Try to find it. 01800 if (!$cm = get_coursemodule_from_instance('data', $data->id)) { 01801 echo $OUTPUT->notification('Could not get the course module for the data'); 01802 return false; 01803 } else { 01804 $cmid = $cm->id; 01805 } 01806 } 01807 $context = get_context_instance(CONTEXT_MODULE, $cmid); 01808 01809 01810 // $data->participants: 01811 // 1 - Only teachers can add entries 01812 // 3 - Teachers and students can add entries 01813 switch ($data->participants) { 01814 case 1: 01815 foreach ($studentroles as $studentrole) { 01816 assign_capability('mod/data:writeentry', CAP_PREVENT, $studentrole->id, $context->id); 01817 } 01818 foreach ($teacherroles as $teacherrole) { 01819 assign_capability('mod/data:writeentry', CAP_ALLOW, $teacherrole->id, $context->id); 01820 } 01821 break; 01822 case 3: 01823 foreach ($studentroles as $studentrole) { 01824 assign_capability('mod/data:writeentry', CAP_ALLOW, $studentrole->id, $context->id); 01825 } 01826 foreach ($teacherroles as $teacherrole) { 01827 assign_capability('mod/data:writeentry', CAP_ALLOW, $teacherrole->id, $context->id); 01828 } 01829 break; 01830 } 01831 01832 // $data->assessed: 01833 // 2 - Only teachers can rate posts 01834 // 1 - Everyone can rate posts 01835 // 0 - No one can rate posts 01836 switch ($data->assessed) { 01837 case 0: 01838 foreach ($studentroles as $studentrole) { 01839 assign_capability('mod/data:rate', CAP_PREVENT, $studentrole->id, $context->id); 01840 } 01841 foreach ($teacherroles as $teacherrole) { 01842 assign_capability('mod/data:rate', CAP_PREVENT, $teacherrole->id, $context->id); 01843 } 01844 break; 01845 case 1: 01846 foreach ($studentroles as $studentrole) { 01847 assign_capability('mod/data:rate', CAP_ALLOW, $studentrole->id, $context->id); 01848 } 01849 foreach ($teacherroles as $teacherrole) { 01850 assign_capability('mod/data:rate', CAP_ALLOW, $teacherrole->id, $context->id); 01851 } 01852 break; 01853 case 2: 01854 foreach ($studentroles as $studentrole) { 01855 assign_capability('mod/data:rate', CAP_PREVENT, $studentrole->id, $context->id); 01856 } 01857 foreach ($teacherroles as $teacherrole) { 01858 assign_capability('mod/data:rate', CAP_ALLOW, $teacherrole->id, $context->id); 01859 } 01860 break; 01861 } 01862 01863 // $data->assesspublic: 01864 // 0 - Students can only see their own ratings 01865 // 1 - Students can see everyone's ratings 01866 switch ($data->assesspublic) { 01867 case 0: 01868 foreach ($studentroles as $studentrole) { 01869 assign_capability('mod/data:viewrating', CAP_PREVENT, $studentrole->id, $context->id); 01870 } 01871 foreach ($teacherroles as $teacherrole) { 01872 assign_capability('mod/data:viewrating', CAP_ALLOW, $teacherrole->id, $context->id); 01873 } 01874 break; 01875 case 1: 01876 foreach ($studentroles as $studentrole) { 01877 assign_capability('mod/data:viewrating', CAP_ALLOW, $studentrole->id, $context->id); 01878 } 01879 foreach ($teacherroles as $teacherrole) { 01880 assign_capability('mod/data:viewrating', CAP_ALLOW, $teacherrole->id, $context->id); 01881 } 01882 break; 01883 } 01884 01885 if (empty($cm)) { 01886 $cm = $DB->get_record('course_modules', array('id'=>$cmid)); 01887 } 01888 01889 switch ($cm->groupmode) { 01890 case NOGROUPS: 01891 break; 01892 case SEPARATEGROUPS: 01893 foreach ($studentroles as $studentrole) { 01894 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $studentrole->id, $context->id); 01895 } 01896 foreach ($teacherroles as $teacherrole) { 01897 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $teacherrole->id, $context->id); 01898 } 01899 break; 01900 case VISIBLEGROUPS: 01901 foreach ($studentroles as $studentrole) { 01902 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $studentrole->id, $context->id); 01903 } 01904 foreach ($teacherroles as $teacherrole) { 01905 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $teacherrole->id, $context->id); 01906 } 01907 break; 01908 } 01909 return true; 01910 } 01911 01919 function data_preset_name($shortname, $path) { 01920 01921 // We are looking inside the preset itself as a first choice, but also in normal data directory 01922 $string = get_string('modulename', 'datapreset_'.$shortname); 01923 01924 if (substr($string, 0, 1) == '[') { 01925 return $shortname; 01926 } else { 01927 return $string; 01928 } 01929 } 01930 01936 function data_get_available_presets($context) { 01937 global $CFG, $USER; 01938 01939 $presets = array(); 01940 01941 // First load the ratings sub plugins that exist within the modules preset dir 01942 if ($dirs = get_list_of_plugins('mod/data/preset')) { 01943 foreach ($dirs as $dir) { 01944 $fulldir = $CFG->dirroot.'/mod/data/preset/'.$dir; 01945 if (is_directory_a_preset($fulldir)) { 01946 $preset = new stdClass(); 01947 $preset->path = $fulldir; 01948 $preset->userid = 0; 01949 $preset->shortname = $dir; 01950 $preset->name = data_preset_name($dir, $fulldir); 01951 if (file_exists($fulldir.'/screenshot.jpg')) { 01952 $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.jpg'; 01953 } else if (file_exists($fulldir.'/screenshot.png')) { 01954 $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.png'; 01955 } else if (file_exists($fulldir.'/screenshot.gif')) { 01956 $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.gif'; 01957 } 01958 $presets[] = $preset; 01959 } 01960 } 01961 } 01962 // Now add to that the site presets that people have saved 01963 $presets = data_get_available_site_presets($context, $presets); 01964 return $presets; 01965 } 01966 01974 function data_get_available_site_presets($context, array $presets=array()) { 01975 global $USER; 01976 01977 $fs = get_file_storage(); 01978 $files = $fs->get_area_files(DATA_PRESET_CONTEXT, DATA_PRESET_COMPONENT, DATA_PRESET_FILEAREA); 01979 $canviewall = has_capability('mod/data:viewalluserpresets', $context); 01980 if (empty($files)) { 01981 return $presets; 01982 } 01983 foreach ($files as $file) { 01984 if (($file->is_directory() && $file->get_filepath()=='/') || !$file->is_directory() || (!$canviewall && $file->get_userid() != $USER->id)) { 01985 continue; 01986 } 01987 $preset = new stdClass; 01988 $preset->path = $file->get_filepath(); 01989 $preset->name = trim($preset->path, '/'); 01990 $preset->shortname = $preset->name; 01991 $preset->userid = $file->get_userid(); 01992 $preset->id = $file->get_id(); 01993 $preset->storedfile = $file; 01994 $presets[] = $preset; 01995 } 01996 return $presets; 01997 } 01998 02005 function data_delete_site_preset($name) { 02006 $fs = get_file_storage(); 02007 02008 $files = $fs->get_directory_files(DATA_PRESET_CONTEXT, DATA_PRESET_COMPONENT, DATA_PRESET_FILEAREA, 0, '/'.$name.'/'); 02009 if (!empty($files)) { 02010 foreach ($files as $file) { 02011 $file->delete(); 02012 } 02013 } 02014 02015 $dir = $fs->get_file(DATA_PRESET_CONTEXT, DATA_PRESET_COMPONENT, DATA_PRESET_FILEAREA, 0, '/'.$name.'/', '.'); 02016 if (!empty($dir)) { 02017 $dir->delete(); 02018 } 02019 return true; 02020 } 02021 02030 function data_print_header($course, $cm, $data, $currenttab='') { 02031 02032 global $CFG, $displaynoticegood, $displaynoticebad, $OUTPUT, $PAGE; 02033 02034 $PAGE->set_title($data->name); 02035 echo $OUTPUT->header(); 02036 echo $OUTPUT->heading(format_string($data->name)); 02037 02038 // Groups needed for Add entry tab 02039 $currentgroup = groups_get_activity_group($cm); 02040 $groupmode = groups_get_activity_groupmode($cm); 02041 02042 // Print the tabs 02043 02044 if ($currenttab) { 02045 include('tabs.php'); 02046 } 02047 02048 // Print any notices 02049 02050 if (!empty($displaynoticegood)) { 02051 echo $OUTPUT->notification($displaynoticegood, 'notifysuccess'); // good (usually green) 02052 } else if (!empty($displaynoticebad)) { 02053 echo $OUTPUT->notification($displaynoticebad); // bad (usuually red) 02054 } 02055 } 02056 02066 function data_user_can_add_entry($data, $currentgroup, $groupmode, $context = null) { 02067 global $USER; 02068 02069 if (empty($context)) { 02070 $cm = get_coursemodule_from_instance('data', $data->id, 0, false, MUST_EXIST); 02071 $context = get_context_instance(CONTEXT_MODULE, $cm->id); 02072 } 02073 02074 if (has_capability('mod/data:manageentries', $context)) { 02075 // no entry limits apply if user can manage 02076 02077 } else if (!has_capability('mod/data:writeentry', $context)) { 02078 return false; 02079 02080 } else if (data_atmaxentries($data)) { 02081 return false; 02082 } 02083 02084 //if in the view only time window 02085 $now = time(); 02086 if ($now>$data->timeviewfrom && $now<$data->timeviewto) { 02087 return false; 02088 } 02089 02090 if (!$groupmode or has_capability('moodle/site:accessallgroups', $context)) { 02091 return true; 02092 } 02093 02094 if ($currentgroup) { 02095 return groups_is_member($currentgroup); 02096 } else { 02097 //else it might be group 0 in visible mode 02098 if ($groupmode == VISIBLEGROUPS){ 02099 return true; 02100 } else { 02101 return false; 02102 } 02103 } 02104 } 02105 02106 02110 function is_directory_a_preset($directory) { 02111 $directory = rtrim($directory, '/\\') . '/'; 02112 $status = file_exists($directory.'singletemplate.html') && 02113 file_exists($directory.'listtemplate.html') && 02114 file_exists($directory.'listtemplateheader.html') && 02115 file_exists($directory.'listtemplatefooter.html') && 02116 file_exists($directory.'addtemplate.html') && 02117 file_exists($directory.'rsstemplate.html') && 02118 file_exists($directory.'rsstitletemplate.html') && 02119 file_exists($directory.'csstemplate.css') && 02120 file_exists($directory.'jstemplate.js') && 02121 file_exists($directory.'preset.xml'); 02122 02123 return $status; 02124 } 02125 02129 abstract class data_preset_importer { 02130 02131 protected $course; 02132 protected $cm; 02133 protected $module; 02134 protected $directory; 02135 02144 public function __construct($course, $cm, $module, $directory) { 02145 $this->course = $course; 02146 $this->cm = $cm; 02147 $this->module = $module; 02148 $this->directory = $directory; 02149 } 02150 02155 public function get_directory() { 02156 return basename($this->directory); 02157 } 02158 02167 public function data_preset_get_file_contents(&$filestorage, &$fileobj, $dir, $filename) { 02168 if(empty($filestorage) || empty($fileobj)) { 02169 if (substr($dir, -1)!='/') { 02170 $dir .= '/'; 02171 } 02172 return file_get_contents($dir.$filename); 02173 } else { 02174 $file = $filestorage->get_file(DATA_PRESET_CONTEXT, DATA_PRESET_COMPONENT, DATA_PRESET_FILEAREA, 0, $fileobj->get_filepath(), $filename); 02175 return $file->get_content(); 02176 } 02177 02178 } 02184 public function get_preset_settings() { 02185 global $DB; 02186 02187 $fs = $fileobj = null; 02188 if (!is_directory_a_preset($this->directory)) { 02189 //maybe the user requested a preset stored in the Moodle file storage 02190 02191 $fs = get_file_storage(); 02192 $files = $fs->get_area_files(DATA_PRESET_CONTEXT, DATA_PRESET_COMPONENT, DATA_PRESET_FILEAREA); 02193 02194 //preset name to find will be the final element of the directory 02195 $presettofind = end(explode('/',$this->directory)); 02196 02197 //now go through the available files available and see if we can find it 02198 foreach ($files as $file) { 02199 if (($file->is_directory() && $file->get_filepath()=='/') || !$file->is_directory()) { 02200 continue; 02201 } 02202 $presetname = trim($file->get_filepath(), '/'); 02203 if ($presetname==$presettofind) { 02204 $this->directory = $presetname; 02205 $fileobj = $file; 02206 } 02207 } 02208 02209 if (empty($fileobj)) { 02210 print_error('invalidpreset', 'data', '', $this->directory); 02211 } 02212 } 02213 02214 $allowed_settings = array( 02215 'intro', 02216 'comments', 02217 'requiredentries', 02218 'requiredentriestoview', 02219 'maxentries', 02220 'rssarticles', 02221 'approval', 02222 'defaultsortdir', 02223 'defaultsort'); 02224 02225 $result = new stdClass; 02226 $result->settings = new stdClass; 02227 $result->importfields = array(); 02228 $result->currentfields = $DB->get_records('data_fields', array('dataid'=>$this->module->id)); 02229 if (!$result->currentfields) { 02230 $result->currentfields = array(); 02231 } 02232 02233 02234 /* Grab XML */ 02235 $presetxml = $this->data_preset_get_file_contents($fs, $fileobj, $this->directory,'preset.xml'); 02236 $parsedxml = xmlize($presetxml, 0); 02237 02238 /* First, do settings. Put in user friendly array. */ 02239 $settingsarray = $parsedxml['preset']['#']['settings'][0]['#']; 02240 $result->settings = new StdClass(); 02241 foreach ($settingsarray as $setting => $value) { 02242 if (!is_array($value) || !in_array($setting, $allowed_settings)) { 02243 // unsupported setting 02244 continue; 02245 } 02246 $result->settings->$setting = $value[0]['#']; 02247 } 02248 02249 /* Now work out fields to user friendly array */ 02250 $fieldsarray = $parsedxml['preset']['#']['field']; 02251 foreach ($fieldsarray as $field) { 02252 if (!is_array($field)) { 02253 continue; 02254 } 02255 $f = new StdClass(); 02256 foreach ($field['#'] as $param => $value) { 02257 if (!is_array($value)) { 02258 continue; 02259 } 02260 $f->$param = $value[0]['#']; 02261 } 02262 $f->dataid = $this->module->id; 02263 $f->type = clean_param($f->type, PARAM_ALPHA); 02264 $result->importfields[] = $f; 02265 } 02266 /* Now add the HTML templates to the settings array so we can update d */ 02267 $result->settings->singletemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"singletemplate.html"); 02268 $result->settings->listtemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"listtemplate.html"); 02269 $result->settings->listtemplateheader = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"listtemplateheader.html"); 02270 $result->settings->listtemplatefooter = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"listtemplatefooter.html"); 02271 $result->settings->addtemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"addtemplate.html"); 02272 $result->settings->rsstemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"rsstemplate.html"); 02273 $result->settings->rsstitletemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"rsstitletemplate.html"); 02274 $result->settings->csstemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"csstemplate.css"); 02275 $result->settings->jstemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"jstemplate.js"); 02276 02277 //optional 02278 if (file_exists($this->directory."/asearchtemplate.html")) { 02279 $result->settings->asearchtemplate = $this->data_preset_get_file_contents($fs, $fileobj,$this->directory,"asearchtemplate.html"); 02280 } else { 02281 $result->settings->asearchtemplate = NULL; 02282 } 02283 $result->settings->instance = $this->module->id; 02284 02285 return $result; 02286 } 02287 02292 function import($overwritesettings) { 02293 global $DB, $CFG; 02294 02295 $params = $this->get_preset_settings(); 02296 $settings = $params->settings; 02297 $newfields = $params->importfields; 02298 $currentfields = $params->currentfields; 02299 $preservedfields = array(); 02300 02301 /* Maps fields and makes new ones */ 02302 if (!empty($newfields)) { 02303 /* We require an injective mapping, and need to know what to protect */ 02304 foreach ($newfields as $nid => $newfield) { 02305 $cid = optional_param("field_$nid", -1, PARAM_INT); 02306 if ($cid == -1) { 02307 continue; 02308 } 02309 if (array_key_exists($cid, $preservedfields)){ 02310 print_error('notinjectivemap', 'data'); 02311 } 02312 else $preservedfields[$cid] = true; 02313 } 02314 02315 foreach ($newfields as $nid => $newfield) { 02316 $cid = optional_param("field_$nid", -1, PARAM_INT); 02317 02318 /* A mapping. Just need to change field params. Data kept. */ 02319 if ($cid != -1 and isset($currentfields[$cid])) { 02320 $fieldobject = data_get_field_from_id($currentfields[$cid]->id, $this->module); 02321 foreach ($newfield as $param => $value) { 02322 if ($param != "id") { 02323 $fieldobject->field->$param = $value; 02324 } 02325 } 02326 unset($fieldobject->field->similarfield); 02327 $fieldobject->update_field(); 02328 unset($fieldobject); 02329 } else { 02330 /* Make a new field */ 02331 include_once("field/$newfield->type/field.class.php"); 02332 02333 if (!isset($newfield->description)) { 02334 $newfield->description = ''; 02335 } 02336 $classname = 'data_field_'.$newfield->type; 02337 $fieldclass = new $classname($newfield, $this->module); 02338 $fieldclass->insert_field(); 02339 unset($fieldclass); 02340 } 02341 } 02342 } 02343 02344 /* Get rid of all old unused data */ 02345 if (!empty($preservedfields)) { 02346 foreach ($currentfields as $cid => $currentfield) { 02347 if (!array_key_exists($cid, $preservedfields)) { 02348 /* Data not used anymore so wipe! */ 02349 print "Deleting field $currentfield->name<br />"; 02350 02351 $id = $currentfield->id; 02352 //Why delete existing data records and related comments/ratings?? 02353 $DB->delete_records('data_content', array('fieldid'=>$id)); 02354 $DB->delete_records('data_fields', array('id'=>$id)); 02355 } 02356 } 02357 } 02358 02359 // handle special settings here 02360 if (!empty($settings->defaultsort)) { 02361 if (is_numeric($settings->defaultsort)) { 02362 // old broken value 02363 $settings->defaultsort = 0; 02364 } else { 02365 $settings->defaultsort = (int)$DB->get_field('data_fields', 'id', array('dataid'=>$this->module->id, 'name'=>$settings->defaultsort)); 02366 } 02367 } else { 02368 $settings->defaultsort = 0; 02369 } 02370 02371 // do we want to overwrite all current database settings? 02372 if ($overwritesettings) { 02373 // all supported settings 02374 $overwrite = array_keys((array)$settings); 02375 } else { 02376 // only templates and sorting 02377 $overwrite = array('singletemplate', 'listtemplate', 'listtemplateheader', 'listtemplatefooter', 02378 'addtemplate', 'rsstemplate', 'rsstitletemplate', 'csstemplate', 'jstemplate', 02379 'asearchtemplate', 'defaultsortdir', 'defaultsort'); 02380 } 02381 02382 // now overwrite current data settings 02383 foreach ($this->module as $prop=>$unused) { 02384 if (in_array($prop, $overwrite)) { 02385 $this->module->$prop = $settings->$prop; 02386 } 02387 } 02388 02389 data_update_instance($this->module); 02390 02391 return $this->cleanup(); 02392 } 02393 02398 public function cleanup() { 02399 return true; 02400 } 02401 } 02402 02406 class data_preset_upload_importer extends data_preset_importer { 02407 public function __construct($course, $cm, $module, $filepath) { 02408 global $USER; 02409 if (is_file($filepath)) { 02410 $fp = get_file_packer(); 02411 if ($fp->extract_to_pathname($filepath, $filepath.'_extracted')) { 02412 fulldelete($filepath); 02413 } 02414 $filepath .= '_extracted'; 02415 } 02416 parent::__construct($course, $cm, $module, $filepath); 02417 } 02418 public function cleanup() { 02419 return fulldelete($this->directory); 02420 } 02421 } 02422 02426 class data_preset_existing_importer extends data_preset_importer { 02427 protected $userid; 02428 public function __construct($course, $cm, $module, $fullname) { 02429 global $USER; 02430 list($userid, $shortname) = explode('/', $fullname, 2); 02431 $context = get_context_instance(CONTEXT_MODULE, $cm->id); 02432 if ($userid && ($userid != $USER->id) && !has_capability('mod/data:manageuserpresets', $context) && !has_capability('mod/data:viewalluserpresets', $context)) { 02433 throw new coding_exception('Invalid preset provided'); 02434 } 02435 02436 $this->userid = $userid; 02437 $filepath = data_preset_path($course, $userid, $shortname); 02438 parent::__construct($course, $cm, $module, $filepath); 02439 } 02440 public function get_userid() { 02441 return $this->userid; 02442 } 02443 } 02444 02453 function data_preset_path($course, $userid, $shortname) { 02454 global $USER, $CFG; 02455 02456 $context = get_context_instance(CONTEXT_COURSE, $course->id); 02457 02458 $userid = (int)$userid; 02459 02460 $path = null; 02461 if ($userid > 0 && ($userid == $USER->id || has_capability('mod/data:viewalluserpresets', $context))) { 02462 $path = $CFG->dataroot.'/data/preset/'.$userid.'/'.$shortname; 02463 } else if ($userid == 0) { 02464 $path = $CFG->dirroot.'/mod/data/preset/'.$shortname; 02465 } else if ($userid < 0) { 02466 $path = $CFG->tempdir.'/data/'.-$userid.'/'.$shortname; 02467 } 02468 02469 return $path; 02470 } 02471 02478 function data_reset_course_form_definition(&$mform) { 02479 $mform->addElement('header', 'dataheader', get_string('modulenameplural', 'data')); 02480 $mform->addElement('checkbox', 'reset_data', get_string('deleteallentries','data')); 02481 02482 $mform->addElement('checkbox', 'reset_data_notenrolled', get_string('deletenotenrolled', 'data')); 02483 $mform->disabledIf('reset_data_notenrolled', 'reset_data', 'checked'); 02484 02485 $mform->addElement('checkbox', 'reset_data_ratings', get_string('deleteallratings')); 02486 $mform->disabledIf('reset_data_ratings', 'reset_data', 'checked'); 02487 02488 $mform->addElement('checkbox', 'reset_data_comments', get_string('deleteallcomments')); 02489 $mform->disabledIf('reset_data_comments', 'reset_data', 'checked'); 02490 } 02491 02496 function data_reset_course_form_defaults($course) { 02497 return array('reset_data'=>0, 'reset_data_ratings'=>1, 'reset_data_comments'=>1, 'reset_data_notenrolled'=>0); 02498 } 02499 02508 function data_reset_gradebook($courseid, $type='') { 02509 global $CFG, $DB; 02510 02511 $sql = "SELECT d.*, cm.idnumber as cmidnumber, d.course as courseid 02512 FROM {data} d, {course_modules} cm, {modules} m 02513 WHERE m.name='data' AND m.id=cm.module AND cm.instance=d.id AND d.course=?"; 02514 02515 if ($datas = $DB->get_records_sql($sql, array($courseid))) { 02516 foreach ($datas as $data) { 02517 data_grade_item_update($data, 'reset'); 02518 } 02519 } 02520 } 02521 02531 function data_reset_userdata($data) { 02532 global $CFG, $DB; 02533 require_once($CFG->libdir.'/filelib.php'); 02534 require_once($CFG->dirroot.'/rating/lib.php'); 02535 02536 $componentstr = get_string('modulenameplural', 'data'); 02537 $status = array(); 02538 02539 $allrecordssql = "SELECT r.id 02540 FROM {data_records} r 02541 INNER JOIN {data} d ON r.dataid = d.id 02542 WHERE d.course = ?"; 02543 02544 $alldatassql = "SELECT d.id 02545 FROM {data} d 02546 WHERE d.course=?"; 02547 02548 $rm = new rating_manager(); 02549 $ratingdeloptions = new stdClass; 02550 $ratingdeloptions->component = 'mod_data'; 02551 $ratingdeloptions->ratingarea = 'entry'; 02552 02553 // delete entries if requested 02554 if (!empty($data->reset_data)) { 02555 $DB->delete_records_select('comments', "itemid IN ($allrecordssql) AND commentarea='database_entry'", array($data->courseid)); 02556 $DB->delete_records_select('data_content', "recordid IN ($allrecordssql)", array($data->courseid)); 02557 $DB->delete_records_select('data_records', "dataid IN ($alldatassql)", array($data->courseid)); 02558 02559 if ($datas = $DB->get_records_sql($alldatassql, array($data->courseid))) { 02560 foreach ($datas as $dataid=>$unused) { 02561 fulldelete("$CFG->dataroot/$data->courseid/moddata/data/$dataid"); 02562 02563 if (!$cm = get_coursemodule_from_instance('data', $dataid)) { 02564 continue; 02565 } 02566 $datacontext = get_context_instance(CONTEXT_MODULE, $cm->id); 02567 02568 $ratingdeloptions->contextid = $datacontext->id; 02569 $rm->delete_ratings($ratingdeloptions); 02570 } 02571 } 02572 02573 if (empty($data->reset_gradebook_grades)) { 02574 // remove all grades from gradebook 02575 data_reset_gradebook($data->courseid); 02576 } 02577 $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallentries', 'data'), 'error'=>false); 02578 } 02579 02580 // remove entries by users not enrolled into course 02581 if (!empty($data->reset_data_notenrolled)) { 02582 $recordssql = "SELECT r.id, r.userid, r.dataid, u.id AS userexists, u.deleted AS userdeleted 02583 FROM {data_records} r 02584 JOIN {data} d ON r.dataid = d.id 02585 LEFT JOIN {user} u ON r.userid = u.id 02586 WHERE d.course = ? AND r.userid > 0"; 02587 02588 $course_context = get_context_instance(CONTEXT_COURSE, $data->courseid); 02589 $notenrolled = array(); 02590 $fields = array(); 02591 $rs = $DB->get_recordset_sql($recordssql, array($data->courseid)); 02592 foreach ($rs as $record) { 02593 if (array_key_exists($record->userid, $notenrolled) or !$record->userexists or $record->userdeleted 02594 or !is_enrolled($course_context, $record->userid)) { 02595 //delete ratings 02596 if (!$cm = get_coursemodule_from_instance('data', $record->dataid)) { 02597 continue; 02598 } 02599 $datacontext = get_context_instance(CONTEXT_MODULE, $cm->id); 02600 $ratingdeloptions->contextid = $datacontext->id; 02601 $ratingdeloptions->itemid = $record->id; 02602 $rm->delete_ratings($ratingdeloptions); 02603 02604 $DB->delete_records('comments', array('itemid'=>$record->id, 'commentarea'=>'database_entry')); 02605 $DB->delete_records('data_content', array('recordid'=>$record->id)); 02606 $DB->delete_records('data_records', array('id'=>$record->id)); 02607 // HACK: this is ugly - the recordid should be before the fieldid! 02608 if (!array_key_exists($record->dataid, $fields)) { 02609 if ($fs = $DB->get_records('data_fields', array('dataid'=>$record->dataid))) { 02610 $fields[$record->dataid] = array_keys($fs); 02611 } else { 02612 $fields[$record->dataid] = array(); 02613 } 02614 } 02615 foreach($fields[$record->dataid] as $fieldid) { 02616 fulldelete("$CFG->dataroot/$data->courseid/moddata/data/$record->dataid/$fieldid/$record->id"); 02617 } 02618 $notenrolled[$record->userid] = true; 02619 } 02620 } 02621 $rs->close(); 02622 $status[] = array('component'=>$componentstr, 'item'=>get_string('deletenotenrolled', 'data'), 'error'=>false); 02623 } 02624 02625 // remove all ratings 02626 if (!empty($data->reset_data_ratings)) { 02627 if ($datas = $DB->get_records_sql($alldatassql, array($data->courseid))) { 02628 foreach ($datas as $dataid=>$unused) { 02629 if (!$cm = get_coursemodule_from_instance('data', $dataid)) { 02630 continue; 02631 } 02632 $datacontext = get_context_instance(CONTEXT_MODULE, $cm->id); 02633 02634 $ratingdeloptions->contextid = $datacontext->id; 02635 $rm->delete_ratings($ratingdeloptions); 02636 } 02637 } 02638 02639 if (empty($data->reset_gradebook_grades)) { 02640 // remove all grades from gradebook 02641 data_reset_gradebook($data->courseid); 02642 } 02643 02644 $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallratings'), 'error'=>false); 02645 } 02646 02647 // remove all comments 02648 if (!empty($data->reset_data_comments)) { 02649 $DB->delete_records_select('comments', "itemid IN ($allrecordssql) AND commentarea='database_entry'", array($data->courseid)); 02650 $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallcomments'), 'error'=>false); 02651 } 02652 02653 // updating dates - shift may be negative too 02654 if ($data->timeshift) { 02655 shift_course_mod_dates('data', array('timeavailablefrom', 'timeavailableto', 'timeviewfrom', 'timeviewto'), $data->timeshift, $data->courseid); 02656 $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged'), 'error'=>false); 02657 } 02658 02659 return $status; 02660 } 02661 02667 function data_get_extra_capabilities() { 02668 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'); 02669 } 02670 02675 function data_supports($feature) { 02676 switch($feature) { 02677 case FEATURE_GROUPS: return true; 02678 case FEATURE_GROUPINGS: return true; 02679 case FEATURE_GROUPMEMBERSONLY: return true; 02680 case FEATURE_MOD_INTRO: return true; 02681 case FEATURE_COMPLETION_TRACKS_VIEWS: return true; 02682 case FEATURE_GRADE_HAS_GRADE: return true; 02683 case FEATURE_GRADE_OUTCOMES: return true; 02684 case FEATURE_RATE: return true; 02685 case FEATURE_BACKUP_MOODLE2: return true; 02686 case FEATURE_SHOW_DESCRIPTION: return true; 02687 02688 default: return null; 02689 } 02690 } 02700 function data_export_csv($export, $delimiter_name, $dataname, $count, $return=false) { 02701 global $CFG; 02702 require_once($CFG->libdir . '/csvlib.class.php'); 02703 $delimiter = csv_import_reader::get_delimiter($delimiter_name); 02704 $filename = clean_filename("{$dataname}-{$count}_record"); 02705 if ($count > 1) { 02706 $filename .= 's'; 02707 } 02708 $filename .= clean_filename('-' . gmdate("Ymd_Hi")); 02709 $filename .= clean_filename("-{$delimiter_name}_separated"); 02710 $filename .= '.csv'; 02711 if (empty($return)) { 02712 header("Content-Type: application/download\n"); 02713 header("Content-Disposition: attachment; filename=$filename"); 02714 header('Expires: 0'); 02715 header('Cache-Control: must-revalidate,post-check=0,pre-check=0'); 02716 header('Pragma: public'); 02717 } 02718 $encdelim = '&#' . ord($delimiter) . ';'; 02719 $returnstr = ''; 02720 foreach($export as $row) { 02721 foreach($row as $key => $column) { 02722 $row[$key] = str_replace($delimiter, $encdelim, $column); 02723 } 02724 $returnstr .= implode($delimiter, $row) . "\n"; 02725 } 02726 if (empty($return)) { 02727 echo $returnstr; 02728 return; 02729 } 02730 return $returnstr; 02731 } 02732 02740 function data_export_xls($export, $dataname, $count) { 02741 global $CFG; 02742 require_once("$CFG->libdir/excellib.class.php"); 02743 $filename = clean_filename("{$dataname}-{$count}_record"); 02744 if ($count > 1) { 02745 $filename .= 's'; 02746 } 02747 $filename .= clean_filename('-' . gmdate("Ymd_Hi")); 02748 $filename .= '.xls'; 02749 02750 $filearg = '-'; 02751 $workbook = new MoodleExcelWorkbook($filearg); 02752 $workbook->send($filename); 02753 $worksheet = array(); 02754 $worksheet[0] =& $workbook->add_worksheet(''); 02755 $rowno = 0; 02756 foreach ($export as $row) { 02757 $colno = 0; 02758 foreach($row as $col) { 02759 $worksheet[0]->write($rowno, $colno, $col); 02760 $colno++; 02761 } 02762 $rowno++; 02763 } 02764 $workbook->close(); 02765 return $filename; 02766 } 02767 02775 function data_export_ods($export, $dataname, $count) { 02776 global $CFG; 02777 require_once("$CFG->libdir/odslib.class.php"); 02778 $filename = clean_filename("{$dataname}-{$count}_record"); 02779 if ($count > 1) { 02780 $filename .= 's'; 02781 } 02782 $filename .= clean_filename('-' . gmdate("Ymd_Hi")); 02783 $filename .= '.ods'; 02784 $filearg = '-'; 02785 $workbook = new MoodleODSWorkbook($filearg); 02786 $workbook->send($filename); 02787 $worksheet = array(); 02788 $worksheet[0] =& $workbook->add_worksheet(''); 02789 $rowno = 0; 02790 foreach ($export as $row) { 02791 $colno = 0; 02792 foreach($row as $col) { 02793 $worksheet[0]->write($rowno, $colno, $col); 02794 $colno++; 02795 } 02796 $rowno++; 02797 } 02798 $workbook->close(); 02799 return $filename; 02800 } 02801 02811 function data_get_exportdata($dataid, $fields, $selectedfields, $currentgroup=0) { 02812 global $DB; 02813 02814 $exportdata = array(); 02815 02816 // populate the header in first row of export 02817 foreach($fields as $key => $field) { 02818 if (!in_array($field->field->id, $selectedfields)) { 02819 // ignore values we aren't exporting 02820 unset($fields[$key]); 02821 } else { 02822 $exportdata[0][] = $field->field->name; 02823 } 02824 } 02825 02826 $datarecords = $DB->get_records('data_records', array('dataid'=>$dataid)); 02827 ksort($datarecords); 02828 $line = 1; 02829 foreach($datarecords as $record) { 02830 // get content indexed by fieldid 02831 if ($currentgroup) { 02832 $select = 'SELECT c.fieldid, c.content, c.content1, c.content2, c.content3, c.content4 FROM {data_content} c, {data_records} r WHERE c.recordid = ? AND r.id = c.recordid AND r.groupid = ?'; 02833 $where = array($record->id, $currentgroup); 02834 } else { 02835 $select = 'SELECT fieldid, content, content1, content2, content3, content4 FROM {data_content} WHERE recordid = ?'; 02836 $where = array($record->id); 02837 } 02838 02839 if( $content = $DB->get_records_sql($select, $where) ) { 02840 foreach($fields as $field) { 02841 $contents = ''; 02842 if(isset($content[$field->field->id])) { 02843 $contents = $field->export_text_value($content[$field->field->id]); 02844 } 02845 $exportdata[$line][] = $contents; 02846 } 02847 } 02848 $line++; 02849 } 02850 $line--; 02851 return $exportdata; 02852 } 02853 02862 function data_get_file_areas($course, $cm, $context) { 02863 $areas = array(); 02864 return $areas; 02865 } 02866 02878 function data_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) { 02879 global $CFG, $DB; 02880 02881 if ($context->contextlevel != CONTEXT_MODULE) { 02882 return false; 02883 } 02884 02885 require_course_login($course, true, $cm); 02886 02887 if ($filearea === 'content') { 02888 $contentid = (int)array_shift($args); 02889 02890 if (!$content = $DB->get_record('data_content', array('id'=>$contentid))) { 02891 return false; 02892 } 02893 02894 if (!$field = $DB->get_record('data_fields', array('id'=>$content->fieldid))) { 02895 return false; 02896 } 02897 02898 if (!$record = $DB->get_record('data_records', array('id'=>$content->recordid))) { 02899 return false; 02900 } 02901 02902 if (!$data = $DB->get_record('data', array('id'=>$field->dataid))) { 02903 return false; 02904 } 02905 02906 if ($data->id != $cm->instance) { 02907 // hacker attempt - context does not match the contentid 02908 return false; 02909 } 02910 02911 //check if approved 02912 if ($data->approval and !$record->approved and !data_isowner($record) and !has_capability('mod/data:approve', $context)) { 02913 return false; 02914 } 02915 02916 // group access 02917 if ($record->groupid) { 02918 $groupmode = groups_get_activity_groupmode($cm, $course); 02919 if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) { 02920 if (!groups_is_member($record->groupid)) { 02921 return false; 02922 } 02923 } 02924 } 02925 02926 $fieldobj = data_get_field($field, $data, $cm); 02927 02928 $relativepath = implode('/', $args); 02929 $fullpath = "/$context->id/mod_data/content/$content->id/$relativepath"; 02930 02931 if (!$fieldobj->file_ok($relativepath)) { 02932 return false; 02933 } 02934 02935 $fs = get_file_storage(); 02936 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { 02937 return false; 02938 } 02939 02940 // finally send the file 02941 send_stored_file($file, 0, 0, true); // download MUST be forced - security! 02942 } 02943 02944 return false; 02945 } 02946 02947 02948 function data_extend_navigation($navigation, $course, $module, $cm) { 02949 global $CFG, $OUTPUT, $USER, $DB; 02950 02951 $rid = optional_param('rid', 0, PARAM_INT); 02952 02953 $data = $DB->get_record('data', array('id'=>$cm->instance)); 02954 $currentgroup = groups_get_activity_group($cm); 02955 $groupmode = groups_get_activity_groupmode($cm); 02956 02957 $numentries = data_numentries($data); 02959 if ($data->requiredentries > 0 && $numentries < $data->requiredentries && !has_capability('mod/data:manageentries', get_context_instance(CONTEXT_MODULE, $cm->id))) { 02960 $data->entriesleft = $data->requiredentries - $numentries; 02961 $entriesnode = $navigation->add(get_string('entrieslefttoadd', 'data', $data)); 02962 $entriesnode->add_class('note'); 02963 } 02964 02965 $navigation->add(get_string('list', 'data'), new moodle_url('/mod/data/view.php', array('d'=>$cm->instance))); 02966 if (!empty($rid)) { 02967 $navigation->add(get_string('single', 'data'), new moodle_url('/mod/data/view.php', array('d'=>$cm->instance, 'rid'=>$rid))); 02968 } else { 02969 $navigation->add(get_string('single', 'data'), new moodle_url('/mod/data/view.php', array('d'=>$cm->instance, 'mode'=>'single'))); 02970 } 02971 $navigation->add(get_string('search', 'data'), new moodle_url('/mod/data/view.php', array('d'=>$cm->instance, 'mode'=>'asearch'))); 02972 } 02973 02980 function data_extend_settings_navigation(settings_navigation $settings, navigation_node $datanode) { 02981 global $PAGE, $DB, $CFG, $USER; 02982 02983 $data = $DB->get_record('data', array("id" => $PAGE->cm->instance)); 02984 02985 $currentgroup = groups_get_activity_group($PAGE->cm); 02986 $groupmode = groups_get_activity_groupmode($PAGE->cm); 02987 02988 if (data_user_can_add_entry($data, $currentgroup, $groupmode, $PAGE->cm->context)) { // took out participation list here! 02989 if (empty($editentry)) { //TODO: undefined 02990 $addstring = get_string('add', 'data'); 02991 } else { 02992 $addstring = get_string('editentry', 'data'); 02993 } 02994 $datanode->add($addstring, new moodle_url('/mod/data/edit.php', array('d'=>$PAGE->cm->instance))); 02995 } 02996 02997 if (has_capability(DATA_CAP_EXPORT, $PAGE->cm->context)) { 02998 // The capability required to Export database records is centrally defined in 'lib.php' 02999 // and should be weaker than those required to edit Templates, Fields and Presets. 03000 $datanode->add(get_string('exportentries', 'data'), new moodle_url('/mod/data/export.php', array('d'=>$data->id))); 03001 } 03002 if (has_capability('mod/data:manageentries', $PAGE->cm->context)) { 03003 $datanode->add(get_string('importentries', 'data'), new moodle_url('/mod/data/import.php', array('d'=>$data->id))); 03004 } 03005 03006 if (has_capability('mod/data:managetemplates', $PAGE->cm->context)) { 03007 $currenttab = ''; 03008 if ($currenttab == 'list') { 03009 $defaultemplate = 'listtemplate'; 03010 } else if ($currenttab == 'add') { 03011 $defaultemplate = 'addtemplate'; 03012 } else if ($currenttab == 'asearch') { 03013 $defaultemplate = 'asearchtemplate'; 03014 } else { 03015 $defaultemplate = 'singletemplate'; 03016 } 03017 03018 $templates = $datanode->add(get_string('templates', 'data')); 03019 03020 $templatelist = array ('listtemplate', 'singletemplate', 'asearchtemplate', 'addtemplate', 'rsstemplate', 'csstemplate', 'jstemplate'); 03021 foreach ($templatelist as $template) { 03022 $templates->add(get_string($template, 'data'), new moodle_url('/mod/data/templates.php', array('d'=>$data->id,'mode'=>$template))); 03023 } 03024 03025 $datanode->add(get_string('fields', 'data'), new moodle_url('/mod/data/field.php', array('d'=>$data->id))); 03026 $datanode->add(get_string('presets', 'data'), new moodle_url('/mod/data/preset.php', array('d'=>$data->id))); 03027 } 03028 03029 if (!empty($CFG->enablerssfeeds) && !empty($CFG->data_enablerssfeeds) && $data->rssarticles > 0) { 03030 require_once("$CFG->libdir/rsslib.php"); 03031 03032 $string = get_string('rsstype','forum'); 03033 03034 $url = new moodle_url(rss_get_url($PAGE->cm->context->id, $USER->id, 'mod_data', $data->id)); 03035 $datanode->add($string, $url, settings_navigation::TYPE_SETTING, null, null, new pix_icon('i/rss', '')); 03036 } 03037 } 03038 03048 function data_presets_save($course, $cm, $data, $path) { 03049 $fs = get_file_storage(); 03050 $filerecord = new stdClass; 03051 $filerecord->contextid = DATA_PRESET_CONTEXT; 03052 $filerecord->component = DATA_PRESET_COMPONENT; 03053 $filerecord->filearea = DATA_PRESET_FILEAREA; 03054 $filerecord->itemid = 0; 03055 $filerecord->filepath = '/'.$path.'/'; 03056 03057 $filerecord->filename = 'preset.xml'; 03058 $fs->create_file_from_string($filerecord, data_presets_generate_xml($course, $cm, $data)); 03059 03060 $filerecord->filename = 'singletemplate.html'; 03061 $fs->create_file_from_string($filerecord, $data->singletemplate); 03062 03063 $filerecord->filename = 'listtemplateheader.html'; 03064 $fs->create_file_from_string($filerecord, $data->listtemplateheader); 03065 03066 $filerecord->filename = 'listtemplate.html'; 03067 $fs->create_file_from_string($filerecord, $data->listtemplate); 03068 03069 $filerecord->filename = 'listtemplatefooter.html'; 03070 $fs->create_file_from_string($filerecord, $data->listtemplatefooter); 03071 03072 $filerecord->filename = 'addtemplate.html'; 03073 $fs->create_file_from_string($filerecord, $data->addtemplate); 03074 03075 $filerecord->filename = 'rsstemplate.html'; 03076 $fs->create_file_from_string($filerecord, $data->rsstemplate); 03077 03078 $filerecord->filename = 'rsstitletemplate.html'; 03079 $fs->create_file_from_string($filerecord, $data->rsstitletemplate); 03080 03081 $filerecord->filename = 'csstemplate.css'; 03082 $fs->create_file_from_string($filerecord, $data->csstemplate); 03083 03084 $filerecord->filename = 'jstemplate.js'; 03085 $fs->create_file_from_string($filerecord, $data->jstemplate); 03086 03087 $filerecord->filename = 'asearchtemplate.html'; 03088 $fs->create_file_from_string($filerecord, $data->asearchtemplate); 03089 03090 return true; 03091 } 03092 03102 function data_presets_generate_xml($course, $cm, $data) { 03103 global $DB; 03104 03105 // Assemble "preset.xml": 03106 $presetxmldata = "<preset>\n\n"; 03107 03108 // Raw settings are not preprocessed during saving of presets 03109 $raw_settings = array( 03110 'intro', 03111 'comments', 03112 'requiredentries', 03113 'requiredentriestoview', 03114 'maxentries', 03115 'rssarticles', 03116 'approval', 03117 'defaultsortdir' 03118 ); 03119 03120 $presetxmldata .= "<settings>\n"; 03121 // First, settings that do not require any conversion 03122 foreach ($raw_settings as $setting) { 03123 $presetxmldata .= "<$setting>" . htmlspecialchars($data->$setting) . "</$setting>\n"; 03124 } 03125 03126 // Now specific settings 03127 if ($data->defaultsort > 0 && $sortfield = data_get_field_from_id($data->defaultsort, $data)) { 03128 $presetxmldata .= '<defaultsort>' . htmlspecialchars($sortfield->field->name) . "</defaultsort>\n"; 03129 } else { 03130 $presetxmldata .= "<defaultsort>0</defaultsort>\n"; 03131 } 03132 $presetxmldata .= "</settings>\n\n"; 03133 // Now for the fields. Grab all that are non-empty 03134 $fields = $DB->get_records('data_fields', array('dataid'=>$data->id)); 03135 ksort($fields); 03136 if (!empty($fields)) { 03137 foreach ($fields as $field) { 03138 $presetxmldata .= "<field>\n"; 03139 foreach ($field as $key => $value) { 03140 if ($value != '' && $key != 'id' && $key != 'dataid') { 03141 $presetxmldata .= "<$key>" . htmlspecialchars($value) . "</$key>\n"; 03142 } 03143 } 03144 $presetxmldata .= "</field>\n\n"; 03145 } 03146 } 03147 $presetxmldata .= '</preset>'; 03148 return $presetxmldata; 03149 } 03150 03151 function data_presets_export($course, $cm, $data, $tostorage=false) { 03152 global $CFG, $DB; 03153 03154 $presetname = clean_filename($data->name) . '-preset-' . gmdate("Ymd_Hi"); 03155 $exportsubdir = "mod_data/presetexport/$presetname"; 03156 make_temp_directory($exportsubdir); 03157 $exportdir = "$CFG->tempdir/$exportsubdir"; 03158 03159 // Assemble "preset.xml": 03160 $presetxmldata = data_presets_generate_xml($course, $cm, $data); 03161 03162 // After opening a file in write mode, close it asap 03163 $presetxmlfile = fopen($exportdir . '/preset.xml', 'w'); 03164 fwrite($presetxmlfile, $presetxmldata); 03165 fclose($presetxmlfile); 03166 03167 // Now write the template files 03168 $singletemplate = fopen($exportdir . '/singletemplate.html', 'w'); 03169 fwrite($singletemplate, $data->singletemplate); 03170 fclose($singletemplate); 03171 03172 $listtemplateheader = fopen($exportdir . '/listtemplateheader.html', 'w'); 03173 fwrite($listtemplateheader, $data->listtemplateheader); 03174 fclose($listtemplateheader); 03175 03176 $listtemplate = fopen($exportdir . '/listtemplate.html', 'w'); 03177 fwrite($listtemplate, $data->listtemplate); 03178 fclose($listtemplate); 03179 03180 $listtemplatefooter = fopen($exportdir . '/listtemplatefooter.html', 'w'); 03181 fwrite($listtemplatefooter, $data->listtemplatefooter); 03182 fclose($listtemplatefooter); 03183 03184 $addtemplate = fopen($exportdir . '/addtemplate.html', 'w'); 03185 fwrite($addtemplate, $data->addtemplate); 03186 fclose($addtemplate); 03187 03188 $rsstemplate = fopen($exportdir . '/rsstemplate.html', 'w'); 03189 fwrite($rsstemplate, $data->rsstemplate); 03190 fclose($rsstemplate); 03191 03192 $rsstitletemplate = fopen($exportdir . '/rsstitletemplate.html', 'w'); 03193 fwrite($rsstitletemplate, $data->rsstitletemplate); 03194 fclose($rsstitletemplate); 03195 03196 $csstemplate = fopen($exportdir . '/csstemplate.css', 'w'); 03197 fwrite($csstemplate, $data->csstemplate); 03198 fclose($csstemplate); 03199 03200 $jstemplate = fopen($exportdir . '/jstemplate.js', 'w'); 03201 fwrite($jstemplate, $data->jstemplate); 03202 fclose($jstemplate); 03203 03204 $asearchtemplate = fopen($exportdir . '/asearchtemplate.html', 'w'); 03205 fwrite($asearchtemplate, $data->asearchtemplate); 03206 fclose($asearchtemplate); 03207 03208 // Check if all files have been generated 03209 if (! is_directory_a_preset($exportdir)) { 03210 print_error('generateerror', 'data'); 03211 } 03212 03213 $filenames = array( 03214 'preset.xml', 03215 'singletemplate.html', 03216 'listtemplateheader.html', 03217 'listtemplate.html', 03218 'listtemplatefooter.html', 03219 'addtemplate.html', 03220 'rsstemplate.html', 03221 'rsstitletemplate.html', 03222 'csstemplate.css', 03223 'jstemplate.js', 03224 'asearchtemplate.html' 03225 ); 03226 03227 $filelist = array(); 03228 foreach ($filenames as $filename) { 03229 $filelist[$filename] = $exportdir . '/' . $filename; 03230 } 03231 03232 $exportfile = $exportdir.'.zip'; 03233 file_exists($exportfile) && unlink($exportfile); 03234 03235 $fp = get_file_packer('application/zip'); 03236 $fp->archive_to_pathname($filelist, $exportfile); 03237 03238 foreach ($filelist as $file) { 03239 unlink($file); 03240 } 03241 rmdir($exportdir); 03242 03243 // Return the full path to the exported preset file: 03244 return $exportfile; 03245 } 03246 03264 function data_comment_permissions($comment_param) { 03265 global $CFG, $DB; 03266 if (!$record = $DB->get_record('data_records', array('id'=>$comment_param->itemid))) { 03267 throw new comment_exception('invalidcommentitemid'); 03268 } 03269 if (!$data = $DB->get_record('data', array('id'=>$record->dataid))) { 03270 throw new comment_exception('invalidid', 'data'); 03271 } 03272 if ($data->comments) { 03273 return array('post'=>true, 'view'=>true); 03274 } else { 03275 return array('post'=>false, 'view'=>false); 03276 } 03277 } 03278 03291 function data_comment_validate($comment_param) { 03292 global $DB; 03293 // validate comment area 03294 if ($comment_param->commentarea != 'database_entry') { 03295 throw new comment_exception('invalidcommentarea'); 03296 } 03297 // validate itemid 03298 if (!$record = $DB->get_record('data_records', array('id'=>$comment_param->itemid))) { 03299 throw new comment_exception('invalidcommentitemid'); 03300 } 03301 if (!$data = $DB->get_record('data', array('id'=>$record->dataid))) { 03302 throw new comment_exception('invalidid', 'data'); 03303 } 03304 if (!$course = $DB->get_record('course', array('id'=>$data->course))) { 03305 throw new comment_exception('coursemisconf'); 03306 } 03307 if (!$cm = get_coursemodule_from_instance('data', $data->id, $course->id)) { 03308 throw new comment_exception('invalidcoursemodule'); 03309 } 03310 if (!$data->comments) { 03311 throw new comment_exception('commentsoff', 'data'); 03312 } 03313 $context = get_context_instance(CONTEXT_MODULE, $cm->id); 03314 03315 //check if approved 03316 if ($data->approval and !$record->approved and !data_isowner($record) and !has_capability('mod/data:approve', $context)) { 03317 throw new comment_exception('notapproved', 'data'); 03318 } 03319 03320 // group access 03321 if ($record->groupid) { 03322 $groupmode = groups_get_activity_groupmode($cm, $course); 03323 if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) { 03324 if (!groups_is_member($record->groupid)) { 03325 throw new comment_exception('notmemberofgroup'); 03326 } 03327 } 03328 } 03329 // validate context id 03330 if ($context->id != $comment_param->context->id) { 03331 throw new comment_exception('invalidcontext'); 03332 } 03333 // validation for comment deletion 03334 if (!empty($comment_param->commentid)) { 03335 if ($comment = $DB->get_record('comments', array('id'=>$comment_param->commentid))) { 03336 if ($comment->commentarea != 'database_entry') { 03337 throw new comment_exception('invalidcommentarea'); 03338 } 03339 if ($comment->contextid != $comment_param->context->id) { 03340 throw new comment_exception('invalidcontext'); 03341 } 03342 if ($comment->itemid != $comment_param->itemid) { 03343 throw new comment_exception('invalidcommentitemid'); 03344 } 03345 } else { 03346 throw new comment_exception('invalidcommentid'); 03347 } 03348 } 03349 return true; 03350 } 03351 03358 function data_page_type_list($pagetype, $parentcontext, $currentcontext) { 03359 $module_pagetype = array('mod-data-*'=>get_string('page-mod-data-x', 'data')); 03360 return $module_pagetype; 03361 }