23
23
///////////////////////////////////////////////////////////////////////////
26
26
define ('DATA_MAX_ENTRIES', 50);
27
27
define ('DATA_PERPAGE_SINGLE', 1);
29
class data_field_base { /// Base class for Database Field Types (see field/*/field.class.php)
31
var $type = 'unknown'; /// Subclasses must override the type with their name
32
var $data = NULL; /// The database object that this field belongs to
33
var $field = NULL; /// The field object itself, if we know it
35
var $iconwidth = 16; /// Width of the icon for this fieldtype
36
var $iconheight = 16; /// Width of the icon for this fieldtype
39
/// Constructor function
28
define ('DATA_FIRSTNAME', -1);
29
define ('DATA_LASTNAME', -2);
30
define ('DATA_APPROVED', -3);
31
define ('DATA_TIMEADDED', 0);
32
define ('DATA_TIMEMODIFIED', -4);
34
define ('DATA_CAP_EXPORT', 'mod/data:viewalluserpresets');
35
// Users having assigned the default role "Non-editing teacher" can export database records
36
// Using the mod/data capability "viewalluserpresets" for Moodle 1.9.x, so no change in the role system is required.
37
// In Moodle >= 2, new roles may be introduced and used instead.
39
class data_field_base { // Base class for Database Field Types (see field/*/field.class.php)
41
var $type = 'unknown'; // Subclasses must override the type with their name
42
var $data = NULL; // The database object that this field belongs to
43
var $field = NULL; // The field object itself, if we know it
45
var $iconwidth = 16; // Width of the icon for this fieldtype
46
var $iconheight = 16; // Width of the icon for this fieldtype
49
// Constructor function
40
50
function data_field_base($field=0, $data=0) { // Field or data or both, each can be id or object
42
51
if (empty($field) && empty($data)) {
43
52
error('Programmer error: You must specify field and/or data when defining field class. ');
46
54
if (!empty($field)) {
47
55
if (is_object($field)) {
48
56
$this->field = $field; // Programmer knows what they are doing, we hope
270
/// Check if a field from an add form is empty
275
// Check if a field from an add form is empty
271
276
function notemptyfield($value, $name) {
272
277
return !empty($value);
275
/// Just in case a field needs to print something before the whole form
280
// Just in case a field needs to print something before the whole form
276
281
function print_before_form() {
279
/// Just in case a field needs to print something after the whole form
284
// Just in case a field needs to print something after the whole form
280
285
function print_after_form() {
284
/// Returns the sortable field for the content. By default, it's just content
285
/// but for some plugins, it could be content 1 - content4
289
// Returns the sortable field for the content. By default, it's just content
290
// but for some plugins, it could be content 1 - content4
286
291
function get_sort_field() {
287
292
return 'content';
290
/// Returns the SQL needed to refer to the column. Some fields may need to CAST() etc.
295
// Returns the SQL needed to refer to the column. Some fields may need to CAST() etc.
291
296
function get_sort_sql($fieldname) {
292
297
return $fieldname;
295
/// Returns the name/type of the field
300
// Returns the name/type of the field
297
302
return get_string('name'.$this->type, 'data');
300
/// Prints the respective type icon
305
// Prints the respective type icon
301
306
function image() {
632
642
************************************************************************/
633
643
function data_update_instance($data) {
645
$data->timemodified = time();
636
646
$data->id = $data->instance;
638
648
if (empty($data->assessed)) {
639
649
$data->assessed = 0;
642
$data->timemodified = time();
644
if (! $data->instance = update_record('data', $data)) {
651
if (empty($data->notification)) {
652
$data->notification = 0;
654
if (! update_record('data', $data)) {
647
return $data->instance;
658
$data = stripslashes_recursive($data);
659
data_grade_item_update($data);
651
663
/************************************************************************
652
664
* deletes an instance of a data *
653
665
************************************************************************/
654
function data_delete_instance($id) { //takes the dataid
666
function data_delete_instance($id) { // takes the dataid
658
669
if (! $data = get_record('data', 'id', $id)) {
662
/// Delete all the associated information
673
// Delete all the associated information
664
674
// get all the records in this data
665
675
$sql = 'SELECT c.* FROM '.$CFG->prefix.'data_records r LEFT JOIN '.
666
676
$CFG->prefix.'data_content c ON c.recordid = r.id WHERE r.dataid = '.$id;
668
if ($contents = get_records_sql($sql)){
670
foreach($contents as $content){
678
if ($contents = get_records_sql($sql)) {
679
foreach($contents as $content) {
672
680
$field = get_record('data_fields','id',$content->fieldid);
673
if ($g = data_get_field($field, $data)){
681
if ($g = data_get_field($field, $data)) {
674
682
$g->delete_content_files($id, $content->recordid, $content->content);
676
684
//delete the content itself
713
716
/************************************************************************
714
717
* Prints all the records uploaded by this user *
715
718
************************************************************************/
716
719
function data_user_complete($course, $user, $mod, $data) {
718
720
if ($records = get_records_select('data_records', 'dataid = '.$data->id.' AND userid = '.$user->id,
719
721
'timemodified DESC')) {
721
722
data_print_template('singletemplate', $records, $data);
727
* Return grade for given user or all users.
729
* @param int $dataid id of data
730
* @param int $userid optional user id, 0 means all users
731
* @return array array of grades, false if none
733
function data_get_user_grades($data, $userid=0) {
735
$user = $userid ? "AND u.id = $userid" : "";
736
$sql = "SELECT u.id, u.id AS userid, avg(drt.rating) AS rawgrade
737
FROM {$CFG->prefix}user u, {$CFG->prefix}data_records dr,
738
{$CFG->prefix}data_ratings drt
739
WHERE u.id = dr.userid AND dr.id = drt.recordid
740
AND drt.userid != u.id AND dr.dataid = $data->id
743
return get_records_sql($sql);
747
* Update grades by firing grade_updated event
749
* @param object $data null means all databases
750
* @param int $userid specific user only, 0 mean all
752
function data_update_grades($data=null, $userid=0, $nullifnone=true) {
754
if (!function_exists('grade_update')) { //workaround for buggy PHP versions
755
require_once($CFG->libdir.'/gradelib.php');
759
if ($grades = data_get_user_grades($data, $userid)) {
760
data_grade_item_update($data, $grades);
761
} else if ($userid and $nullifnone) {
762
$grade = new object();
763
$grade->userid = $userid;
764
$grade->rawgrade = NULL;
765
data_grade_item_update($data, $grade);
767
data_grade_item_update($data);
770
$sql = "SELECT d.*, cm.idnumber as cmidnumber
771
FROM {$CFG->prefix}data d, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m
772
WHERE m.name='data' AND m.id=cm.module AND cm.instance=d.id";
773
if ($rs = get_recordset_sql($sql)) {
774
while ($data = rs_fetch_next_record($rs)) {
775
if ($data->assessed) {
776
data_update_grades($data, 0, false);
778
data_grade_item_update($data);
787
* Update/create grade item for given data
789
* @param object $data object with extra cmidnumber
790
* @param mixed optional array/object of grade(s); 'reset' means reset grades in gradebook
791
* @return object grade_item
793
function data_grade_item_update($data, $grades=NULL) {
795
if (!function_exists('grade_update')) { //workaround for buggy PHP versions
796
require_once($CFG->libdir.'/gradelib.php');
798
$params = array('itemname'=>$data->name, 'idnumber'=>$data->cmidnumber);
799
if (!$data->assessed or $data->scale == 0) {
800
$params['gradetype'] = GRADE_TYPE_NONE;
801
} else if ($data->scale > 0) {
802
$params['gradetype'] = GRADE_TYPE_VALUE;
803
$params['grademax'] = $data->scale;
804
$params['grademin'] = 0;
805
} else if ($data->scale < 0) {
806
$params['gradetype'] = GRADE_TYPE_SCALE;
807
$params['scaleid'] = -$data->scale;
809
if ($grades === 'reset') {
810
$params['reset'] = true;
814
return grade_update('mod/data', $data->course, 'mod', 'data', $data->id, 0, $grades, $params);
818
* Delete grade item for given data
820
* @param object $data object
821
* @return object grade_item
823
function data_grade_item_delete($data) {
825
require_once($CFG->libdir.'/gradelib.php');
826
return grade_update('mod/data', $data->course, 'mod', 'data', $data->id, 0, NULL, array('deleted'=>1));
726
829
/************************************************************************
727
830
* returns a list of participants of this database *
728
831
************************************************************************/
729
832
function data_get_participants($dataid) {
730
//Returns the users with data in one data
731
//(users with records in data_records, data_comments and data_ratings)
833
// Returns the users with data in one data
834
// (users with records in data_records, data_comments and data_ratings)
734
836
$records = get_records_sql("SELECT DISTINCT u.id, u.id
735
837
FROM {$CFG->prefix}user u,
736
838
{$CFG->prefix}data_records r
737
839
WHERE r.dataid = '$dataid'
738
840
AND u.id = r.userid");
740
841
$comments = get_records_sql("SELECT DISTINCT u.id, u.id
741
842
FROM {$CFG->prefix}user u,
742
843
{$CFG->prefix}data_records r,
850
924
$replacement[] = '';
851
925
$replacement[] = '';
928
$moreurl = $CFG->wwwroot . '/mod/data/view.php?d=' . $data->id . '&rid=' . $record->id;
930
$moreurl .= '&filter=1';
853
932
$patterns[]='##more##';
854
$replacement[] = '<a href="'.$CFG->wwwroot.'/mod/data/view.php?d='.$data->id.'&rid='.$record->id.'"><img src="'.$CFG->pixpath.'/i/search.gif" class="iconsmall" alt="'.get_string('more', 'data').'" title="'.get_string('more', 'data').'" /></a>';
933
$replacement[] = '<a href="' . $moreurl . '"><img src="' . $CFG->pixpath . '/i/search.gif" class="iconsmall" alt="' . get_string('more', 'data') . '" title="' . get_string('more', 'data') . '" /></a>';
856
935
$patterns[]='##moreurl##';
857
$replacement[] = $CFG->wwwroot.'/mod/data/view.php?d='.$data->id.'&rid='.$record->id;
936
$replacement[] = $moreurl;
859
938
$patterns[]='##user##';
860
939
$replacement[] = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$record->userid.
861
940
'&course='.$data->course.'">'.fullname($record).'</a>';
942
$patterns[] = '##timeadded##';
943
$replacement[] = userdate($record->timecreated);
945
$patterns[] = '##timemodified##';
946
$replacement [] = userdate($record->timemodified);
863
948
$patterns[]='##approve##';
864
if (has_capability('mod/data:approve', $context) && ($data->approval) && (!$record->approved)){
865
$replacement[] = '<a href="'.$CFG->wwwroot.'/mod/data/view.php?d='.$data->id.'&approve='.$record->id.'&sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/i/approve.gif" class="iconsmall" alt="'.get_string('approve').'" /></a>';
949
if (has_capability('mod/data:approve', $context) && ($data->approval) && (!$record->approved)) {
950
$replacement[] = '<span class="approve"><a href="'.$CFG->wwwroot.'/mod/data/view.php?d='.$data->id.'&approve='.$record->id.'&sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/i/approve.gif" class="icon" alt="'.get_string('approve').'" /></a></span>';
867
952
$replacement[] = '';
907
function data_print_show_all_form($data, $perpage, $sort, $order, $mode) {
908
echo '<div align="center">';
909
echo '<form id="options" action="view.php" method="get">';
911
echo '<input type="hidden" name="d" value="'.$data->id.'" />';
912
echo '<input type="hidden" name="perpage" value="'.$perpage.'" />';
913
echo '<input type="hidden" name="search" value="" />'; // clear search
914
echo '<input type="hidden" name="sort" value="'.$sort.'" />';
915
echo '<input type="hidden" name="order" value="'.$order.'" />';
916
echo '<input type="hidden" name="mode" value="'.$mode.'" />';
917
echo '<input type="submit" value="'.get_string('showall','data').'" />';
925
989
/************************************************************************
926
990
* function that takes in the current data, number of items per page, *
927
991
* a search string and prints a preference box in view.php *
993
* This preference box prints a searchable advanced search template if *
994
* a) A template is defined *
995
* b) The advanced search checkbox is checked. *
928
997
* input @param object $data *
929
998
* @param int $perpage *
930
999
* @param string $search *
932
1001
************************************************************************/
933
function data_print_preference_form($data, $perpage, $search, $sort='', $order='ASC', $mode='single'){
934
echo '<br /><div class="datapreferences" style="text-align:center">';
1002
function data_print_preference_form($data, $perpage, $search, $sort='', $order='ASC', $search_array = '', $advanced = 0, $mode= '') {
1004
$cm = get_coursemodule_from_instance('data', $data->id);
1005
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
1006
echo '<br /><div class="datapreferences">';
935
1007
echo '<form id="options" action="view.php" method="get">';
936
echo '<fieldset class="invisiblefieldset">';
937
1009
echo '<input type="hidden" name="d" value="'.$data->id.'" />';
1010
if ($mode =='asearch') {
1012
echo '<input type="hidden" name="mode" value="list" />';
938
1014
echo '<label for="pref_perpage">'.get_string('pagesize','data').'</label> ';
939
1015
$pagesizes = array(2=>2,3=>3,4=>4,5=>5,6=>6,7=>7,8=>8,9=>9,10=>10,15=>15,
940
1016
20=>20,30=>30,40=>40,50=>50,100=>100,200=>200,300=>300,400=>400,500=>500,1000=>1000);
941
1017
choose_from_menu($pagesizes, 'perpage', $perpage, '', '', '0', false, false, 0, 'pref_perpage');
942
echo ' <label for="pref_search">'.get_string('search').'</label> <input type="text" size="16" name="search" id= "pref_search" value="'.s($search).'" />';
1018
echo '<div id="reg_search" style="display: ';
1025
echo ';" > <label for="pref_search">'.get_string('search').'</label> <input type="text" size="16" name="search" id= "pref_search" value="'.s($search).'" /></div>';
943
1026
echo ' <label for="pref_sortby">'.get_string('sortby').'</label> ';
944
//foreach field, print the option
945
$fields = get_records('data_fields','dataid',$data->id, 'name');
946
echo '<select name="sort" id="pref_sortby"><option value="0">'.get_string('dateentered','data').'</option>';
947
foreach ($fields as $field) {
948
if ($field->id == $sort) {
949
echo '<option value="'.$field->id.'" selected="selected">'.$field->name.'</option>';
1027
// foreach field, print the option
1028
echo '<select name="sort" id="pref_sortby">';
1029
if ($fields = get_records('data_fields','dataid',$data->id, 'name')) {
1030
echo '<optgroup label="'.get_string('fields', 'data').'">';
1031
foreach ($fields as $field) {
1032
if ($field->id == $sort) {
1033
echo '<option value="'.$field->id.'" selected="selected">'.$field->name.'</option>';
1035
echo '<option value="'.$field->id.'">'.$field->name.'</option>';
1041
$options[DATA_TIMEADDED] = get_string('timeadded', 'data');
1042
$options[DATA_TIMEMODIFIED] = get_string('timemodified', 'data');
1043
$options[DATA_FIRSTNAME] = get_string('authorfirstname', 'data');
1044
$options[DATA_LASTNAME] = get_string('authorlastname', 'data');
1045
if ($data->approval and has_capability('mod/data:approve', $context)) {
1046
$options[DATA_APPROVED] = get_string('approved', 'data');
1048
echo '<optgroup label="'.get_string('other', 'data').'">';
1049
foreach ($options as $key => $name) {
1050
if ($key == $sort) {
1051
echo '<option value="'.$key.'" selected="selected">'.$name.'</option>';
951
echo '<option value="'.$field->id.'">'.$field->name.'</option>';
1053
echo '<option value="'.$key.'">'.$name.'</option>';
954
1057
echo '</select>';
955
1058
echo '<label for="pref_order" class="accesshide">'.get_string('order').'</label>';
956
1059
echo '<select id="pref_order" name="order">';
965
1068
echo '<option value="DESC">'.get_string('descending','data').'</option>';
967
1070
echo '</select>';
969
echo ' ';
970
echo '<input type="hidden" name="mode" value="'.$mode.'" />';
971
echo '<input type="submit" value="'.get_string('savesettings','data').'" />';
1073
$checked = ' checked="checked" ';
1079
<script type="text/javascript">
1082
// javascript for hiding/displaying advanced search form
1084
function showHideAdvSearch(checked) {
1085
var divs = document.getElementsByTagName(\'div\');
1086
for(i=0;i<divs.length;i++) {
1087
if(divs[i].id.match(\'data_adv_form\')) {
1089
divs[i].style.display = \'inline\';
1092
divs[i].style.display = \'none\';
1095
else if (divs[i].id.match(\'reg_search\')) {
1097
divs[i].style.display = \'inline\';
1100
divs[i].style.display = \'none\';
1108
echo ' <input type="hidden" name="advanced" value="0" />';
1109
echo ' <input type="hidden" name="filter" value="1" />';
1110
echo ' <input type="checkbox" id="advancedcheckbox" name="advanced" value="1" '.$checked.' onchange="showHideAdvSearch(this.checked);" /><label for="advancedcheckbox">'.get_string('advancedsearch', 'data').'</label>';
1111
echo ' <input type="submit" value="'.get_string('savesettings','data').'" />';
1113
echo '<div class="dataadvancedsearch" id="data_adv_form" style="display: ';
1120
echo ';margin-left:auto;margin-right:auto;" >';
1121
echo '<table class="boxaligncenter">';
1122
// print ASC or DESC
1123
echo '<tr><td colspan="2"> </td></tr>';
1126
// Determine if we are printing all fields for advanced search, or the template for advanced search
1127
// If a template is not defined, use the deafault template and display all fields.
1128
if(empty($data->asearchtemplate)) {
1129
data_generate_default_template($data, 'asearchtemplate');
1132
static $fields = NULL;
1134
static $dataid = NULL;
1135
if (empty($dataid)) {
1136
$dataid = $data->id;
1137
} else if ($dataid != $data->id) {
1141
if (empty($fields)) {
1142
$fieldrecords = get_records('data_fields','dataid', $data->id);
1143
foreach ($fieldrecords as $fieldrecord) {
1144
$fields[]= data_get_field($fieldrecord, $data);
1146
$isteacher = has_capability('mod/data:managetemplates', $context);
1150
$patterns = array();
1151
$replacement = array();
1153
// Then we generate strings to replace for normal tags
1154
foreach ($fields as $field) {
1155
$fieldname = $field->field->name;
1156
$fieldname = preg_quote($fieldname, '/');
1157
$patterns[] = "/\[\[$fieldname\]\]/i";
1158
$searchfield = data_get_field_from_id($field->field->id, $data);
1159
if (!empty($search_array[$field->field->id]->data)) {
1160
$replacement[] = $searchfield->display_search_field($search_array[$field->field->id]->data);
1162
$replacement[] = $searchfield->display_search_field();
1165
$fn = !empty($search_array[DATA_FIRSTNAME]->data) ? $search_array[DATA_FIRSTNAME]->data : '';
1166
$ln = !empty($search_array[DATA_LASTNAME]->data) ? $search_array[DATA_LASTNAME]->data : '';
1167
$patterns[] = '/##firstname##/';
1168
$replacement[] = '<input type="text" size="16" name="u_fn" value="'.$fn.'" />';
1169
$patterns[] = '/##lastname##/';
1170
$replacement[] = '<input type="text" size="16" name="u_ln" value="'.$ln.'" />';
1172
// actual replacement of the tags
1173
$newtext = preg_replace($patterns, $replacement, $data->asearchtemplate);
1174
$options = new object();
1175
$options->para=false;
1176
$options->noclean=true;
1178
echo format_text($newtext, FORMAT_HTML, $options);
1180
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>';
980
1191
$cm = get_coursemodule_from_instance('data', $data->id);
981
1192
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
983
if ($data->assessed and !empty($USER->id)
984
and (has_capability('mod/data:rate', $context) or has_capability('mod/data:viewrating', $context) or data_isowner($record->id))) {
1193
if ($data->assessed and !empty($USER->id) and (has_capability('mod/data:rate', $context) or has_capability('mod/data:viewrating', $context) or data_isowner($record->id))) {
985
1194
if ($ratingsscale = make_grades_menu($data->scale)) {
986
1195
$ratingsmenuused = false;
988
1196
echo '<div class="ratings" style="text-align:center">';
989
1197
echo '<form id="form" method="post" action="rate.php">';
1198
echo '<input type="hidden" name="dataid" value="'.$data->id.'" />';
991
1199
if (has_capability('mod/data:rate', $context) and !data_isowner($record->id)) {
992
1200
data_print_ratings_mean($record->id, $ratingsscale, has_capability('mod/data:viewrating', $context));
994
1202
data_print_rating_menu($record->id, $USER->id, $ratingsscale);
995
1203
$ratingsmenuused = true;
998
1205
data_print_ratings_mean($record->id, $ratingsscale, true);
1001
1207
if ($data->scale < 0) {
1002
1208
if ($scale = get_record('scale', 'id', abs($data->scale))) {
1003
1209
print_scale_menu_helpbutton($data->course, $scale );
1079
1275
function data_print_rating_menu($recordid, $userid, $scale) {
1080
/// Print the menu of ratings as part of a larger form.
1081
/// If the post has already been - set that value.
1082
/// Scale is an array of ratings
1276
// Print the menu of ratings as part of a larger form.
1277
// If the post has already been - set that value.
1278
// Scale is an array of ratings
1084
1279
static $strrate;
1086
1280
if (!$rating = get_record("data_ratings", "userid", $userid, "recordid", $recordid)) {
1087
$rating->rating = 0;
1281
$rating->rating = -999;
1090
1283
if (empty($strrate)) {
1091
1284
$strrate = get_string("rate", "data");
1094
choose_from_menu($scale, $recordid, $rating->rating, "$strrate...");
1286
choose_from_menu($scale, $recordid, $rating->rating, "$strrate...", '', -999);
1098
1290
function data_get_ratings($recordid, $sort="u.firstname ASC") {
1099
/// Returns a list of ratings for a particular post - sorted.
1291
// Returns a list of ratings for a particular post - sorted.
1101
1293
return get_records_sql("SELECT u.*, r.rating
1102
1294
FROM {$CFG->prefix}data_ratings r,
1458
1614
return $presets;
1462
1618
function data_print_header($course, $cm, $data, $currenttab='') {
1464
1619
global $CFG, $displaynoticegood, $displaynoticebad;
1466
$strdata = get_string('modulenameplural','data');
1468
print_header_simple($data->name, '', "<a href='index.php?id=$course->id'>$strdata</a> -> $data->name",
1620
$navigation = build_navigation('', $cm);
1621
print_header_simple($data->name, '', $navigation,
1469
1622
'', '', true, update_module_button($cm->id, $course->id, get_string('modulename', 'data')),
1470
1623
navmenu($course, $cm));
1472
1624
print_heading(format_string($data->name));
1474
/// Groups needed for Add entry tab
1475
$groupmode = groupmode($course, $cm);
1476
$currentgroup = get_and_set_current_group($course, $groupmode);
1626
// Groups needed for Add entry tab
1627
$currentgroup = groups_get_activity_group($cm);
1628
$groupmode = groups_get_activity_groupmode($cm);
1480
1630
if ($currenttab) {
1481
include_once('tabs.php');
1631
include('tabs.php');
1484
/// Print any notices
1633
// Print any notices
1486
1634
if (!empty($displaynoticegood)) {
1487
1635
notify($displaynoticegood, 'notifysuccess'); // good (usually green)
1488
1636
} else if (!empty($displaynoticebad)) {
1521
// pulled directly out of preset.php Penny 20070426
1523
1667
function is_directory_a_preset($directory) {
1524
1668
$directory = rtrim($directory, '/\\') . '/';
1525
if (file_exists($directory.'singletemplate.html') &&
1526
file_exists($directory.'listtemplate.html') &&
1527
file_exists($directory.'listtemplateheader.html') &&
1528
file_exists($directory.'listtemplatefooter.html') &&
1529
file_exists($directory.'addtemplate.html') &&
1530
file_exists($directory.'rsstemplate.html') &&
1531
file_exists($directory.'rsstitletemplate.html') &&
1532
file_exists($directory.'csstemplate.css') &&
1533
file_exists($directory.'jstemplate.js') &&
1534
file_exists($directory.'preset.xml')) return true;
1669
$status = file_exists($directory.'singletemplate.html') &&
1670
file_exists($directory.'listtemplate.html') &&
1671
file_exists($directory.'listtemplateheader.html') &&
1672
file_exists($directory.'listtemplatefooter.html') &&
1673
file_exists($directory.'addtemplate.html') &&
1674
file_exists($directory.'rsstemplate.html') &&
1675
file_exists($directory.'rsstitletemplate.html') &&
1676
file_exists($directory.'csstemplate.css') &&
1677
file_exists($directory.'jstemplate.js') &&
1678
file_exists($directory.'preset.xml');
1539
1683
function clean_preset($folder) {
1540
if (@unlink($folder.'/singletemplate.html') &&
1541
@unlink($folder.'/listtemplate.html') &&
1542
@unlink($folder.'/listtemplateheader.html') &&
1543
@unlink($folder.'/listtemplatefooter.html') &&
1544
@unlink($folder.'/addtemplate.html') &&
1545
@unlink($folder.'/rsstemplate.html') &&
1546
@unlink($folder.'/rsstitletemplate.html') &&
1547
@unlink($folder.'/csstemplate.css') &&
1548
@unlink($folder.'/jstemplate.js') &&
1549
@unlink($folder.'/preset.xml')) {
1556
function data_presets_export($course, $cm, $data) {
1558
/* Info Collected. Now need to make files in moodledata/temp */
1559
$tempfolder = $CFG->dataroot.'/temp';
1560
$singletemplate = fopen($tempfolder.'/singletemplate.html', 'w');
1561
$listtemplate = fopen($tempfolder.'/listtemplate.html', 'w');
1562
$listtemplateheader = fopen($tempfolder.'/listtemplateheader.html', 'w');
1563
$listtemplatefooter = fopen($tempfolder.'/listtemplatefooter.html', 'w');
1564
$addtemplate = fopen($tempfolder.'/addtemplate.html', 'w');
1565
$rsstemplate = fopen($tempfolder.'/rsstemplate.html', 'w');
1566
$rsstitletemplate = fopen($tempfolder.'/rsstitletemplate.html', 'w');
1567
$csstemplate = fopen($tempfolder.'/csstemplate.css', 'w');
1568
$jstemplate = fopen($tempfolder.'/jstemplate.js', 'w');
1570
fwrite($singletemplate, $data->singletemplate);
1571
fwrite($listtemplate, $data->listtemplate);
1572
fwrite($listtemplateheader, $data->listtemplateheader);
1573
fwrite($listtemplatefooter, $data->listtemplatefooter);
1574
fwrite($addtemplate, $data->addtemplate);
1575
fwrite($rsstemplate, $data->rsstemplate);
1576
fwrite($rsstitletemplate, $data->rsstitletemplate);
1577
fwrite($csstemplate, $data->csstemplate);
1578
fwrite($jstemplate, $data->jstemplate);
1580
fclose($singletemplate);
1581
fclose($listtemplate);
1582
fclose($listtemplateheader);
1583
fclose($listtemplatefooter);
1584
fclose($addtemplate);
1585
fclose($rsstemplate);
1586
fclose($rsstitletemplate);
1587
fclose($csstemplate);
1588
fclose($jstemplate);
1590
/* All the display data is now done. Now assemble preset.xml */
1591
$fields = get_records('data_fields', 'dataid', $data->id);
1592
$presetfile = fopen($tempfolder.'/preset.xml', 'w');
1593
$presetxml = "<preset>\n\n";
1595
/* Database settings first. Name not included? */
1596
$settingssaved = array('intro', 'comments',
1597
'requiredentries', 'requiredentriestoview', 'maxentries',
1598
'rssarticles', 'approval', 'scale', 'assessed',
1599
'defaultsort', 'defaultsortdir', 'editany');
1601
$presetxml .= "<settings>\n";
1602
foreach ($settingssaved as $setting) {
1603
$presetxml .= "<$setting>{$data->$setting}</$setting>\n";
1605
$presetxml .= "</settings>\n\n";
1607
/* Now for the fields. Grabs all settings that are non-empty */
1608
if (!empty($fields)) {
1609
foreach ($fields as $field) {
1610
$presetxml .= "<field>\n";
1611
foreach ($field as $key => $value) {
1612
if ($value != '' && $key != 'id' && $key != 'dataid') {
1613
$presetxml .= "<$key>$value</$key>\n";
1616
$presetxml .= "</field>\n\n";
1620
$presetxml .= "</preset>";
1621
fwrite($presetfile, $presetxml);
1622
fclose($presetfile);
1624
/* Check all is well */
1625
if (!is_directory_a_preset($tempfolder)) {
1626
error("Not all files generated!");
1630
'singletemplate.html',
1631
'listtemplate.html',
1632
'listtemplateheader.html',
1633
'listtemplatefooter.html',
1636
'rsstitletemplate.html',
1641
foreach ($filelist as $key => $file) {
1642
$filelist[$key] = $tempfolder.'/'.$filelist[$key];
1645
@unlink($tempfolder.'/export.zip');
1646
$status = zip_files($filelist, $tempfolder.'/export.zip');
1648
/* made the zip... now return the filename for storage.*/
1649
return $tempfolder.'/export.zip';
1684
$status = @unlink($folder.'/singletemplate.html') &&
1685
@unlink($folder.'/listtemplate.html') &&
1686
@unlink($folder.'/listtemplateheader.html') &&
1687
@unlink($folder.'/listtemplatefooter.html') &&
1688
@unlink($folder.'/addtemplate.html') &&
1689
@unlink($folder.'/rsstemplate.html') &&
1690
@unlink($folder.'/rsstitletemplate.html') &&
1691
@unlink($folder.'/csstemplate.css') &&
1692
@unlink($folder.'/jstemplate.js') &&
1693
@unlink($folder.'/preset.xml');
1696
@unlink($folder.'/asearchtemplate.html');
1654
1701
class PresetImporter {
1719
1789
if (!confirm_sesskey()) {
1720
1790
error("Sesskey Invalid");
1723
1792
$strblank = get_string('blank', 'data');
1724
$strnofields = get_string('nofields', 'data');
1725
1793
$strcontinue = get_string('continue');
1726
1794
$strwarning = get_string('mappingwarning', 'data');
1727
1795
$strfieldmappings = get_string('fieldmappings', 'data');
1728
1796
$strnew = get_string('new');
1729
$strold = get_string('old');
1731
1797
$sesskey = sesskey();
1733
1798
list($settings, $newfields, $currentfields) = $this->get_settings();
1735
echo '<div style="text-align:center"><form action="preset.php" method="post">';
1736
echo '<fieldset class="invisiblefieldset">';
1799
echo '<div class="presetmapping"><form action="preset.php" method="post">';
1737
1801
echo '<input type="hidden" name="action" value="finishimport" />';
1738
1802
echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
1739
1803
echo '<input type="hidden" name="d" value="'.$this->data->id.'" />';
1740
1804
echo '<input type="hidden" name="fullname" value="'.$this->userid.'/'.$this->shortname.'" />';
1742
1805
if (!empty($currentfields) && !empty($newfields)) {
1743
1806
echo "<h3>$strfieldmappings ";
1744
helpbutton('fieldmappings', '', 'data');
1807
helpbutton('fieldmappings', $strfieldmappings, 'data');
1745
1808
echo '</h3><table>';
1747
1809
foreach ($newfields as $nid => $newfield) {
1748
1810
echo "<tr><td><label for=\"id_$newfield->name\">$newfield->name</label></td>";
1749
1811
echo '<td><select name="field_'.$nid.'" id="id_'.$newfield->name.'">';
1751
1812
$selected = false;
1752
1813
foreach ($currentfields as $cid => $currentfield) {
1753
1814
if ($currentfield->type == $newfield->type) {
1770
1830
echo '</table>';
1771
1831
echo "<p>$strwarning</p>";
1773
else if (empty($newfields)) {
1832
} else if (empty($newfields)) {
1774
1833
error("New preset has no defined fields!");
1776
echo '<input type="submit" value="'.$strcontinue.'" /></fieldset></form></div>';
1835
echo '<div class="overwritesettings"><label for="overwritesettings">'.get_string('overwritesettings', 'data').'</label>';
1836
echo '<input id="overwritesettings" name="overwritesettings" type="checkbox" /></label></div>';
1837
echo '<input class="button" type="submit" value="'.$strcontinue.'" /></div></form></div>';
1780
1840
function import() {
1783
1842
list($settings, $newfields, $currentfields) = $this->get_settings();
1784
1843
$preservedfields = array();
1844
$overwritesettings = optional_param('overwritesettings', 0, PARAM_BOOL);
1786
1845
/* Maps fields and makes new ones */
1787
1846
if (!empty($newfields)) {
1788
1847
/* We require an injective mapping, and need to know what to protect */
1789
1848
foreach ($newfields as $nid => $newfield) {
1790
1849
$cid = optional_param("field_$nid", -1, PARAM_INT);
1791
1850
if ($cid == -1) continue;
1793
1851
if (array_key_exists($cid, $preservedfields)) error("Not an injective map");
1794
1852
else $preservedfields[$cid] = true;
1797
1854
foreach ($newfields as $nid => $newfield) {
1798
1855
$cid = optional_param("field_$nid", -1, PARAM_INT);
1800
1856
/* A mapping. Just need to change field params. Data kept. */
1801
1857
if ($cid != -1 and isset($currentfields[$cid])) {
1802
1858
$fieldobject = data_get_field_from_id($currentfields[$cid]->id, $this->data);
1850
data_update_instance(addslashes_object($settings));
1852
if (strstr($this->folder, '/temp/')) clean_preset($this->folder); /* Removes the temporary files */
1904
// handle special settings here
1905
if (!empty($settings->defaultsort)) {
1906
if (is_numeric($settings->defaultsort)) {
1908
$settings->defaultsort = 0;
1910
$settings->defaultsort = (int)get_field('data_fields', 'id', 'dataid', $this->data->id, 'name', addslashes($settings->defaultsort));
1913
$settings->defaultsort = 0;
1916
// do we want to overwrite all current database settings?
1917
if ($overwritesettings) {
1918
// all supported settings
1919
$overwrite = array_keys((array)$settings);
1921
// only templates and sorting
1922
$overwrite = array('singletemplate', 'listtemplate', 'listtemplateheader', 'listtemplatefooter',
1923
'addtemplate', 'rsstemplate', 'rsstitletemplate', 'csstemplate', 'jstemplate',
1924
'asearchtemplate', 'defaultsortdir', 'defaultsort');
1927
// now overwrite current data settings
1928
foreach ($this->data as $prop=>$unused) {
1929
if (in_array($prop, $overwrite)) {
1930
$this->data->$prop = $settings->$prop;
1934
data_update_instance(addslashes_object($this->data));
1935
if (strstr($this->folder, '/temp/')) {
1936
// Removes the temporary files
1937
clean_preset($this->folder);
1857
1943
function data_preset_path($course, $userid, $shortname) {
1858
1944
global $USER, $CFG;
1860
1945
$context = get_context_instance(CONTEXT_COURSE, $course->id);
1862
1946
$userid = (int)$userid;
1864
1947
if ($userid > 0 && ($userid == $USER->id || has_capability('mod/data:viewalluserpresets', $context))) {
1865
1948
return $CFG->dataroot.'/data/preset/'.$userid.'/'.$shortname;
1866
1949
} else if ($userid == 0) {
1868
1951
} else if ($userid < 0) {
1869
1952
return $CFG->dataroot.'/temp/data/'.-$userid.'/'.$shortname;
1872
1954
return 'Does it disturb you that this code will never run?';
1958
* Implementation of the function for printing the form elements that control
1959
* whether the course reset functionality affects the data.
1960
* @param $mform form passed by reference
1962
function data_reset_course_form_definition(&$mform) {
1963
$mform->addElement('header', 'dataheader', get_string('modulenameplural', 'data'));
1964
$mform->addElement('checkbox', 'reset_data', get_string('deleteallentries','data'));
1966
$mform->addElement('checkbox', 'reset_data_notenrolled', get_string('deletenotenrolled', 'data'));
1967
$mform->disabledIf('reset_data_notenrolled', 'reset_data', 'checked');
1969
$mform->addElement('checkbox', 'reset_data_ratings', get_string('deleteallratings'));
1970
$mform->disabledIf('reset_data_ratings', 'reset_data', 'checked');
1972
$mform->addElement('checkbox', 'reset_data_comments', get_string('deleteallcomments'));
1973
$mform->disabledIf('reset_data_comments', 'reset_data', 'checked');
1977
* Course reset form defaults.
1979
function data_reset_course_form_defaults($course) {
1980
return array('reset_data'=>0, 'reset_data_ratings'=>1, 'reset_data_comments'=>1, 'reset_data_notenrolled'=>0);
1984
* Removes all grades from gradebook
1985
* @param int $courseid
1986
* @param string optional type
1988
function data_reset_gradebook($courseid, $type='') {
1990
$sql = "SELECT d.*, cm.idnumber as cmidnumber, d.course as courseid
1991
FROM {$CFG->prefix}data d, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m
1992
WHERE m.name='data' AND m.id=cm.module AND cm.instance=d.id AND d.course=$courseid";
1993
if ($datas = get_records_sql($sql)) {
1994
foreach ($datas as $data) {
1995
data_grade_item_update($data, 'reset');
2001
* Actual implementation of the rest coures functionality, delete all the
2002
* data responses for course $data->courseid.
2003
* @param $data the data submitted from the reset course.
2004
* @return array status array
2006
function data_reset_userdata($data) {
2008
require_once($CFG->libdir.'/filelib.php');
2009
$componentstr = get_string('modulenameplural', 'data');
2011
$allrecordssql = "SELECT r.id
2012
FROM {$CFG->prefix}data_records r
2013
INNER JOIN {$CFG->prefix}data d ON r.dataid = d.id
2014
WHERE d.course = {$data->courseid}";
2015
$alldatassql = "SELECT d.id
2016
FROM {$CFG->prefix}data d
2017
WHERE d.course={$data->courseid}";
2018
// delete entries if requested
2019
if (!empty($data->reset_data)) {
2020
delete_records_select('data_ratings', "recordid IN ($allrecordssql)");
2021
delete_records_select('data_comments', "recordid IN ($allrecordssql)");
2022
delete_records_select('data_content', "recordid IN ($allrecordssql)");
2023
delete_records_select('data_records', "dataid IN ($alldatassql)");
2024
if ($datas = get_records_sql($alldatassql)) {
2025
foreach ($datas as $dataid=>$unused) {
2026
fulldelete("$CFG->dataroot/$data->courseid/moddata/data/$dataid");
2029
if (empty($data->reset_gradebook_grades)) {
2030
// remove all grades from gradebook
2031
data_reset_gradebook($data->courseid);
2033
$status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallentries', 'data'), 'error'=>false);
2036
// remove entries by users not enrolled into course
2037
if (!empty($data->reset_data_notenrolled)) {
2038
$recordssql = "SELECT r.id, r.userid, r.dataid, u.id AS userexists, u.deleted AS userdeleted
2039
FROM {$CFG->prefix}data_records r
2040
INNER JOIN {$CFG->prefix}data d ON r.dataid = d.id
2041
LEFT OUTER JOIN {$CFG->prefix}user u ON r.userid = u.id
2042
WHERE d.course = {$data->courseid} AND r.userid > 0";
2043
$course_context = get_context_instance(CONTEXT_COURSE, $data->courseid);
2044
$notenrolled = array();
2046
if ($rs = get_recordset_sql($recordssql)) {
2047
while ($record = rs_fetch_next_record($rs)) {
2048
if (array_key_exists($record->userid, $notenrolled) or !$record->userexists or $record->userdeleted
2049
or !has_capability('moodle/course:view', $course_context , $record->userid)) {
2050
delete_records('data_ratings', 'recordid', $record->id);
2051
delete_records('data_comments', 'recordid', $record->id);
2052
delete_records('data_content', 'recordid', $record->id);
2053
delete_records('data_records', 'id', $record->id);
2054
// HACK: this is ugly - the recordid should be before the fieldid!
2055
if (!array_key_exists($record->dataid, $fields)) {
2056
if ($fs = get_records('data_fields', 'dataid', $record->dataid)) {
2057
$fields[$record->dataid] = array_keys($fs);
2059
$fields[$record->dataid] = array();
2062
foreach($fields[$record->dataid] as $fieldid) {
2063
fulldelete("$CFG->dataroot/$data->courseid/moddata/data/$record->dataid/$fieldid/$record->id");
2065
$notenrolled[$record->userid] = true;
2069
$status[] = array('component'=>$componentstr, 'item'=>get_string('deletenotenrolled', 'data'), 'error'=>false);
2073
// remove all ratings
2074
if (!empty($data->reset_data_ratings)) {
2075
delete_records_select('data_ratings', "recordid IN ($allrecordssql)");
2076
if (empty($data->reset_gradebook_grades)) {
2077
// remove all grades from gradebook
2078
data_reset_gradebook($data->courseid);
2080
$status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallratings'), 'error'=>false);
2083
// remove all comments
2084
if (!empty($data->reset_data_comments)) {
2085
delete_records_select('data_comments', "recordid IN ($allrecordssql)");
2086
$status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallcomments'), 'error'=>false);
2089
// updating dates - shift may be negative too
2090
if ($data->timeshift) {
2091
shift_course_mod_dates('data', array('timeavailablefrom', 'timeavailableto', 'timeviewfrom', 'timeviewto'), $data->timeshift, $data->courseid);
2092
$status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged'), 'error'=>false);
2098
* Returns all other caps used in module
2100
function data_get_extra_capabilities() {
2101
return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames');