Merge branch 'MDL-25793' of git://github.com/samhemelryk/moodle
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 10 Jan 2011 23:33:56 +0000 (00:33 +0100)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 10 Jan 2011 23:33:56 +0000 (00:33 +0100)
51 files changed:
admin/report/courseoverview/index.php
admin/report/courseoverview/reportsgraph.php
admin/roles/assign.php
blocks/calendar_month/block_calendar_month.php
blocks/community/forms.php
blocks/navigation/block_navigation.php
blocks/navigation/renderer.php
blocks/navigation/yui/navigation/navigation.js
blocks/rss_client/editfeed.php
blog/preferences.php
blog/preferences_form.php
calendar/lib.php
course/category.php
course/format/topics/format.php
course/format/weeks/format.php
course/lib.php
course/modedit.php
course/pending.php
course/report/stats/index.php
course/report/stats/lib.php
course/report/stats/report.php
course/request.php
enrol/locallib.php
enrol/meta/locallib.php
index.php
lang/en/moodle.php
lib/accesslib.php
lib/ajax/section_classes.js
lib/completionlib.php
lib/datalib.php
lib/db/messages.php
lib/javascript-static.js
lib/outputcomponents.php
lib/simpletest/testoutputcomponents.php [new file with mode: 0644]
lib/statslib.php
mod/data/edit.php
mod/forum/forum.js
mod/forum/index.php
mod/forum/lang/en/forum.php
mod/forum/lib.php
mod/forum/subscribe.php
mod/scorm/datamodels/scorm_12.js.php
mod/scorm/locallib.php
mod/wiki/db/migration/lib.php
mod/wiki/db/upgrade.php
mod/wiki/db/upgradelib.php
mod/wiki/locallib.php
question/type/description/questiontype.php
user/filters/globalrole.php
user/profile.php
version.php

index 74c6d24..da91b61 100644 (file)
@@ -27,9 +27,9 @@
 
     $reportoptions = stats_get_report_options($course->id,STATS_MODE_RANKED);
 
-    $earliestday = $DB->get_field_sql('SELECT timeend FROM {stats_daily} ORDER BY timeend');
-    $earliestweek = $DB->get_field_sql('SELECT timeend FROM {stats_weekly} ORDER BY timeend');
-    $earliestmonth = $DB->get_field_sql('SELECT timeend FROM {stats_monthly} ORDER BY timeend');
+    $earliestday = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_daily}');
+    $earliestweek = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_weekly}');
+    $earliestmonth = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_monthly}');
 
     if (empty($earliestday)) $earliestday = time();
     if (empty($earliestweek)) $earliestweek = time();
index 471ffc0..45ea7d8 100644 (file)
@@ -27,7 +27,7 @@
               ORDER BY $param->orderby";
     }
 
-    $courses = $DB->get_records_sql($sql, $param->$params, 0, $numcourses);
+    $courses = $DB->get_records_sql($sql, $param->params, 0, $numcourses);
 
     if (empty($courses)) {
         $PAGE->set_url('/admin/report/courseoverview/index.php');
index 6922350..65aa221 100755 (executable)
@@ -232,7 +232,8 @@ $assignurl = new moodle_url($PAGE->url, array('roleid'=>$roleid));
     $select = new single_select($PAGE->url, 'roleid', $nameswithcounts, $roleid, null);
     $select->label = get_string('assignanotherrole', 'role');
     echo $OUTPUT->render($select);
-    echo '<p><a href="' . $PAGE->url . '">' . get_string('backtoallroles', 'role') . '</a></p>';
+    $backurl = new moodle_url('/admin/roles/assign.php', array('contextid' => $contextid));
+    echo '<p><a href="' . $backurl->out() . '">' . get_string('backtoallroles', 'role') . '</a></p>';
     echo '</div>';
 
 } else if (empty($assignableroles)) {
index 67488c4..9fa7ecb 100644 (file)
@@ -40,8 +40,6 @@ class block_calendar_month extends block_base {
             calendar_set_referring_course(0);
 
         } else {
-            //MDL-14693: fix calendar on resource page
-            $courseshown =  optional_param( 'id', $this->page->course->id, PARAM_INT );
             // Forcibly filter events to include only those from the particular course we are in.
             $filtercourse    = array($courseshown => $this->page->course);
             $groupeventsfrom = array($courseshown => 1);
index 8d16563..c4abd1e 100644 (file)
@@ -131,7 +131,7 @@ class community_hub_search_form extends moodleform {
             }
         }
         if (!empty($additionalhubs)) {
-            $hubs = $hubs + $additionalhubs;
+            $hubs = array_merge($hubs, $additionalhubs);
         }
 
         if (!empty($hubs)) {
@@ -174,7 +174,7 @@ class community_hub_search_form extends moodleform {
                                     array('class' => $hub['trusted'] ? 'hubtrusted' : 'hubnottrusted'));
                 } else {
                     $hubdescription = html_writer::tag('a', $hub['name'],
-                                    array('class' => 'hublink', 'href' => $hub['url']));
+                                    array('class' => 'hublink hubtrusted', 'href' => $hub['url']));
                 }
 
                 if (empty($firsthub)) {
index c7321f7..c51efa8 100644 (file)
@@ -107,7 +107,13 @@ class block_navigation extends block_base {
         if (!empty($CFG->navcourselimit)) {
             $limit = $CFG->navcourselimit;
         }
-        $arguments = array('id'=>$this->instance->id, 'instance'=>$this->instance->id, 'candock'=>$this->instance_can_be_docked(), 'courselimit'=>$limit);
+        $arguments = array(
+            'id'             => $this->instance->id,
+            'instance'       => $this->instance->id,
+            'candock'        => $this->instance_can_be_docked(),
+            'courselimit'    => $limit,
+            'expansionlimit' => $this->config->expansionlimit
+        );
         $this->page->requires->yui_module(array('core_dock', 'moodle-block_navigation-navigation'), 'M.block_navigation.init_add_tree', array($arguments));
     }
 
index 6ef43a4..d59f87c 100644 (file)
@@ -21,13 +21,16 @@ class block_navigation_renderer extends plugin_renderer_base {
         // array of nested li elements
         $lis = array();
         foreach ($items as $item) {
-            if (!$item->display) {
+            if (!$item->display && !$item->contains_active_node()) {
                 continue;
             }
             $content = $item->get_content();
             $title = $item->get_title();
-            $isbranch = ($item->type !== $expansionlimit && ($item->children->count() > 0 || ($item->nodetype == navigation_node::NODETYPE_BRANCH && $item->children->count()==0 && (isloggedin() || $item->type <= navigation_node::TYPE_CATEGORY))));
-            $hasicon = ((!$isbranch || $item->type == navigation_node::TYPE_ACTIVITY)&& $item->icon instanceof renderable);
+
+            $isexpandable = (empty($expansionlimit) || ($item->type > navigation_node::TYPE_ACTIVITY || $item->type < $expansionlimit) || ($item->contains_active_node() && $item->children->count() > 0));
+            $isbranch = $isexpandable && ($item->children->count() > 0 || ($item->has_children() && (isloggedin() || $item->type <= navigation_node::TYPE_CATEGORY)));
+
+            $hasicon = ((!$isbranch || $item->type == navigation_node::TYPE_ACTIVITY )&& $item->icon instanceof renderable);
 
             if ($hasicon) {
                 $icon = $this->output->render($item->icon);
@@ -91,7 +94,10 @@ class block_navigation_renderer extends plugin_renderer_base {
             if (!empty($item->id)) {
                 $divattr['id'] = $item->id;
             }
-            $content = html_writer::tag('p', $content, $divattr) . $this->navigation_node($item->children, array(), $expansionlimit, $options, $depth+1);
+            $content = html_writer::tag('p', $content, $divattr);
+            if ($isexpandable) {
+                $content .= $this->navigation_node($item->children, array(), $expansionlimit, $options, $depth+1);
+            }
             if (!empty($item->preceedwithhr) && $item->preceedwithhr===true) {
                 $content = html_writer::empty_tag('hr') . $content;
             }
index d35d8d7..f2522d8 100644 (file)
@@ -1,5 +1,11 @@
 YUI.add('moodle-block_navigation-navigation', function(Y){
 
+var EXPANSIONLIMIT_EVERYTHING = 0,
+    EXPANSIONLIMIT_COURSE     = 20,
+    EXPANSIONLIMIT_SECTION    = 30,
+    EXPANSIONLIMIT_ACTIVITY   = 40;
+
+
 /**
  * Navigation tree class.
  *
@@ -119,6 +125,12 @@ Y.extend(TREE, Y.Base, TREE.prototype, {
         accordian : {
             validator : Y.Lang.isBool,
             value : false
+        },
+        expansionlimit : {
+            value : 0,
+            setter : function(val) {
+                return parseInt(val);
+            }
         }
     }
 });
@@ -161,7 +173,15 @@ BRANCH.prototype = {
                 this.set(i, config.overrides[i]);
             }
         }
+        // Get the node for this branch
         this.node = Y.one('#', this.get('id'));
+        // Now check whether the branch is not expandable because of the expansionlimit
+        var expansionlimit = this.get('tree').get('expansionlimit');
+        var type = this.get('type');
+        if (expansionlimit != EXPANSIONLIMIT_EVERYTHING &&  type >= expansionlimit && type <= EXPANSIONLIMIT_ACTIVITY) {
+            this.set('expandable', false);
+            this.set('haschildren', false);
+        }
     },
     /**
      * Draws the branch within the tree.
index b031455..38eeb48 100644 (file)
@@ -44,7 +44,7 @@ class feed_edit_form extends moodleform {
         $mform =& $this->_form;
 
         // Then show the fields about where this block appears.
-        $mform->addElement('header', 'header', get_string('feed', 'block_rss_client'));
+        $mform->addElement('header', 'rsseditfeedheader', get_string('feed', 'block_rss_client'));
 
         $mform->addElement('text', 'url', get_string('feedurl', 'block_rss_client'), array('size' => 60));
         $mform->setType('url', PARAM_URL);
index 366beda..472ee30 100755 (executable)
@@ -73,6 +73,7 @@ require_capability('moodle/blog:view', $context);
 /// If data submitted, then process and store.
 
 $mform = new blog_preferences_form('preferences.php');
+$mform->set_data(array('pagesize' => get_user_preferences('blogpagesize')));
 
 if (!$mform->is_cancelled() && $data = $mform->get_data()) {
     $pagesize = $data->pagesize;
index a1fff64..d5c5005 100644 (file)
@@ -39,7 +39,9 @@ class blog_preferences_form extends moodleform {
         $strpagesize = get_string('pagesize', 'blog');
 
         $mform->addElement('text', 'pagesize', $strpagesize);
-        $mform->setDefault('pagesize', get_user_preferences('pagesize'));
+        $mform->setType('pagesize', PARAM_INT);
+        $mform->addRule('pagesize', null, 'numeric', null, 'client');
+        $mform->setDefault('pagesize', 10);
 
         $this->add_action_buttons();
     }
index ff8fe33..3b6693f 100644 (file)
@@ -273,7 +273,7 @@ function calendar_get_mini($courses, $groups, $users, $cal_month = false, $cal_y
                 $dayhref->set_anchor('event_'.$event->id);
 
                 $popupcontent .= html_writer::start_tag('div');
-                $popupcontent .= $OUTPUT->pix_icon($popupicon, $popupalt);
+                $popupcontent .= $OUTPUT->pix_icon($popupicon, $popupalt, $component);
                 $popupcontent .= html_writer::link($dayhref, format_string($event->name, true));
                 $popupcontent .= html_writer::end_tag('div');
             }
index 7ca8fc4..12558aa 100644 (file)
         echo $OUTPUT->single_button(new moodle_url('edit.php', $options), get_string('addnewcourse'), 'get');
     }
 
-    if (!empty($CFG->enablecourserequests) && $category->id == $CFG->enablecourserequests) {
+    if (!empty($CFG->enablecourserequests) && $category->id == $CFG->defaultrequestcategory) {
         print_course_request_buttons(get_context_instance(CONTEXT_SYSTEM));
     }
     echo '</div>';
index 12611df..905892d 100644 (file)
@@ -69,7 +69,7 @@ if ($editing) {
 
 // Print the Your progress icon if the track completion is enabled
 $completioninfo = new completion_info($course);
-$completioninfo->print_help_icon();
+echo $completioninfo->display_help_icon();
 
 echo $OUTPUT->heading(get_string('topicoutline'), 2, 'headingblock header outline');
 
index 9b9886a..c43def7 100644 (file)
@@ -61,11 +61,10 @@ defined('MOODLE_INTERNAL') || die();
 
     //Print the Your progress icon if the track completion is enabled
     $completioninfo = new completion_info($course);
-    $completioninfo->print_help_icon();
+    echo $completioninfo->display_help_icon();
 
     echo $OUTPUT->heading(get_string('weeklyoutline'), 2, 'headingblock header outline');
 
-    echo "<span id='maincontent'></span>";
     // Note, an ordered list would confuse - "1" could be the clipboard or summary.
     echo "<ul class='weeks'>\n";
 
index a28be6d..10d7178 100644 (file)
@@ -2110,7 +2110,7 @@ function print_category_info($category, $depth=0, $showcourses = false) {
         echo '<div class="categorylist">';
         $html = '';
         $cat = html_writer::link(new moodle_url('/course/category.php', array('id'=>$category->id)), format_string($category->name), $catlinkcss);
-        $cat .= html_writer::tag('span', '('.count($courses).')', array('title'=>get_string('numberofcourses'), 'class'=>'numberofcourse'));
+        $cat .= html_writer::tag('span', ' ('.count($courses).')', array('title'=>get_string('numberofcourses'), 'class'=>'numberofcourse'));
 
         if ($depth > 0) {
             for ($i=0; $i< $depth; $i++) {
@@ -4074,8 +4074,7 @@ class course_request {
      */
     protected function notify($touser, $fromuser, $name='courserequested', $subject, $message) {
         $eventdata = new stdClass();
-        $eventdata->modulename        = 'moodle';
-        $eventdata->component         = 'course';
+        $eventdata->component         = 'moodle';
         $eventdata->name              = $name;
         $eventdata->userfrom          = $fromuser;
         $eventdata->userto            = $touser;
@@ -4084,6 +4083,7 @@ class course_request {
         $eventdata->fullmessageformat = FORMAT_PLAIN;
         $eventdata->fullmessagehtml   = '';
         $eventdata->smallmessage      = '';
+        $eventdata->notification      = 1;
         message_send($eventdata);
     }
 }
index d6338e6..4b5c615 100644 (file)
@@ -42,12 +42,14 @@ if (!empty($return)) {
 }
 
 if (!empty($add)) {
-    $url->param('add', $add);
-    $PAGE->set_url($url);
-
     $section = required_param('section', PARAM_INT);
     $course  = required_param('course', PARAM_INT);
 
+    $url->param('add', $add);
+    $url->param('section', $section);
+    $url->param('course', $course);
+    $PAGE->set_url($url);
+
     $course = $DB->get_record('course', array('id'=>$course), '*', MUST_EXIST);
     $module = $DB->get_record('modules', array('name'=>$add), '*', MUST_EXIST);
 
index dcffa99..3c167ca 100644 (file)
@@ -100,8 +100,8 @@ if (empty($pending)) {
 /// Build a table of all the requests.
     $table = new html_table();
     $table->attributes['class'] = 'pendingcourserequests generaltable';
-    $table->align = array('center', 'center', 'center', 'center', 'center', 'center', 'center');
-    $table->head = array('&nbsp;', get_string('shortname'), get_string('fullname'),
+    $table->align = array('center', 'center', 'center', 'center', 'center', 'center');
+    $table->head = array(get_string('shortname'), get_string('fullname'),
             get_string('requestedby'), get_string('summary'), get_string('requestreason'), get_string('action'));
 
     foreach ($pending as $course) {
index adca011..6af3bc7 100644 (file)
 
     require_login($course);
     $context = get_context_instance(CONTEXT_COURSE, $course->id);
-
     require_capability('coursereport/stats:view', $context);
 
+    $PAGE->set_url(new moodle_url('/course/report/stats/index.php', array('course' => $course->id,
+                                                                          'report' => $report,
+                                                                          'time'   => $time,
+                                                                          'mode'   => $mode,
+                                                                          'userid' => $userid)));
+
     add_to_log($course->id, "course", "report stats", "report/stats/index.php?course=$course->id", $course->id);
     stats_check_uptodate($course->id);
 
 
         $PAGE->set_title("$course->shortname: $strstats");
         $PAGE->set_heading($course->fullname);
-        //$PAGE->set_headingmenu();
-        $PAGE->navbar->add($strreports, new moodle_url('/course/report.php', array('id'=>$course->id)));
-        $PAGE->navbar->add($strstats);
-        $PAGE->headingmenu(report_stats_mode_menu($course, $mode, $time, "$CFG->wwwroot/course/report/stats/index.php"));
+        $PAGE->set_pagelayout('report');
+        $PAGE->set_headingmenu(report_stats_mode_menu($course, $mode, $time, "$CFG->wwwroot/course/report/stats/index.php"));
         echo $OUTPUT->header();
     }
 
index 095d13c..ed31e78 100644 (file)
@@ -46,7 +46,7 @@ function report_stats_mode_menu($course, $mode, $time, $url) {
     $popupurl = $url."?course=$course->id&time=$time";
     $select = new single_select(new moodle_url($popupurl), 'mode', $options, $mode, null);
     $select->formid = 'switchmode';
-    echo $OUTPUT->render($select);
+    return $OUTPUT->render($select);
 }
 
 
@@ -54,13 +54,13 @@ function report_stats_timeoptions($mode) {
     global $CFG, $DB;
 
     if ($mode == STATS_MODE_DETAILED) {
-        $earliestday = $DB->get_field_sql('SELECT timeend FROM {stats_user_daily} ORDER BY timeend');
-        $earliestweek = $DB->get_field_sql('SELECT timeend FROM {stats_user_weekly} ORDER BY timeend');
-        $earliestmonth = $DB->get_field_sql('SELECT timeend FROM {stats_user_monthly} ORDER BY timeend');
+        $earliestday = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_user_daily}');
+        $earliestweek = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_user_weekly}');
+        $earliestmonth = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_user_monthly}');
     } else {
-        $earliestday = $DB->get_field_sql('SELECT timeend FROM {stats_daily} ORDER BY timeend');
-        $earliestweek = $DB->get_field_sql('SELECT timeend FROM {stats_weekly} ORDER BY timeend');
-        $earliestmonth = $DB->get_field_sql('SELECT timeend FROM {stats_monthly} ORDER BY timeend');
+        $earliestday = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_daily}');
+        $earliestweek = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_weekly}');
+        $earliestmonth = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_monthly}');
     }
 
 
@@ -86,8 +86,8 @@ function stats_report_extend_navigation($navigation, $course, $context) {
     global $CFG, $OUTPUT;
     if (has_capability('coursereport/stats:view', $context)) {
         if (!empty($CFG->enablestats)) {
-            $url = new moodle_url('/course/report/stats/index.php', array('id'=>$course->id));
+            $url = new moodle_url('/course/report/stats/index.php', array('course'=>$course->id));
             $navigation->add(get_string('stats'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('i/report', ''));
         }
     }
-}
\ No newline at end of file
+}
index 65962dd..e13f064 100644 (file)
@@ -98,7 +98,7 @@
                 .' ORDER BY timeend DESC';
         }
 
-        $stats = $DB->get_records_sql($sql, $params);
+        $stats = $DB->get_records_sql($sql);
 
         if (empty($stats)) {
             echo $OUTPUT->notification(get_string('statsnodata'));
index 3919715..3e0e097 100644 (file)
@@ -32,6 +32,7 @@ $PAGE->set_url('/course/request.php');
 /// Where we came from. Used in a number of redirects.
 $returnurl = $CFG->wwwroot . '/course/index.php';
 
+
 /// Check permissions.
 require_login();
 if (isguestuser()) {
@@ -40,7 +41,9 @@ if (isguestuser()) {
 if (empty($CFG->enablecourserequests)) {
     print_error('courserequestdisabled', '', $returnurl);
 }
-require_capability('moodle/course:request', get_context_instance(CONTEXT_SYSTEM));
+$context = get_context_instance(CONTEXT_SYSTEM);
+$PAGE->set_context($context);
+require_capability('moodle/course:request', $context);
 
 /// Set up the form.
 $data = course_request::prepare();
@@ -67,4 +70,4 @@ echo $OUTPUT->header();
 echo $OUTPUT->heading($strtitle);
 // Show the request form.
 $requestform->display();
-echo $OUTPUT->footer();
\ No newline at end of file
+echo $OUTPUT->footer();
index 83aebf4..dcf4bb7 100644 (file)
@@ -331,8 +331,7 @@ class course_enrolment_manager {
         }
         $wherecondition = implode(' AND ', $tests);
 
-
-        $fields      = 'SELECT u.id, u.firstname, u.lastname, u.username, u.email, u.lastaccess, u.picture, u.imagealt, '.user_picture::fields('u');;
+        $fields      = 'SELECT '.user_picture::fields('u', array('username','lastaccess'));
         $countfields = 'SELECT COUNT(u.id)';
         $sql   = " FROM {user} u
                   WHERE $wherecondition
index f626504..066390f 100644 (file)
@@ -180,7 +180,7 @@ class enrol_meta_handler {
         $plugin = enrol_get_plugin('meta');
         foreach ($enrols as $enrol) {
             //unenrol all users
-            $ues = $DB->get_records_sql('user_enrolments', array('courseid'=>$enrol->courseid, 'enrolid'=>$enrol->id));
+            $ues = $DB->get_recordset('user_enrolments', array('enrolid'=>$enrol->id));
             foreach ($ues as $ue) {
                 $plugin->unenrol_user($enrol, $ue->userid);
             }
index f871c9f..8aa5b3a 100644 (file)
--- a/index.php
+++ b/index.php
                             $subtext = get_string('subscribe', 'forum');
                         }
                         echo $OUTPUT->heading($newsforum->name, 2, 'headingblock header');
-                        echo '<div class="subscribelink"><a href="mod/forum/subscribe.php?id='.$newsforum->id.'">'.$subtext.'</a></div>';
+                        $suburl = new moodle_url('/mod/forum/subscribe.php', array('id' => $newsforum->id, 'sesskey' => sesskey()));
+                        echo html_writer::tag('div', html_writer::link($suburl, $subtext), array('class' => 'subscribelink'));
                     } else {
                         echo $OUTPUT->heading($newsforum->name, 2, 'headingblock header');
                     }
index af6261b..593bf21 100644 (file)
@@ -986,6 +986,9 @@ $string['messagebody'] = 'Message body';
 $string['messagedselectedusers'] = 'Selected users have been messaged and the recipient list has been reset.';
 $string['messagedselectedusersfailed'] = 'Something went wrong while messaging selected users.  Some may have received the email.';
 $string['messageprovider:backup'] = 'Backup notifications';
+$string['messageprovider:courserequestapproved'] = 'Course creation request approval notification';
+$string['messageprovider:courserequested'] = 'Course creation request notification';
+$string['messageprovider:courserequestrejected'] = 'Course creation request rejection notification';
 $string['messageprovider:errors'] = 'Important errors with the site';
 $string['messageprovider:errors_help'] = 'These are important errors that an administrator should know about.';
 $string['messageprovider:notices'] = 'Notices about minor problems';
index 93db002..87a8287 100755 (executable)
@@ -4459,7 +4459,7 @@ function get_user_roles($context, $userid = 0, $checkparentcontexts = true, $ord
  *
  * @param int $sroleid source roleid
  * @param int $troleid target roleid
- * @return int id or false
+ * @return void
  */
 function allow_override($sroleid, $troleid) {
     global $DB;
@@ -4475,7 +4475,7 @@ function allow_override($sroleid, $troleid) {
  *
  * @param int $sroleid source roleid
  * @param int $troleid target roleid
- * @return int id or false
+ * @return void
  */
 function allow_assign($fromroleid, $targetroleid) {
     global $DB;
@@ -4491,7 +4491,7 @@ function allow_assign($fromroleid, $targetroleid) {
  *
  * @param int $sroleid source roleid
  * @param int $troleid target roleid
- * @return int id or false
+ * @return void
  */
 function allow_switch($fromroleid, $targetroleid) {
     global $DB;
index 9acf607..bc52f95 100755 (executable)
@@ -736,7 +736,7 @@ resource_class.prototype.indent_left = function() {
         }
         return false;
     }
-    var oldindent = indentdiv.classList.toString().match(/mod-indent-(\d{1,})/);
+    var oldindent = indentdiv.className.match(/mod-indent-(\d{1,})/);
     if (oldindent && oldindent[1] > 0) {
         oldindent = oldindent[1];
     } else {
@@ -767,7 +767,7 @@ resource_class.prototype.indent_right = function() {
         }
         return false;
     }
-    var oldindent = indentdiv.classList.toString().match(/mod-indent-(\d{1,})/);
+    var oldindent = indentdiv.className.match(/mod-indent-(\d{1,})/);
     if (oldindent && oldindent[1] >= 0) {
         oldindent = oldindent[1];
         var newindent = parseFloat(oldindent) + 1;
index f0482db..b020d32 100644 (file)
@@ -207,17 +207,29 @@ class completion_info {
     }
 
     /**
-     * Print the Your progress help icon if the completion tracking is enabled.
-     * @global object
+     * Displays the 'Your progress' help icon, if completion tracking is enabled.
+     * Just prints the result of display_help_icon().
+     * @deprecated Use display_help_icon instead.
      * @return void
      */
     public function print_help_icon() {
+        print $this->display_help_icon();
+    }
+
+    /**
+     * Returns the 'Your progress' help icon, if completion tracking is enabled.
+     * @global object
+     * @return string HTML code for help icon, or blank if not needed
+     */
+    public function display_help_icon() {
         global $PAGE, $OUTPUT;
+        $result = '';
         if ($this->is_enabled() && !$PAGE->user_is_editing() && isloggedin() && !isguestuser()) {
-            echo '<span id = "completionprogressid" class="completionprogress">'.get_string('yourprogress','completion').' ';
-            echo $OUTPUT->help_icon('completionicons', 'completion');
-            echo '</span>';
+            $result .= '<span id = "completionprogressid" class="completionprogress">'.get_string('yourprogress','completion').' ';
+            $result .= $OUTPUT->help_icon('completionicons', 'completion');
+            $result .= '</span>';
         }
+        return $result;
     }
 
     /**
index ad75220..cb3d926 100644 (file)
@@ -1039,11 +1039,20 @@ function fix_course_sortorder() {
             HAVING cc.coursecount <> COUNT(c.id)";
 
     if ($updatecounts = $DB->get_records_sql($sql)) {
+        // categories with more courses than MAX_COURSES_IN_CATEGORY
+        $categories = array();
         foreach ($updatecounts as $cat) {
             $cat->coursecount = $cat->newcount;
+            if ($cat->coursecount >= MAX_COURSES_IN_CATEGORY) {
+                $categories[] = $cat->id;
+            }
             unset($cat->newcount);
             $DB->update_record_raw('course_categories', $cat, true);
         }
+        if (!empty($categories)) {
+            $str = implode(', ', $categories);
+            debugging("The number of courses (category id: $str) has reached MAX_COURSES_IN_CATEGORY (" . MAX_COURSES_IN_CATEGORY . "), it will cause a sorting performance issue, please increase the value of MAX_COURSES_IN_CATEGORY in lib/datalib.php file. See tracker issue: MDL-25669", DEBUG_DEVELOPER);
+        }
     }
 
     // now make sure that sortorders in course table are withing the category sortorder ranges
index 5873874..11e2d80 100644 (file)
@@ -43,6 +43,21 @@ $messageproviders = array (
 
     'backup' => array (
         'capability'  => 'moodle/site:config'
+    ),
+
+    //course creation request notification
+    'courserequested' => array (
+        'capability'  => 'moodle/site:approvecourse'
+    ),
+
+    //course request approval notification
+    'courserequestapproved' => array (
+         'capability'  => 'moodle/course:request'
+    ),
+
+    //course request rejection notification
+    'courserequestrejected' => array (
+        'capability'  => 'moodle/course:request'
     )
 
 );
index d79230d..a60ddaf 100644 (file)
@@ -262,15 +262,17 @@ M.util.show_confirm_dialog = function(e, args) {
                 return;
             }
 
-            if (target.get('tagName').toLowerCase() == 'a') {
+            var targetancestor = null,
+                targetform = null;
+
+            if (target.test('a')) {
                 window.location = target.get('href');
-            } else if (target.get('tagName').toLowerCase() == 'input') {
-                var parentelement = target.get('parentNode');
-                while (parentelement.get('tagName').toLowerCase() != 'form' && parentelement.get('tagName').toLowerCase() != 'body') {
-                    parentelement = parentelement.get('parentNode');
-                }
-                if (parentelement.get('tagName').toLowerCase() == 'form') {
-                    parentelement.submit();
+            } else if ((targetancestor = target.ancestor('a')) !== null) {
+                window.location = targetancestor.get('href');
+            } else if (target.test('input')) {
+                targetform = target.ancestor('form');
+                if (targetform && targetform.submit) {
+                    targetform.submit();
                 }
             } else if (M.cfg.developerdebug) {
                 alert("Element of type " + target.get('tagName') + " is not supported by the M.util.show_confirm_dialog function. Use A or INPUT");
@@ -365,7 +367,12 @@ M.util.init_select_autosubmit = function(Y, formid, selectid, nothing) {
                 // event.... usability
                 Y.on('key', processchange, select, 'press:13', form, select.get('selectedIndex'));
                 select.on('blur', processchange, form, select.get('selectedIndex'));
-                select.on('click', processchange, form, select.get('selectedIndex'));
+                //little hack for chrome that need onChange event instead of onClick - see MDL-23224
+                if (Y.UA.webkit) {
+                    select.on('change', processchange, form, select.get('selectedIndex'));
+                } else {
+                    select.on('click', processchange, form, select.get('selectedIndex'));
+                }
             }
         }
     });
index 4cbd05c..3ffed7c 100644 (file)
@@ -177,9 +177,10 @@ class user_picture implements renderable {
      * @param string $tableprefix name of database table prefix in query
      * @param array $extrafields extra fields to be included in result (do not include TEXT columns because it would break SELECT DISTINCT in MSSQL and ORACLE)
      * @param string $idalias alias of id field
+     * @param string $fieldprefix prefix to add to all columns in their aliases, does not apply to 'id'
      * @return string
      */
-    public static function fields($tableprefix = '', array $extrafields = NULL, $idalias = 'id') {
+    public static function fields($tableprefix = '', array $extrafields = NULL, $idalias = 'id', $fieldprefix = '') {
         if (!$tableprefix and !$extrafields and !$idalias) {
             return implode(',', self::$fields);
         }
@@ -191,7 +192,11 @@ class user_picture implements renderable {
             if ($field === 'id' and $idalias and $idalias !== 'id') {
                 $fields[$field] = "$tableprefix$field AS $idalias";
             } else {
-                $fields[$field] = $tableprefix.$field;
+                if ($fieldprefix and $field !== 'id') {
+                    $fields[$field] = "$tableprefix$field AS $fieldprefix$field";
+                } else {
+                    $fields[$field] = "$tableprefix$field";
+                }
             }
         }
         // add extra fields if not already there
@@ -200,13 +205,60 @@ class user_picture implements renderable {
                 if ($e === 'id' or isset($fields[$e])) {
                     continue;
                 }
-                $fields[$e] = $tableprefix.$e;
+                if ($fieldprefix) {
+                    $fields[$e] = "$tableprefix$e AS $fieldprefix$e";
+                } else {
+                    $fields[$e] = "$tableprefix$e";
+                }
             }
         }
         return implode(',', $fields);
     }
-}
 
+    /**
+     * Extract the aliased user fields from a given record
+     *
+     * Given a record that was previously obtained using {@link self::fields()} with aliases,
+     * this method extracts user related unaliased fields.
+     *
+     * @param stdClass $record containing user picture fields
+     * @param array $extrafields extra fields included in the $record
+     * @param string $idalias alias of the id field
+     * @param string $fieldprefix prefix added to all columns in their aliases, does not apply to 'id'
+     * @return stdClass object with unaliased user fields
+     */
+    public static function unalias(stdClass $record, array $extrafields=null, $idalias='id', $fieldprefix='') {
+
+        if (empty($idalias)) {
+            $idalias = 'id';
+        }
+
+        $return = new stdClass();
+
+        foreach (self::$fields as $field) {
+            if ($field === 'id') {
+                if (isset($record->{$idalias})) {
+                    $return->id = $record->{$idalias};
+                }
+            } else {
+                if (isset($record->{$fieldprefix.$field})) {
+                    $return->{$field} = $record->{$fieldprefix.$field};
+                }
+            }
+        }
+        // add extra fields if not already there
+        if ($extrafields) {
+            foreach ($extrafields as $e) {
+                if ($e === 'id' or isset($return->{$e})) {
+                    continue;
+                }
+                $return->{$e} = $record->{$fieldprefix.$e};
+            }
+        }
+
+        return $return;
+    }
+}
 
 /**
  * Data structure representing a help icon.
diff --git a/lib/simpletest/testoutputcomponents.php b/lib/simpletest/testoutputcomponents.php
new file mode 100644 (file)
index 0000000..0ca721c
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Unit tests for lib/outputcomponents.php.
+ *
+ * @package   core
+ * @copyright 2011 David Mudrak <david@moodle.com>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+require_once($CFG->libdir . '/outputcomponents.php');
+
+/**
+ * Unit tests for the user_picture class
+ */
+class user_picture_test extends UnitTestCase {
+
+    public static $includecoverage = array('lib/outputcomponents.php');
+
+    public function test_user_picture_fields_aliasing() {
+        $fields = user_picture::fields();
+        $fields = array_map('trim', explode(',', $fields));
+        $this->assertTrue(in_array('id', $fields));
+
+        $aliased = array();
+        foreach ($fields as $field) {
+            if ($field === 'id') {
+                $aliased['id'] = 'aliasedid';
+            } else {
+                $aliased[$field] = 'prefix'.$field;
+            }
+        }
+
+        $returned = user_picture::fields('', array('custom1', 'id'), 'aliasedid', 'prefix');
+        $returned = array_map('trim', explode(',', $returned));
+        $this->assertEqual(count($returned), count($fields) + 1); // only one extra field added
+
+        foreach ($fields as $field) {
+            if ($field === 'id') {
+                $expected = "id AS aliasedid";
+            } else {
+                $expected = "$field AS prefix$field";
+            }
+            $this->assertTrue(in_array($expected, $returned), "Expected pattern '$expected' not returned");
+        }
+        $this->assertTrue(in_array("custom1 AS prefixcustom1", $returned), "Expected pattern 'custom1 AS prefixcustom1' not returned");
+    }
+
+    public function test_user_picture_fields_unaliasing() {
+        $fields = user_picture::fields();
+        $fields = array_map('trim', explode(',', $fields));
+
+        $fakerecord = new stdClass();
+        $fakerecord->aliasedid = 42;
+        foreach ($fields as $field) {
+            if ($field !== 'id') {
+                $fakerecord->{'prefix'.$field} = "Value of $field";
+            }
+        }
+        $fakerecord->prefixcustom1 = 'Value of custom1';
+
+        $returned = user_picture::unalias($fakerecord, array('custom1'), 'aliasedid', 'prefix');
+
+        $this->assertEqual($returned->id, 42);
+        foreach ($fields as $field) {
+            if ($field !== 'id') {
+                $this->assertEqual($returned->{$field}, "Value of $field");
+            }
+        }
+        $this->assertEqual($returned->custom1, 'Value of custom1');
+    }
+}
index b52a7c4..8a49917 100644 (file)
@@ -854,13 +854,13 @@ function stats_get_start_from($str) {
     global $CFG, $DB;
 
     // are there any data in stats table? Should not be...
-    if ($timeend = $DB->get_field_sql('SELECT timeend FROM {stats_'.$str.'} ORDER BY timeend DESC')) {
+    if ($timeend = $DB->get_field_sql('SELECT MAX(timeend) FROM {stats_'.$str.'}')) {
         return $timeend;
     }
     // decide what to do based on our config setting (either all or none or a timestamp)
     switch ($CFG->statsfirstrun) {
         case 'all':
-            if ($firstlog = $DB->get_field_sql('SELECT time FROM {log} ORDER BY time ASC')) {
+            if ($firstlog = $DB->get_field_sql('SELECT MIN(time) FROM {log}')) {
                 return $firstlog;
             }
         default:
@@ -1333,8 +1333,8 @@ function stats_get_report_options($courseid,$mode) {
     case STATS_MODE_GENERAL:
         $reportoptions[STATS_REPORT_ACTIVITY] = get_string('statsreport'.STATS_REPORT_ACTIVITY);
         if ($courseid != SITEID && $context = get_context_instance(CONTEXT_COURSE, $courseid)) {
-            $sql = 'SELECT r.id,r.name FROM {role} r JOIN {stats_daily} s ON s.roleid = r.id WHERE s.courseid = '.$courseid;
-            if ($roles = $DB->get_records_sql($sql)) {
+            $sql = 'SELECT r.id, r.name FROM {role} r JOIN {stats_daily} s ON s.roleid = r.id WHERE s.courseid = :courseid GROUP BY s.roleid';
+            if ($roles = $DB->get_records_sql($sql, array('courseid' => $courseid))) {
                 foreach ($roles as $role) {
                     $reportoptions[STATS_REPORT_ACTIVITYBYROLE.$role->id] = get_string('statsreport'.STATS_REPORT_ACTIVITYBYROLE). ' '.$role->name;
                 }
index 34aef3f..c1acdb5 100755 (executable)
@@ -198,6 +198,7 @@ if ($datarecord = data_submitted() and confirm_sesskey()) {
     /// Of course, you can't be stopped if you are an editting teacher! =)
 
         if (data_atmaxentries($data) and !has_capability('mod/data:manageentries',$context)){
+            echo $OUTPUT->header();
             echo $OUTPUT->notification(get_string('atmaxentry','data'));
             echo $OUTPUT->footer();
             exit;
index 3d47538..749b043 100644 (file)
@@ -5,7 +5,7 @@ function forum_produce_subscribe_link(forumid, backtoindex, ltext, ltitle) {
     var elementid = "subscriptionlink";
     var subs_link = document.getElementById(elementid);
     if(subs_link){
-        subs_link.innerHTML = "<a title="+ltitle+" href='"+M.cfg.wwwroot+"/mod/forum/subscribe.php?id="+forumid+backtoindex+"'>"+ltext+"<\/a>";
+        subs_link.innerHTML = "<a title='"+ltitle+"' href='"+M.cfg.wwwroot+"/mod/forum/subscribe.php?id="+forumid+backtoindex+"&amp;sesskey="+M.cfg.sesskey+"'>"+ltext+"<\/a>";
     }
 }
 
@@ -13,7 +13,7 @@ function forum_produce_tracking_link(forumid, ltext, ltitle) {
     var elementid = "trackinglink";
     var subs_link = document.getElementById(elementid);
     if(subs_link){
-        subs_link.innerHTML = "<a title="+ltitle+" href='"+M.cfg.wwwroot+"/mod/forum/settracking.php?id="+forumid+"'>"+ltext+"<\/a>";
+        subs_link.innerHTML = "<a title='"+ltitle+"' href='"+M.cfg.wwwroot+"/mod/forum/settracking.php?id="+forumid+"'>"+ltext+"<\/a>";
     }
 }
 
@@ -56,4 +56,4 @@ function unlockoption(form,item) {
     if (form.elements['h'+item]) {
         form.elements['h'+item].value=0;
     }
-}
\ No newline at end of file
+}
index 1b95fb7..ce365c7 100644 (file)
@@ -31,6 +31,7 @@ $subscribe = optional_param('subscribe', null, PARAM_INT);  // Subscribe/Unsubsc
 
 $url = new moodle_url('/mod/forum/index.php', array('id'=>$id));
 if ($subscribe !== null) {
+    require_sesskey();
     $url->param('subscribe', $subscribe);
 }
 $PAGE->set_url($url);
@@ -410,11 +411,14 @@ echo $OUTPUT->header();
 
 if (!isguestuser()) {
     echo $OUTPUT->box_start('subscription');
-    echo '<span class="helplink">';
-    echo '<a href="index.php?id='.$course->id.'&amp;subscribe=1">'.get_string('allsubscribe', 'forum').'</a>';
-    echo '</span><br /><span class="helplink">';
-    echo '<a href="index.php?id='.$course->id.'&amp;subscribe=0">'.get_string('allunsubscribe', 'forum').'</a>';
-    echo '</span>';
+    echo html_writer::tag('div',
+        html_writer::link(new moodle_url('/mod/forum/index.php', array('id'=>$course->id, 'subscribe'=>1, 'sesskey'=>sesskey())),
+            get_string('allsubscribe', 'forum')),
+        array('class'=>'helplink'));
+    echo html_writer::tag('div',
+        html_writer::link(new moodle_url('/mod/forum/index.php', array('id'=>$course->id, 'subscribe'=>0, 'sesskey'=>sesskey())),
+            get_string('allunsubscribe', 'forum')),
+        array('class'=>'helplink'));
     echo $OUTPUT->box_end();
     echo $OUTPUT->box('&nbsp;', 'clearer');
 }
index 684390a..6985b4e 100644 (file)
@@ -96,6 +96,8 @@ $string['configreplytouser'] = 'When a forum post is mailed out, should it conta
 $string['configshortpost'] = 'Any post under this length (in characters not including HTML) is considered short (see below).';
 $string['configtrackreadposts'] = 'Set to \'yes\' if you want to track read/unread for each user.';
 $string['configusermarksread'] = 'If \'yes\', the user must manually mark a post as read. If \'no\', when the post is viewed it is marked as read.';
+$string['confirmsubscribe'] = 'Do you really want to subscribe to forum \'{$a}\'?';
+$string['confirmunsubscribe'] = 'Do you really want to unsubscribe from forum \'{$a}\'?';
 $string['couldnotadd'] = 'Could not add your post due to an unknown error';
 $string['couldnotdeletereplies'] = 'Sorry, that cannot be deleted as people have already responded to it';
 $string['couldnotupdate'] = 'Could not update your post due to an unknown error';
index c5b5bcc..443bd8c 100644 (file)
@@ -3155,7 +3155,7 @@ function forum_print_post($post, $discussion, $forum, &$cm, $course, $ownpost=fa
             return;
         }
         $output .= html_writer::tag('a', '', array('id'=>'p'.$post->id));
-        $output .= html_writer::start_tag('div', array('class'=>'forumpost clearfix '.$forumpostclass));
+        $output .= html_writer::start_tag('div', array('class'=>'forumpost clearfix'));
         $output .= html_writer::start_tag('div', array('class'=>'row header'));
         $output .= html_writer::tag('div', '', array('class'=>'left picture')); // Picture
         if ($post->parent) {
@@ -3165,6 +3165,7 @@ function forum_print_post($post, $discussion, $forum, &$cm, $course, $ownpost=fa
         }
         $output .= html_writer::tag('div', get_string('forumsubjecthidden','forum'), array('class'=>'subject')); // Subject
         $output .= html_writer::tag('div', get_string('forumauthorhidden','forum'), array('class'=>'author')); // author
+        $output .= html_writer::end_tag('div');
         $output .= html_writer::end_tag('div'); // row
         $output .= html_writer::start_tag('div', array('class'=>'row'));
         $output .= html_writer::tag('div', '&nbsp;', array('class'=>'left side')); // Groups
@@ -4504,10 +4505,11 @@ function forum_get_subscribe_link($forum, $context, $messages = array(), $cantac
 
         if ($fakelink) {
             $PAGE->requires->js('/mod/forum/forum.js');
-            $PAGE->requires->js_function_call('forum_produce_subscribe_link', Array($forum->id, $backtoindexlink, $linktext, $linktitle));
+            $PAGE->requires->js_function_call('forum_produce_subscribe_link', array($forum->id, $backtoindexlink, $linktext, $linktitle));
             $link = "<noscript>";
         }
-        $options ['id'] = $forum->id;
+        $options['id'] = $forum->id;
+        $options['sesskey'] = sesskey();
         $url = new moodle_url('/mod/forum/subscribe.php', $options);
         $link .= $OUTPUT->single_button($url, $linktext, 'get', array('title'=>$linktitle));
         if ($fakelink) {
@@ -7496,10 +7498,10 @@ function forum_extend_settings_navigation(settings_navigation $settingsnav, navi
     if ($canmanage) {
         $mode = $forumnode->add(get_string('subscriptionmode', 'forum'), null, navigation_node::TYPE_CONTAINER);
 
-        $allowchoice = $mode->add(get_string('subscriptionoptional', 'forum'), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>'0')), navigation_node::TYPE_SETTING);
-        $forceforever = $mode->add(get_string("subscriptionforced", "forum"), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>'1')), navigation_node::TYPE_SETTING);
-        $forceinitially = $mode->add(get_string("subscriptionauto", "forum"), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>'2')), navigation_node::TYPE_SETTING);
-        $disallowchoice = $mode->add(get_string('subscriptiondisabled', 'forum'), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>'3')), navigation_node::TYPE_SETTING);
+        $allowchoice = $mode->add(get_string('subscriptionoptional', 'forum'), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>FORUM_CHOOSESUBSCRIBE, 'sesskey'=>sesskey())), navigation_node::TYPE_SETTING);
+        $forceforever = $mode->add(get_string("subscriptionforced", "forum"), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>FORUM_FORCESUBSCRIBE, 'sesskey'=>sesskey())), navigation_node::TYPE_SETTING);
+        $forceinitially = $mode->add(get_string("subscriptionauto", "forum"), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>FORUM_INITIALSUBSCRIBE, 'sesskey'=>sesskey())), navigation_node::TYPE_SETTING);
+        $disallowchoice = $mode->add(get_string('subscriptiondisabled', 'forum'), new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'mode'=>FORUM_DISALLOWSUBSCRIBE, 'sesskey'=>sesskey())), navigation_node::TYPE_SETTING);
 
         switch ($subscriptionmode) {
             case FORUM_CHOOSESUBSCRIBE : // 0
@@ -7544,7 +7546,7 @@ function forum_extend_settings_navigation(settings_navigation $settingsnav, navi
         } else {
             $linktext = get_string('subscribe', 'forum');
         }
-        $url = new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id));
+        $url = new moodle_url('/mod/forum/subscribe.php', array('id'=>$forumobject->id, 'sesskey'=>sesskey()));
         $forumnode->add($linktext, $url, navigation_node::TYPE_SETTING);
     }
 
index 75efa7b..021c1d7 100644 (file)
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * Subscribe to or unsubscribe from a forum.
+ * Subscribe to or unsubscribe from a forum or manage forum subscription mode
  *
- * @package mod-forum
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * This script can be used by either individual users to subscribe to or
+ * unsubscribe from a forum (no 'mode' param provided), or by forum managers
+ * to control the subscription mode (by 'mode' param).
+ * This script can be called from a link in email so the sesskey is not
+ * required parameter. However, if sesskey is missing, the user has to go
+ * through a confirmation page that redirects the user back with the
+ * sesskey.
+ *
+ * @package    mod
+ * @subpackage forum
+ * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-require_once("../../config.php");
-require_once("lib.php");
+require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
+require_once($CFG->dirroot.'/mod/forum/lib.php');
 
-$id = required_param('id',PARAM_INT);      // The forum to subscribe or unsubscribe to
-$mode = optional_param('mode',false,PARAM_INT);  // Force everyone to be subscribed to this forum?
-$user = optional_param('user',0,PARAM_INT);
+$id      = required_param('id', PARAM_INT);             // the forum to subscribe or unsubscribe to
+$mode    = optional_param('mode', null, PARAM_INT);     // the forum's subscription mode
+$user    = optional_param('user', 0, PARAM_INT);        // userid of the user to subscribe, defaults to $USER
+$sesskey = optional_param('sesskey', null, PARAM_RAW);  // sesskey
 
 $url = new moodle_url('/mod/forum/subscribe.php', array('id'=>$id));
-if ($mode !== '') {
+if (!is_null($mode)) {
     $url->param('mode', $mode);
 }
 if ($user !== 0) {
     $url->param('user', $user);
 }
-$PAGE->set_url($url);
-
-if (! $forum = $DB->get_record("forum", array("id" => $id))) {
-    print_error('invalidforumid', 'forum');
-}
-
-if (! $course = $DB->get_record("course", array("id" => $forum->course))) {
-    print_error('invalidcoursemodule');
+if (!is_null($sesskey)) {
+    $url->param('sesskey', $sesskey);
 }
+$PAGE->set_url($url);
 
-$cm = get_coursemodule_from_instance("forum", $forum->id, $course->id, false, MUST_EXIST);
+$forum   = $DB->get_record('forum', array('id' => $id), '*', MUST_EXIST);
+$course  = $DB->get_record('course', array('id' => $forum->course), '*', MUST_EXIST);
+$cm      = get_coursemodule_from_instance('forum', $forum->id, $course->id, false, MUST_EXIST);
 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 
 if ($user) {
+    require_sesskey();
     if (!has_capability('mod/forum:managesubscriptions', $context)) {
         print_error('nopermissiontosubscribe', 'forum');
     }
-    if (!$user = $DB->get_record("user", array("id" => $user))) {
-        print_error('invaliduserid');
-    }
+    $user = $DB->get_record('user', array('id' => $user), MUST_EXIST);
 } else {
     $user = $USER;
 }
 
 if (isset($cm->groupmode) && empty($course->groupmodeforce)) {
-    $groupmode =  $cm->groupmode;
+    $groupmode = $cm->groupmode;
 } else {
     $groupmode = $course->groupmode;
 }
@@ -74,7 +80,7 @@ if ($groupmode && !forum_is_subscribed($user->id, $forum) && !has_capability('mo
 
 require_login($course->id, false, $cm);
 
-if (!is_enrolled($context)) {   // Guests and visitors can't subscribe - only enrolled
+if (is_null($mode) and !is_enrolled($context)) {   // Guests and visitors can't subscribe - only enrolled
     $PAGE->set_title($course->shortname);
     $PAGE->set_heading($course->fullname);
     echo $OUTPUT->header();
@@ -88,7 +94,8 @@ $returnto = optional_param('backtoindex',0,PARAM_INT)
     ? "index.php?id=".$course->id
     : "view.php?f=$id";
 
-if ($mode !== false && has_capability('mod/forum:managesubscriptions', $context)) {
+if (!is_null($mode) and has_capability('mod/forum:managesubscriptions', $context)) {
+    require_sesskey();
     switch ($mode) {
         case FORUM_CHOOSESUBSCRIBE : // 0
             forum_forcesubscribe($forum->id, 0);
@@ -119,6 +126,16 @@ $info->name  = fullname($user);
 $info->forum = format_string($forum->name);
 
 if (forum_is_subscribed($user->id, $forum->id)) {
+    if (is_null($sesskey)) {    // we came here via link in email
+        $PAGE->set_title($course->shortname);
+        $PAGE->set_heading($course->fullname);
+        echo $OUTPUT->header();
+        echo $OUTPUT->confirm(get_string('confirmunsubscribe', 'forum', format_string($forum->name)),
+                new moodle_url($PAGE->url, array('sesskey' => sesskey())), new moodle_url('/mod/forum/view.php', array('f' => $id)));
+        echo $OUTPUT->footer();
+        exit;
+    }
+    require_sesskey();
     if (forum_unsubscribe($user->id, $forum->id)) {
         add_to_log($course->id, "forum", "unsubscribe", "view.php?f=$forum->id", $forum->id, $cm->id);
         redirect($returnto, get_string("nownotsubscribed", "forum", $info), 1);
@@ -134,6 +151,16 @@ if (forum_is_subscribed($user->id, $forum->id)) {
     if (!has_capability('mod/forum:viewdiscussion', $context)) {
         print_error('noviewdiscussionspermission', 'forum', $_SERVER["HTTP_REFERER"]);
     }
+    if (is_null($sesskey)) {    // we came here via link in email
+        $PAGE->set_title($course->shortname);
+        $PAGE->set_heading($course->fullname);
+        echo $OUTPUT->header();
+        echo $OUTPUT->confirm(get_string('confirmsubscribe', 'forum', format_string($forum->name)),
+                new moodle_url($PAGE->url, array('sesskey' => sesskey())), new moodle_url('/mod/forum/view.php', array('f' => $id)));
+        echo $OUTPUT->footer();
+        exit;
+    }
+    require_sesskey();
     forum_subscribe($user->id, $forum->id);
     add_to_log($course->id, "forum", "subscribe", "view.php?f=$forum->id", $forum->id, $cm->id);
     redirect($returnto, get_string("nowsubscribed", "forum", $info), 1);
index 6fe70d8..7331813 100644 (file)
@@ -431,7 +431,7 @@ function SCORMapi1_2() {
                     }
                 ?>
                 result = ('true' == result) ? 'true' : 'false';
-                errorCode = (result ==' true')? '0' : '101';
+                errorCode = (result =='true')? '0' : '101';
                 <?php 
                     if (scorm_debugging($scorm)) {
                         //echo 'alert("Finished SCORM 1.2");';
index 9d8bf02..115f466 100755 (executable)
@@ -723,13 +723,13 @@ function scorm_view_display ($user, $scorm, $action, $cm, $boxwidth='') {
     if (empty($organization)) {
         $organization = $scorm->launch;
     }
-    if ($orgs = $DB->get_records_select('scorm_scoes', 'scorm = ? AND '.
+    if ($orgs = $DB->get_records_select_menu('scorm_scoes', 'scorm = ? AND '.
                                          $DB->sql_isempty('scorm_scoes', 'launch', false, true).' AND '.
                                          $DB->sql_isempty('scorm_scoes', 'organization', false, false),
                                          array($scorm->id),'id','id,title')) {
         if (count($orgs) > 1) {
             $select = new single_select(new moodle_url($action), 'organization', $orgs, $organization, null);
-            $select->lable = get_string('organizations','scorm');
+            $select->label = get_string('organizations','scorm');
             $select->class = 'scorm-center';
             echo $OUTPUT->render($select);
         }
index 63aaa4c..b65a3d5 100644 (file)
@@ -1,4 +1,12 @@
 <?php
+/**
+ * convert ewiki format text to html format
+ *
+ * @param object $oldentry wiki entry object
+ * @param object $oldpage wiki page object
+ * @param object $oldwiki wiki instance object
+ * @return string html format wiki content
+ */
 function wiki_ewiki_2_html($oldentry, $oldpage, $oldwiki) {
     global $CFG, $wiki_entry, $moodle_disable_camel_case, $ewiki_plugins, $ewiki_config, $moodle_format;
 
@@ -6,7 +14,7 @@ function wiki_ewiki_2_html($oldentry, $oldpage, $oldwiki) {
 
     $moodle_disable_camel_case = ($oldwiki->disablecamelcase == 1);
 
-        // Block of dinamic ewiki defines
+    // Block of dinamic ewiki defines
     wiki_set_define("EWIKI_NAME", $wiki_entry->pagename);
     wiki_set_define("EWIKI_DEFAULT_LANG", current_language());
     if ($moodle_disable_camel_case) {
@@ -48,8 +56,7 @@ function wiki_ewiki_2_html($oldentry, $oldpage, $oldwiki) {
 
     $content = ewiki_format($oldpage->content);
 
-    return format_text($content, $moodle_format);
-
+    return $content;
 }
 
 function wiki_set_define($key, $value) {
@@ -64,3 +71,512 @@ function wiki_get_define($key) {
     return $ewikidefines[$key];
 }
 
+function ewiki_mime_magic($binary_data) {
+    $mime_magic_data = array(
+        array(0, 2, 0, "\x06\x02", "application/x-alan-adventure-game"),
+        array(0, 4, 0, "TADS", "application/x-tads-game"),
+        array(0, 2, 0, "\x01\x10", "application/x-executable-file"),
+        array(0, 2, 0, "\x01\x11", "application/x-executable-file"),
+        array(0, 2, 0, "\x01\83", "application/x-executable-file"),
+        array(0, 5, 0, "Core\001", "application/x-executable-file"),
+        array(0, 22, 0, "AMANDA: TAPESTART DATE", "application/x-amanda-header"),
+        array(0, 2, 0xfff0, 0xf0ff, "audio/mpeg"),
+        array(4, 2, 0, "¯\x11", "video/fli"),
+        array(4, 2, 0, "¯\x12", "video/flc"),
+        array(0, 4, 0, "MOVI", "video/x-sgi-movie"),
+        array(4, 4, 0, "moov", "video/quicktime"),
+        array(4, 4, 0, "mdat", "video/quicktime"),
+        array(0, 18, 0, "FiLeStArTfIlEsTaRt", "text/x-apple-binscii"),
+        array(0, 3, 0, "\x0aGL", "application/data"),
+        array(0, 2, 0, "\x76\xff", "application/data"),
+        array(0, 6, 0, "NuFile", "application/data"),
+        array(0, 6, 0, "N\xf5F\xe9l\xe5", "application/data"),
+        array(0, 4, 0, "\x00\x16\x05\x00", "application/data"),
+        array(0, 4, 0, "\x07\x16\x05\x00", "application/data"),
+        array(257, 6, 0, "ustar\0", "application/x-tar"),
+        array(257, 8, 0, "ustar\040\040\0", "application/x-gtar"),
+        array(0, 2, 0, "qÇ", "application/x-cpio"),
+        array(0, 2, 0, "Çq", "application/x-bcpio"),
+        array(0, 6, 0, "070707", "application/x-cpio"),
+        array(0, 6, 0, "070701", "application/x-cpio"),
+        array(0, 6, 0, "070702", "application/x-cpio"),
+        array(0, 2, 0, "ÿm", "application/data"),
+        array(0, 2, 0, "ÿe", "application/data"),
+        array(0, 5, 0, "=<ar>", "application/x-ar"),
+        array(0, 19, 0, "!<arch>\n__________E", "application/x-ar"),
+        array(0, 3, 0, "-h-", "application/data"),
+        array(0, 7, 0, "!<arch>", "application/x-ar"),
+        array(0, 4, 0, "<ar>", "application/x-ar"),
+        array(0, 4, 0, ">ra<", "application/x-ar"),
+        array(0, 4, 0, "!<ar", "application/x-ar"),
+        array(0, 4, 0, "\x00\x03\9bí", "application/data"),
+        array(0, 4, 0, "\x00\x03\9bî", "application/data"),
+        array(0, 4, 0x8080ffff, 0x81a, "application/x-arc"),
+        array(0, 4, 0x8080ffff, 0x91a, "application/x-arc"),
+        array(0, 4, 0x8080ffff, 0x21a, "application/x-arc"),
+        array(0, 4, 0x8080ffff, 0x31a, "application/x-arc"),
+        array(0, 4, 0x8080ffff, 0x41a, "application/x-arc"),
+        array(0, 4, 0x8080ffff, 0x61a, "application/x-arc"),
+        array(0, 8, 0, "\032archive", "application/data"),
+        array(0, 2, 0, "ê`", "application/x-arj"),
+        array(0, 4, 0, "HPAK", "application/data"),
+        array(0, 8, 0, "\351,\001JAM\   ", "application/data"),
+        array(2, 5, 0, "-lh0-", "application/x-lha"),
+        array(2, 5, 0, "-lh1-", "application/x-lha"),
+        array(2, 5, 0, "-lz4-", "application/x-lha"),
+        array(2, 5, 0, "-lz5-", "application/x-lha"),
+        array(2, 5, 0, "-lzs-", "application/x-lha"),
+        array(2, 5, 0, "-lh\40-", "application/x-lha"),
+        array(2, 5, 0, "-lhd-", "application/x-lha"),
+        array(2, 5, 0, "-lh2-", "application/x-lha"),
+        array(2, 5, 0, "-lh3-", "application/x-lha"),
+        array(2, 5, 0, "-lh4-", "application/x-lha"),
+        array(2, 5, 0, "-lh5-", "application/x-lha"),
+        array(0, 4, 0, "Rar!", "application/x-rar"),
+        array(0, 4, 0, "SQSH", "application/data"),
+        array(0, 4, 0, "UC2\x1a", "application/data"),
+        array(0, 4, 0, "PK\003\004", "application/zip"),
+        array(20, 4, 0, "ýħÜ", "application/x-zoo"),
+        array(10, 25, 0, "# This is a shell archive", "application/x-shar"),
+        array(0, 4, 0, "*STA", "application/data"),
+        array(0, 4, 0, "2278", "application/data"),
+        array(0, 2, 0, "p\x01", "application/x-executable-file"),
+        array(0, 2, 0, "q\x01", "application/x-executable-file"),
+        array(0, 5, 0, "\000\004\036\212\200", "application/core"),
+        array(0, 4, 0, ".snd", "audio/basic"),
+        array(0, 4, 0, "\x00ds.", "audio/basic"),
+        array(0, 4, 0, "MThd", "audio/midi"),
+        array(0, 4, 0, "CTMF", "audio/x-cmf"),
+        array(0, 3, 0, "SBI", "audio/x-sbi"),
+        array(0, 19, 0, "Creative Voice File", "audio/x-voc"),
+        array(0, 4, 0, "KRTN", "audio/x-multitrack"),
+        array(0, 4, 0, "RIFF", "audio/x-wav"),
+        array(0, 4, 0, "EMOD", "audio/x-emod"),
+        array(0, 4, 0, "ýar.", "audio/x-pn-realaudio"),
+        array(0, 3, 0, "MTM", "audio/x-multitrack"),
+        array(0, 2, 0, "if", "audio/x-669-mod"),
+        array(0, 3, 0, "FAR", "audio/mod"),
+        array(0, 5, 0, "MAS_U", "audio/x-multimate-mod"),
+        array(0x2c, 4, 0, "SCRM", "audio/x-st3-mod"),
+        array(0, 22, 0, "GF1PATCH110\0ID#000002\0", "audio/x-gus-patch"),
+        array(0, 22, 0, "GF1PATCH100\0ID#000002\0", "audio/x-gus-patch"),
+        array(0, 2, 0, "JN", "audio/x-669-mod"),
+        array(0, 4, 0, "UN05", "audio/x-mikmod-uni"),
+        array(21, 8, 0, "!SCREAM!", "audio/x-st2-mod"),
+        array(1080, 4, 0, "M.K.", "audio/x-protracker-mod"),
+        array(1080, 4, 0, "M!K!", "audio/x-protracker-mod"),
+        array(1080, 4, 0, "FLT4", "audio/x-startracker-mod"),
+        array(1080, 4, 0, "4CHN", "audio/x-fasttracker-mod"),
+        array(1080, 4, 0, "6CHN", "audio/x-fasttracker-mod"),
+        array(1080, 4, 0, "8CHN", "audio/x-fasttracker-mod"),
+        array(1080, 4, 0, "CD81", "audio/x-oktalyzer-mod"),
+        array(1080, 4, 0, "OKTA", "audio/x-oktalyzer-mod"),
+        array(1080, 4, 0, "16CN", "audio/x-taketracker-mod"),
+        array(1080, 4, 0, "32CN", "audio/x-taketracker-mod"),
+        array(0, 3, 0, "TOC", "audio/x-toc"),
+        array(0, 2, 0, "\x07\x01", "application/x-executable-file"),
+        array(0, 2, 0, "\x01\x06", "application/x-executable-file"),
+        array(0, 2, 0, "\x06\x01", "application/x-executable-file"),
+        array(0, 2, 0, "//", "text/cpp"),
+        array(0, 5, 0, "\\1cw ", "application/data"),
+        array(0, 4, 0, "\\1cw", "application/data"),
+        array(0, 4, 0xffffff00, 0x140185, "application/data"),
+        array(0, 4, 0xffffff00, 0xcb0185, "application/data"),
+        array(0, 2, 0, "\x01}", "application/x-executable-file"),
+        array(0, 2, 0, "\x01\7f", "application/x-executable-file"),
+        array(4, 4, 0, "pipe", "application/data"),
+        array(4, 4, 0, "prof", "application/data"),
+        array(0, 9, 0, "#!/bin/sh", "application/x-sh"),
+        array(0, 10, 0, "#! /bin/sh", "application/x-sh"),
+        array(0, 11, 0, "#!\   /bin/sh", "application/x-sh"),
+        array(0, 10, 0, "#!/bin/csh", "application/x-csh"),
+        array(0, 11, 0, "#! /bin/csh", "application/x-csh"),
+        array(0, 12, 0, "#!\   /bin/csh", "application/x-csh"),
+        array(0, 10, 0, "#!/bin/ksh", "application/x-ksh"),
+        array(0, 11, 0, "#! /bin/ksh", "application/x-ksh"),
+        array(0, 12, 0, "#!\   /bin/ksh", "application/x-ksh"),
+        array(0, 17, 0, "#!/usr/local/tcsh", "application/x-csh"),
+        array(0, 21, 0, "#!/usr/local/bin/tcsh", "application/x-csh"),
+        array(0, 22, 0, "#! /usr/local/bin/tcsh", "application/x-csh"),
+        array(0, 23, 0, "#!\   /usr/local/bin/tcsh", "application/x-csh"),
+        array(0, 20, 0, "#!/usr/local/bin/zsh", "application/x-zsh"),
+        array(0, 21, 0, "#! /usr/local/bin/zsh", "application/x-zsh"),
+        array(0, 22, 0, "#!\   /usr/local/bin/zsh", "application/x-zsh"),
+        array(0, 20, 0, "#!/usr/local/bin/ash", "application/x-sh"),
+        array(0, 21, 0, "#! /usr/local/bin/ash", "application/x-zsh"),
+        array(0, 22, 0, "#!\   /usr/local/bin/ash", "application/x-zsh"),
+        array(0, 19, 0, "#!/usr/local/bin/ae", "text/script"),
+        array(0, 20, 0, "#! /usr/local/bin/ae", "text/script"),
+        array(0, 21, 0, "#!\   /usr/local/bin/ae", "text/script"),
+        array(0, 11, 0, "#!/bin/nawk", "application/x-awk"),
+        array(0, 12, 0, "#! /bin/nawk", "application/x-awk"),
+        array(0, 13, 0, "#!\   /bin/nawk", "application/x-awk"),
+        array(0, 15, 0, "#!/usr/bin/nawk", "application/x-awk"),
+        array(0, 16, 0, "#! /usr/bin/nawk", "application/x-awk"),
+        array(0, 17, 0, "#!\   /usr/bin/nawk", "application/x-awk"),
+        array(0, 21, 0, "#!/usr/local/bin/nawk", "application/x-awk"),
+        array(0, 22, 0, "#! /usr/local/bin/nawk", "application/x-awk"),
+        array(0, 23, 0, "#!\   /usr/local/bin/nawk", "application/x-awk"),
+        array(0, 11, 0, "#!/bin/gawk", "application/x-awk"),
+        array(0, 12, 0, "#! /bin/gawk", "application/x-awk"),
+        array(0, 13, 0, "#!\   /bin/gawk", "application/x-awk"),
+        array(0, 15, 0, "#!/usr/bin/gawk", "application/x-awk"),
+        array(0, 16, 0, "#! /usr/bin/gawk", "application/x-awk"),
+        array(0, 17, 0, "#!\   /usr/bin/gawk", "application/x-awk"),
+        array(0, 21, 0, "#!/usr/local/bin/gawk", "application/x-awk"),
+        array(0, 22, 0, "#! /usr/local/bin/gawk", "application/x-awk"),
+        array(0, 23, 0, "#!\   /usr/local/bin/gawk", "application/x-awk"),
+        array(0, 10, 0, "#!/bin/awk", "application/x-awk"),
+        array(0, 11, 0, "#! /bin/awk", "application/x-awk"),
+        array(0, 12, 0, "#!\   /bin/awk", "application/x-awk"),
+        array(0, 14, 0, "#!/usr/bin/awk", "application/x-awk"),
+        array(0, 15, 0, "#! /usr/bin/awk", "application/x-awk"),
+        array(0, 16, 0, "#!\   /usr/bin/awk", "application/x-awk"),
+        array(0, 5, 0, "BEGIN", "application/x-awk"),
+        array(0, 11, 0, "#!/bin/perl", "application/x-perl"),
+        array(0, 12, 0, "#! /bin/perl", "application/x-perl"),
+        array(0, 13, 0, "#!\   /bin/perl", "application/x-perl"),
+        array(0, 20, 0, "eval \"exec /bin/perl", "application/x-perl"),
+        array(0, 15, 0, "#!/usr/bin/perl", "application/x-perl"),
+        array(0, 16, 0, "#! /usr/bin/perl", "application/x-perl"),
+        array(0, 17, 0, "#!\   /usr/bin/perl", "application/x-perl"),
+        array(0, 24, 0, "eval \"exec /usr/bin/perl", "application/x-perl"),
+        array(0, 21, 0, "#!/usr/local/bin/perl", "application/x-perl"),
+        array(0, 22, 0, "#! /usr/local/bin/perl", "application/x-perl"),
+        array(0, 23, 0, "#!\   /usr/local/bin/perl", "application/x-perl"),
+        array(0, 30, 0, "eval \"exec /usr/local/bin/perl", "application/x-perl"),
+        array(0, 9, 0, "#!/bin/rc", "text/script"),
+        array(0, 10, 0, "#! /bin/rc", "text/script"),
+        array(0, 11, 0, "#!\   /bin/rc", "text/script"),
+        array(0, 11, 0, "#!/bin/bash", "application/x-sh"),
+        array(0, 12, 0, "#! /bin/bash", "application/x-sh"),
+        array(0, 13, 0, "#!\   /bin/bash", "application/x-sh"),
+        array(0, 21, 0, "#!/usr/local/bin/bash", "application/x-sh"),
+        array(0, 22, 0, "#! /usr/local/bin/bash", "application/x-sh"),
+        array(0, 23, 0, "#!\   /usr/local/bin/bash", "application/x-sh"),
+        array(0, 4, 0, "#! /", "text/script"),
+        array(0, 5, 0, "#!\   /", "text/script"),
+        array(0, 3, 0, "#!/", "text/script"),
+        array(0, 3, 0, "#! ", "text/script"),
+        array(0, 2, 0, "\037\235", "application/compress"),
+        array(0, 2, 0, "\037\213", "application/x-gzip"),
+        array(0, 2, 0, "\037\036", "application/data"),
+        array(0, 2, 0, "\x1f\x1f", "application/data"),
+        array(0, 2, 0, "\x1fÿ", "application/data"),
+        array(0, 2, 0, "\377\037", "application/data"),
+        array(0, 2, 0, "Ë\x05", "application/data"),
+        array(0, 3, 0, "BZh", "application/x-bzip2"),
+        array(0, 2, 0, "ÿv", "application/data"),
+        array(0, 2, 0, "þv", "application/data"),
+        array(0, 2, 0, "ýv", "application/x-lzh"),
+        array(0, 2, 0, "\037\237", "application/data"),
+        array(0, 2, 0, "\037\236", "application/data"),
+        array(0, 2, 0, "\037\240", "application/data"),
+        array(0, 2, 0, "BZ", "application/x-bzip"),
+        array(0, 9, 0, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", "application/data"),
+        array(0, 4, 0, "W\x12\x01\x00", "application/core"),
+        array(0, 4, 0, "Î\9aW\x13", "application/x-gdbm"),
+        array(0, 4, 0, "\x13W\9aÎ", "application/x-gdbm"),
+        array(0, 4, 0, "GDBM", "application/x-gdbm"),
+        array(0, 4, 0, "a\x15\x06\x00", "application/x-db"),
+        array(0, 4, 0, "b1\x05\x00", "application/x-db"),
+        array(0, 23, 0, "=<list>\n<protocol bbn-m", "application/data"),
+        array(0, 5, 0, "diff ", "text/x-patch"),
+        array(0, 4, 0, "*** ", "text/x-patch"),
+        array(0, 8, 0, "Only in ", "text/x-patch"),
+        array(0, 23, 0, "Common subdirectories: ", "text/x-patch"),
+        array(0, 19, 0, "!<arch>\n________64E", "application/data"),
+        array(0, 2, 0, "\x01\88", "application/x-executable-file"),
+        array(0, 2, 0, "\x01\8f", "application/x-object-file"),
+        array(0, 3, 0, "\377\377\177", "application/data"),
+        array(0, 3, 0, "\377\377\174", "application/data"),
+        array(0, 3, 0, "\377\377\176", "application/data"),
+        array(0, 3, 0, "\033c\033", "application/data"),
+        array(0, 4, 0, "\x00\x12Ö\87", "image/x11"),
+        array(0, 8, 0, "!<PDF>!\n", "application/x-prof"),
+        array(0, 2, 0, "\x05\x01", "application/x-locale"),
+        array(0, 4, 0, "\177ELF", "application/x-executable-file"),
+        array(0, 2, 0, "\x01T", "application/data"),
+        array(0, 2, 0, "\x01U", "application/x-executable-file"),
+        array(0x438, 2, 0, "ïS", "application/x-linux-ext2fs"),
+        array(0, 4, 0, "\366\366\366\366", "application/x-pc-floppy"),
+        array(0774, 2, 0, "¾Ú", "application/data"),
+        array(0x1FE, 2, 0, "ªU", "application/data"),
+        array(0x410, 2, 0, "\x13\7f", "application/x-filesystem"),
+        array(0x410, 2, 0, "\x13\8f", "application/x-filesystem"),
+        array(0x410, 2, 0, "\x24h", "application/x-filesystem"),
+        array(0x410, 2, 0, "\x24x", "application/x-filesystem"),
+        array(0, 9, 0, "-rom1fs-\0", "application/x-filesystem"),
+        array(0, 4, 0, "\x1b\x03\x136", "application/x-bootable"),
+        array(0x18b, 4, 0, "OS/2", "application/x-bootable"),
+        array(0, 4, 0, "FONT", "font/x-vfont"),
+        array(0, 2, 0, "\x01\x1e", "font/x-vfont"),
+        array(0, 2, 0, "\x1e\x01", "font/x-vfont"),
+        array(0, 18, 0, "%!PS-AdobeFont-1.0", "font/type1"),
+        array(6, 18, 0, "%!PS-AdobeFont-1.0", "font/type1"),
+        array(0, 10, 0, "STARTFONT\040", "font/x-bdf"),
+        array(0, 4, 0, "\001fcp", "font/x-pcf"),
+        array(0, 5, 0, "D1.0\015", "font/x-speedo"),
+        array(0, 3, 0, "flf", "font/x-figlet"),
+        array(0, 3, 0, "flc", "application/x-font"),
+        array(0, 4, 0, "\x19Y\x02\x14", "font/x-libgrx"),
+        array(0, 4, 0, "NOFÿ", "font/x-dos"),
+        array(7, 4, 0, "AGE\x00", "font/x-dos"),
+        array(7, 4, 0, "DIV\x00", "font/x-dos"),
+        array(0, 10, 0, "<MakerFile", "application/x-framemaker"),
+        array(0, 8, 0, "<MIFFile", "application/x-framemaker"),
+        array(0, 16, 0, "<MakerDictionary", "application/x-framemaker"),
+        array(0, 16, 0, "<MakerScreenFont", "font/x-framemaker"),
+        array(0, 4, 0, "<MML", "application/x-framemaker"),
+        array(0, 9, 0, "<BookFile", "application/x-framemaker"),
+        array(0, 6, 0, "<Maker", "application/x-framemaker"),
+        array(0, 4, 0377777777, 0x860107, "application/x-executable-file"),
+        array(0, 4, 0377777777, 0x860108, "application/x-executable-file"),
+        array(0, 4, 0377777777, 0x86010b, "application/x-executable-file"),
+        array(0, 4, 0377777777, 0x8600cc, "application/x-executable-file"),
+        array(7, 22, 0, "\357\020\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", "application/core"),
+        array(0, 4, 0, "LDHi", "application/data"),
+        array(0, 13, 0, "GIMP Gradient", "application/x-gimp-gradient"),
+        array(0, 8, 0, "gimp xcf", "application/x-gimp-image"),
+        array(20, 4, 0, "GPAT", "application/x-gimp-pattern"),
+        array(20, 4, 0, "GIMP", "application/x-gimp-brush"),
+        array(0, 4, 0, "\336\22\4\225", "application/x-locale"),
+        array(0, 4, 0, "\225\4\22\336", "application/x-locale"),
+        array(0, 2, 0, "\97\x01", "application/x-executable-file"),
+        array(0, 2, 0, "\94\x01", "application/x-executable-file"),
+        array(0, 5, 0, "\000\001\000\000\000", "font/ttf"),
+        array(0, 4, 0, "\x0a\x0f\x08\x0e", "application/data"),
+        array(0, 4, 0, "\x0f\x0a\x0e\x08", "application/data"),
+        array(0, 4, 0, "\x08\x0e\x0a\x0f", "application/data"),
+        array(0, 4, 0, "\x0e\x08\x0f\x0a", "application/data"),
+        array(0, 4, 0, "\x06\x01\x10\x02", "application/x-object-file"),
+        array(0, 4, 0, "\x07\x01\x10\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x08\x01\x10\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x0b\x01\x10\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x0e\x01\x10\x02", "application/x-library-file"),
+        array(0, 4, 0, "\x0d\x01\x10\x02", "application/x-library-file"),
+        array(0, 4, 0, "\x06\x01\x14\x02", "application/x-object-file"),
+        array(0, 4, 0, "\x07\x01\x14\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x08\x01\x14\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x0b\x01\x14\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x0e\x01\x14\x02", "application/x-library-file"),
+        array(0, 4, 0, "\x0d\x01\x14\x02", "application/x-object-file"),
+        array(0, 4, 0, "\x06\x01\x0b\x02", "application/x-object-file"),
+        array(0, 4, 0, "\x07\x01\x0b\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x08\x01\x0b\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x0b\x01\x0b\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x0e\x01\x0b\x02", "application/x-library-file"),
+        array(0, 4, 0, "\x0d\x01\x0b\x02", "application/x-library-file"),
+        array(0, 4, 0, "ra<!", "application/x-ar"),
+        array(0, 4, 0, "\x02\x08\x01\x06", "application/x-executable-file"),
+        array(0, 4, 0, "\x02\x08\x01\x07", "application/x-executable-file"),
+        array(0, 4, 0, "\x02\x08\x01\x08", "application/x-executable-file"),
+        array(0, 4, 0, "\x08\x01\x0c\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x07\x01\x0c\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x0b\x01\x0c\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x06\x01\x0c\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x08\x01\x0a\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x07\x01\x0a\x02", "application/x-executable-file"),
+        array(0, 4, 0, "\x0e\x01\x0c\x02", "application/x-library-file"),
+        array(0, 4, 0, "\x0d\x01\x0c\x02", "application/x-library-file"),
+        array(0, 4, 0, "\x02\x0aÿe", "application/x-library-file"),
+        array(0, 4, 0, "\x02\x0cÿe", "application/x-library-file"),
+        array(0, 4, 0, "\x02\x08ÿe", "application/x-library-file"),
+        array(0, 4, 0, "\x01X!¦", "application/core"),
+        array(0, 4, 0, "M§îè", "font/x-hp-windows"),
+        array(0, 10, 0, "Bitmapfile", "image/unknown"),
+        array(0, 4, 0, "\x02\x0c\x01\x0c", "application/x-lisp"),
+        array(0, 8, 0, "msgcat01", "application/x-locale"),
+        array(0, 2, 0, "P1", "image/x-portable-bitmap"),
+        array(0, 2, 0, "P2", "image/x-portable-graymap"),
+        array(0, 2, 0, "P3", "image/x-portable-pixmap"),
+        array(0, 2, 0, "P4", "image/x-portable-bitmap"),
+        array(0, 2, 0, "P5", "image/x-portable-graymap"),
+        array(0, 2, 0, "P6", "image/x-portable-pixmap"),
+        array(0, 4, 0, "IIN1", "image/tiff"),
+        array(0, 4, 0, "MM\x00\x2a", "image/tiff"),
+        array(0, 4, 0, "II\x2a\x00", "image/tiff"),
+        array(0, 4, 0, "\x89PNG", "image/x-png"),
+        array(1, 3, 0, "PNG", "image/x-png"),
+        array(0, 4, 0, "GIF8", "image/gif"),
+        array(0, 4, 0, "\361\0\100\273", "image/x-cmu-raster"),
+        array(0, 2, 0, "Øÿ", "image/jpeg"),
+        array(0, 4, 0, "hsi1", "image/x-jpeg-proprietary"),
+        array(0, 2, 0, "BM", "image/x-bmp"),
+        array(0, 2, 0, "IC", "image/x-ico"),
+        array(0, 4, 0, "\95j¦Y", "x/x-image-sun-raster"),
+        array(0, 2, 0, "Ú\x01", "x/x-image-sgi"),
+        array(2048, 7, 0, "PCD_IPI", "x/x-photo-cd-pack-file"),
+        array(0, 7, 0, "PCD_OPA", "x/x-photo-cd-overfiew-file"),
+        array(0, 2, 0, "\x01H", "application/x-executable-file"),
+        array(0, 2, 0, "\x01I", "application/x-executable-file"),
+        array(0, 2, 0, "\x01J", "application/x-executable-file"),
+        array(0, 2, 0, "\x01R", "application/x-executable-file"),
+        array(0, 2, 0, "\x01L", "application/x-executable-file"),
+        array(0, 2, 0, "\x046", "font/linux-psf"),
+        array(0, 4, 0, "FFIL", "font/ttf"),
+        array(65, 4, 0, "FFIL", "font/ttf"),
+        array(0, 4, 0, "LWFN", "font/type1"),
+        array(65, 4, 0, "LWFN", "font/type1"),
+        array(0, 12, 0, "Return-Path:", "message/rfc822"),
+        array(0, 5, 0, "Path:", "message/news"),
+        array(0, 5, 0, "Xref:", "message/news"),
+        array(0, 5, 0, "From:", "message/rfc822"),
+        array(0, 7, 0, "Article", "message/news"),
+        array(0, 5, 0, "BABYL", "message/x-gnu-rmail"),
+        array(0, 9, 0, "Received:", "message/rfc822"),
+        array(0, 2, 0, "MZ", "application/x-ms-dos-executable"),
+        array(2080, 27, 0, "Microsoft Word 6.0 Document", "text/vnd.ms-word"),
+        array(2080, 26, 0, "Documento Microsoft Word 6", "text/vnd.ms-word"),
+        array(2112, 9, 0, "MSWordDoc", "text/vnd.ms-word"),
+        array(0, 5, 0, "PO^Q`", "text/vnd.ms-word"),
+        array(2080, 29, 0, "Microsoft Excel 5.0 Worksheet", "application/vnd.ms-excel"),
+        array(2114, 5, 0, "Biff5", "application/vnd.ms-excel"),
+        array(1, 3, 0, "WPC", "text/vnd.wordperfect"),
+        array(0, 4, 0377777777, 0x7018600, "NetBSD/i386"),
+        array(0, 4, 0377777777, 0x7018700, "NetBSD/m68k"),
+        array(0, 4, 0377777777, 0x7018800, "NetBSD/m68k4k"),
+        array(0, 4, 0377777777, 0x7018900, "NetBSD/ns32532"),
+        array(0, 4, 0377777777, 0x7018a00, "NetBSD/sparc"),
+        array(0, 4, 0377777777, 0x7018b00, "NetBSD/pmax"),
+        array(0, 4, 0377777777, 0x7018c00, "NetBSD/vax"),
+        array(0, 4, 0377777777, 0x7018e00, "NetBSD/mips"),
+        array(0, 4, 0377777777, 0x7018f00, "NetBSD/arm32"),
+        array(0, 16, 0, "StartFontMetrics", "font/x-sunos-news"),
+        array(0, 9, 0, "StartFont", "font/x-sunos-news"),
+        array(0, 4, 0, "D)z\x13", "font/x-sunos-news"),
+        array(0, 4, 0, "G)z\x13", "font/x-sunos-news"),
+        array(0, 4, 0, "P)z\x13", "font/x-sunos-news"),
+        array(0, 4, 0, "Q)z\x13", "font/x-sunos-news"),
+        array(8, 4, 0, "E+z\x13", "font/x-sunos-news"),
+        array(8, 4, 0, "H+z\x13", "font/x-sunos-news"),
+        array(0, 2, 0, "%!", "application/postscript"),
+        array(0, 3, 0, "\004%!", "application/postscript"),
+        array(0, 3, 0, "\033E\033", "image/x-pcl-hp"),
+        array(0, 14, 0, "<!DOCTYPE HTML", "text/html"),
+        array(0, 14, 0, "<!doctype html", "text/html"),
+        array(0, 5, 0, "<HEAD", "text/html"),
+        array(0, 5, 0, "<head", "text/html"),
+        array(0, 6, 0, "<TITLE", "text/html"),
+        array(0, 6, 0, "<title", "text/html"),
+        array(0, 5, 0, "<html", "text/html"),
+        array(0, 5, 0, "<HTML", "text/html"),
+        array(0, 2, 0, "\367\203", "font/x-tex"),
+        array(0, 2, 0, "\367\131", "font/x-tex"),
+        array(0, 2, 0, "\367\312", "font/x-tex"),
+        array(2, 2, 0, "\000\021", "font/x-tex-tfm"),
+        array(2, 2, 0, "\000\022", "font/x-tex-tfm"),
+        array('>2', 2, 0, "º¾", "application/java"),
+        array(8, 4, 0, "AIFF", "audio/x-aiff"),
+        array(8, 4, 0, "AIFC", "audio/x-aiff"),
+        array(8, 4, 0, "8SVX", "audio/x-aiff"),
+        array('>8', 4, 0, "WAVE", "audio/x-wav"),
+        array('>8', 3, 0, "AVI", "video/x-msvideo"),
+        array(0, 3, 0, "ID3", "audio/mpeg"),
+        array(0, 4, 0, "OggS", "audio/x-ogg"),
+        array(0, 6, 0, "/* XPM", "image/x-xpm"),
+        array(16, 2, 0, "==", "image/x-3ds"),
+        array(0, 11, 0, "#!/bin/tcsh", "application/x-shellscript"),
+        array(0, 12, 0, "#! /bin/tcsh", "application/x-shellscript"),
+        array(0, 18, 0, "#! /usr/local/tcsh", "application/x-shellscript"),
+        array('>8', 6, 0, "debian", "application/x-debian-package"),
+        array('>2', 2, 0, "Ûî", "application/x-rpm"),
+        array(2, 5, 0, "-lh -", "application/x-lha"),
+        array(2, 5, 0, "-lh6-", "application/x-lha"),
+        array(2, 5, 0, "-lh7-", "application/x-lha"),
+        array(0, 15, 0, "<MakerScreenFon", "application/x-frame"),
+        array(0, 5, 0, "<Book", "application/x-frame"),
+        array(0, 3, 0, "<h1", "text/html"),
+        array(0, 3, 0, "<H1", "text/html"),
+        array(0, 14, 0, "<!doctype HTML", "text/html"),
+        array(0, 2, 0, "MM", "image/tiff"),
+        array(0, 2, 0, "II", "image/tiff"),
+        array(0, 6, 0, "GIF94z", "image/unknown"),
+        array(0, 6, 0, "FGF95a", "image/unknown"),
+        array(0, 3, 0, "PBF", "image/unknown"),
+        array(0, 3, 0, "GIF", "image/gif"),
+        array(0, 4, 0, "\376\067\0\043", "application/msword"),
+        array(0, 6, 0, "\320\317\021\340\241\261", "application/msword"),
+        array(0, 6, 0, "\333\245-\0\0\0", "application/msword"),
+        array(0, 2, 0, "\x02÷", "application/x-dvi"),
+        array(0, 2, 0, "¯\x11", "video/fli"),
+        array(0, 2, 0, "¯\x12", "video/flc"),
+        array('>8', 4, 0, "AVI ", "video/avi"),
+        array(0, 1, 0, "\x01", "video/unknown"),
+        array(0, 1, 0, "\x02", "video/unknown"),
+        array(0, 19, 0, "[KDE Desktop Entry]", "application/x-kdelnk"),
+        array(0, 18, 0, "\# KDE Config File", "application/x-kdelnk"),
+        array(0, 7, 0, "\# xmcd", "text/xmcd"),
+        array(0, 4, 0, "\x8aMNG", "video/x-mng"),
+        array(0, 4, 0, "ó\x03\x00\x00", "application/x-executable-file"),
+        array(0, 4, 0, "ç\x03\x00\x00", "application/x-library-file"),
+        array(0, 4, 0, "³\x01\x00\x00", "video/mpeg"),
+        array(0, 4, 0, "º\x01\x00\x00", "video/mpeg"),
+        array(0, 4, 0, "\x00\x00\81l", "application/x-apl-workspace"),
+        array(0, 4, 0, "\x00\x00ÿm", "application/x-ar"),
+        array(0, 4, 0, "\x00\x00ÿe", "application/data"),
+        array(0, 4, 0, "\x00\x00\x01\x06", "application/x-executable-file"),
+        array(0, 4, 0, "G\x01\x00\x00", "application/x-object-file"),
+        array(0, 4, 0, "K\x01\x00\x00", "application/x-executable-file"),
+        array(0, 4, 0, "M\x01\x00\x00", "application/x-executable-file"),
+        array(0, 4, 0, "O\x01\x00\x00", "application/x-executable-file"),
+        array(24, 4, 0, "kê\x00\x00", "application/data"),
+        array(24, 4, 0, "lê\x00\x00", "application/data"),
+        array(24, 4, 0, "mê\x00\x00", "application/data"),
+        array(24, 4, 0, "nê\x00\x00", "application/data"),
+        array(0, 4, 0, "\81\x01\x00\x00", "application/x-object-file"),
+        array(0, 4, 0, "\87\x01\x00\x00", "application/data"),
+        array(24, 4, 0, "\x00\x00êl", "application/x-dump"),
+        array(24, 4, 0, "\x00\x00êk", "application/x-dump"),
+        array(0, 4, 0, "\x00\x00¾1", "text/vnd.ms-word"),
+        array(0, 2, 0, "\x00\x00", "audio/mpeg"),
+        array('>16', 2, 0, "\x00\x01", "application/x-object"),
+        array('>16', 2, 0, "\x00\x02", "application/x-executable"),
+        array('>16', 2, 0, "\x00\x03", "application/x-sharedlib"),
+        array('>16', 2, 0, "\x00\x04", "application/x-coredump"),
+        array(0, 4, 0, "\x00\x00\x00Ì", "application/x-executable-file"),
+        array(0, 4, 0, "\x04\x00\x00\x00", "font/x-snf"),
+        array(0, 4, 0, "\x00\x00\x00\x04", "font/x-snf"),
+        array('>12', 4, 0, "\x01\x00\x00\x00", "audio/basic"),
+        array('>12', 4, 0, "\x02\x00\x00\x00", "audio/basic"),
+        array('>12', 4, 0, "\x03\x00\x00\x00", "audio/basic"),
+        array('>12', 4, 0, "\x04\x00\x00\x00", "audio/basic"),
+        array('>12', 4, 0, "\x05\x00\x00\x00", "audio/basic"),
+        array('>12', 4, 0, "\x06\x00\x00\x00", "audio/basic"),
+        array('>12', 4, 0, "\x07\x00\x00\x00", "audio/basic"),
+        array('>12', 4, 0, "\x17\x00\x00\x00", "audio/x-adpcm"),
+        array('>12', 4, 0, "\x00\x00\x00\x01", "audio/x-dec-basic"),
+        array('>12', 4, 0, "\x00\x00\x00\x02", "audio/x-dec-basic"),
+        array('>12', 4, 0, "\x00\x00\x00\x03", "audio/x-dec-basic"),
+        array('>12', 4, 0, "\x00\x00\x00\x04", "audio/x-dec-basic"),
+        array('>12', 4, 0, "\x00\x00\x00\x05", "audio/x-dec-basic"),
+        array('>12', 4, 0, "\x00\x00\x00\x06", "audio/x-dec-basic"),
+        array('>12', 4, 0, "\x00\x00\x00\x07", "audio/x-dec-basic"),
+        array('>12', 4, 0, "\x00\x00\x00\x17", "audio/x-dec-adpcm")
+   );
+
+   $fd = substr($binary_data, 0, 3072);
+   foreach ($mime_magic_data as $def) {
+      $pos0 = $def[0];
+      if ($pos0[0] == ">") {
+         $pos0 = substr($pos0, 1);
+         if (@strpos($fd, $def[3], $pos0) !== false) {
+               return($def[4]);
+         }
+      } else {
+         $part = substr($fd, $pos0, $def[1]);
+         $mask = $def[2];
+         if ($mask) {
+             // if $mask is 0
+            $value = 1 * ('0x'.bin2hex($part));
+            if (($value & $mask) == $def[3]) {
+               return($def[4]);
+            }
+         } else {
+            if ($part == $def[3]) {
+               return($def[4]);
+            }
+         }
+      }
+   }
+}
index 923352f..74a6d09 100644 (file)
@@ -149,9 +149,9 @@ function xmldb_wiki_upgrade($oldversion) {
         /**
          * Migrating wiki entries to new subwikis
          */
-        $sql = "INSERT into {wiki_subwikis} (wikiid, groupid, userid)
-                    SELECT DISTINCT e.wikiid, e.groupid, e.userid
-                    FROM {wiki_entries_old} e";
+        $sql = "INSERT INTO {wiki_subwikis} (wikiid, groupid, userid)
+                SELECT DISTINCT e.wikiid, e.groupid, e.userid
+                  FROM {wiki_entries_old} e";
         echo $OUTPUT->notification('Migrating old entries to new subwikis', 'notifysuccess');
 
         $DB->execute($sql, array());
@@ -161,30 +161,39 @@ function xmldb_wiki_upgrade($oldversion) {
 
     // Step 5: Migrating pages
     if ($oldversion < 2010040105) {
-        /**
-         * Filling pages table with latest versions of every page.
-         *
-         * @TODO:   Ensure that ALL versions of every page are always in database and
-         *          they can be removed or cleaned.
-         *          That fact could let us rewrite the subselect to execute a count(*) to avoid
-         *          the order by and it would be much faster.
-         */
 
-        $sql = "INSERT into {wiki_pages} (subwikiid, title, cachedcontent, timecreated, timemodified, userid, pageviews)
-                    SELECT s.id, p.pagename, ?, p.created, p.lastmodified, p.userid, p.hits
-                    FROM {wiki_pages_old} p
-                    LEFT OUTER JOIN {wiki_entries_old} e ON e.id = p.wiki
-                    LEFT OUTER JOIN {wiki_subwikis} s
-                    ON s.wikiid = e.wikiid AND s.groupid = e.groupid AND s.userid = e.userid
-                    WHERE p.version = (
-                        SELECT max(po.version)
-                        FROM {wiki_pages_old} po
-                        WHERE p.pagename = po.pagename and
-                        p.wiki = po.wiki
-                    )";
+        // select all wiki pages
+        $sql = "SELECT s.id, p.pagename, p.created, p.lastmodified, p.userid, p.hits
+                  FROM {wiki_pages_old} p
+                  LEFT OUTER JOIN {wiki_entries_old} e ON e.id = p.wiki
+                  LEFT OUTER JOIN {wiki_subwikis} s ON s.wikiid = e.wikiid AND s.groupid = e.groupid AND s.userid = e.userid
+                 WHERE p.version = (SELECT max(po.version)
+                                      FROM {wiki_pages_old} po
+                                     WHERE p.pagename = po.pagename AND p.wiki = po.wiki)";
         echo $OUTPUT->notification('Migrating old pages to new pages', 'notifysuccess');
 
-        $DB->execute($sql, array('**reparse needed**'));
+        $records = $DB->get_recordset_sql($sql);
+        foreach ($records as $record) {
+            $page = new stdclass();
+            $page->subwikiid     = $record->id;
+            $page->title         = $record->pagename;
+            $page->cachedcontent = '**reparse needed**';
+            $page->timecreated   = $record->created;
+            $page->timemodified  = $record->lastmodified;
+            $page->userid        = $record->userid;
+            $page->pageviews     = $record->hits;
+            try {
+                // make sure there is no duplicated records exist
+                if (!$DB->record_exists('wiki_pages', array('subwikiid'=>$record->id, 'userid'=>$record->userid, 'title'=>$record->pagename))) {
+                    $DB->insert_record('wiki_pages', $page);
+                }
+            } catch (dml_exception $e) {
+                // catch possible insert exception
+                debugging($e->getMessage());
+                continue;
+            }
+        }
+        $records->close();
 
         upgrade_mod_savepoint(true, 2010040105, 'wiki');
     }
@@ -295,22 +304,6 @@ function xmldb_wiki_upgrade($oldversion) {
         upgrade_mod_savepoint(true, 2010040109, 'wiki');
     }
 
-    // TODO: Will hold the old tables so we will have chance to fix problems
-    // Will remove old tables once migrating 100% stable
-    // Step 10: delete old tables
-    if ($oldversion < 2010040120) {
-        //$tables = array('wiki_pages', 'wiki_locks', 'wiki_entries');
-
-        //foreach ($tables as $tablename) {
-            //$table = new xmldb_table($tablename . '_old');
-            //if ($dbman->table_exists($table)) {
-                //$dbman->drop_table($table);
-            //}
-        //}
-        //echo $OUTPUT->notification('Droping old tables', 'notifysuccess');
-        //upgrade_mod_savepoint(true, 2010040120, 'wiki');
-    }
-
     if ($oldversion < 2010080201) {
 
         $sql = "UPDATE {comments}
@@ -359,37 +352,53 @@ function xmldb_wiki_upgrade($oldversion) {
 
         upgrade_mod_savepoint(true, 2010102800, 'wiki');
     }
-    
+
     if ($oldversion < 2011011000) {
         // Fix wiki in the post table after upgrade from 1.9
         $table = new xmldb_table('wiki');
-        
+
         // name should default to Wiki
         $field = new xmldb_field('name', XMLDB_TYPE_CHAR, 255, null, XMLDB_NOTNULL, null, 'Wiki', 'course');
         if ($dbman->field_exists($table, $field)) {
             $dbman->change_field_default($table, $field);
         }
-        
+
         // timecreated field is missing after 1.9 upgrade
         $field = new xmldb_field('timecreated', XMLDB_TYPE_INTEGER, 10, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'introformat');
         if (!$dbman->field_exists($table, $field)) {
             $dbman->add_field($table, $field);
         }
-        
+
         // timemodified field is missing after 1.9 upgrade
         $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, 10, XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'timecreated');
         if (!$dbman->field_exists($table, $field)) {
             $dbman->add_field($table, $field);
         }
-        
+
         // scaleid is not there any more
         $field = new xmldb_field('scaleid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', null);
         if ($dbman->field_exists($table, $field)) {
             $dbman->drop_field($table, $field);
         }
-        
+
         upgrade_mod_savepoint(true, 2011011000, 'wiki');
     }
 
+    // TODO: Will hold the old tables so we will have chance to fix problems
+    // Will remove old tables once migrating 100% stable
+    // Step 10: delete old tables
+    //if ($oldversion < 2011000000) {
+        //$tables = array('wiki_pages', 'wiki_locks', 'wiki_entries');
+
+        //foreach ($tables as $tablename) {
+            //$table = new xmldb_table($tablename . '_old');
+            //if ($dbman->table_exists($table)) {
+                //$dbman->drop_table($table);
+            //}
+        //}
+        //echo $OUTPUT->notification('Droping old tables', 'notifysuccess');
+        //upgrade_mod_savepoint(true, 2011000000, 'wiki');
+    //}
+
     return true;
 }
index d4a961c..1fd3d44 100644 (file)
@@ -202,23 +202,52 @@ function wiki_upgrade_install_20_tables() {
  */
 function wiki_upgrade_migrate_versions() {
     global $DB, $CFG, $OUTPUT;
-    upgrade_set_timeout();
     require_once($CFG->dirroot . '/mod/wiki/db/migration/lib.php');
-    $sql = "SELECT po.id as oldpage_id, po.pagename as oldpage_pagename, po.version, po.flags, po.content, po.author, po.userid as oldpage_userid, po.created, po.lastmodified, po.refs, po.meta, po.hits, po.wiki,
-                p.id as newpage_id, p.subwikiid, p.title, p.cachedcontent, p.timecreated, p.timemodified as newpage_timemodified, p.timerendered, p.userid as newpage_userid, p.pageviews, p.readonly,
-                e.id as entry_id, e.wikiid, e.course as entrycourse, e.groupid, e.userid as entry_userid, e.pagename as entry_pagename, e.timemodified as entry_timemodified,
-                w.id as wiki_id, w.course as wiki_course, w.name, w.summary as summary, w.pagename as wiki_pagename, w.wtype, w.ewikiprinttitle, w.htmlmode, w.ewikiacceptbinary, w.disablecamelcase, w.setpageflags, w.strippages, w.removepages, w.revertchanges, w.initialcontent, w.timemodified as wiki_timemodified
-                FROM {wiki_pages_old} po LEFT OUTER JOIN {wiki_entries_old} e
-                ON e.id = po.wiki
-                LEFT OUTER JOIN {wiki} w
-                ON w.id = e.wikiid
-                LEFT OUTER JOIN {wiki_subwikis} s
-                ON e.groupid = s.groupid AND e.wikiid = s.wikiid AND e.userid = s.userid
-                LEFT OUTER JOIN {wiki_pages} p
-                ON po.pagename = p.title AND p.subwikiid = s.id";
+    // need to move the binary data in db
+    $fs = get_file_storage();
+    // select all wiki pages history
+    $sql = "SELECT po.id AS oldpage_id, po.pagename AS oldpage_pagename, po.version, po.flags,
+                   po.content, po.author, po.userid AS oldpage_userid, po.created, po.lastmodified, po.refs, po.meta, po.hits, po.wiki,
+                   p.id AS newpage_id, p.subwikiid, p.title, p.cachedcontent, p.timecreated, p.timemodified AS newpage_timemodified,
+                   p.timerendered, p.userid AS newpage_userid, p.pageviews, p.readonly, e.id AS entry_id, e.wikiid, e.course AS entrycourse,
+                   e.groupid, e.userid AS entry_userid, e.pagename AS entry_pagename, e.timemodified AS entry_timemodified,
+                   w.id AS wiki_id, w.course AS wiki_course, w.name, w.summary AS summary, w.pagename AS wiki_pagename, w.wtype,
+                   w.ewikiprinttitle, w.htmlmode, w.ewikiacceptbinary, w.disablecamelcase, w.setpageflags, w.strippages, w.removepages,
+                   w.revertchanges, w.initialcontent, w.timemodified AS wiki_timemodified,
+                   cm.id AS cmid
+              FROM {wiki_pages_old} po
+              LEFT OUTER JOIN {wiki_entries_old} e ON e.id = po.wiki
+              LEFT OUTER JOIN {wiki} w ON w.id = e.wikiid
+              LEFT OUTER JOIN {wiki_subwikis} s ON e.groupid = s.groupid AND e.wikiid = s.wikiid AND e.userid = s.userid
+              LEFT OUTER JOIN {wiki_pages} p ON po.pagename = p.title AND p.subwikiid = s.id
+              JOIN {modules} m ON m.name = 'wiki'
+              JOIN {course_modules} cm ON (cm.module = m.id AND cm.instance = w.id)";
+
     $pagesinfo = $DB->get_recordset_sql($sql, array());
 
     foreach ($pagesinfo as $pageinfo) {
+        upgrade_set_timeout();
+
+        $mimetype = ewiki_mime_magic($pageinfo->content);
+        if (!empty($mimetype)) {
+            // if mimetype is not empty, means this is a file stored in db
+            $context = get_context_instance(CONTEXT_MODULE, $pageinfo->cmid);
+            // clean up file name
+            $filename = clean_param($pageinfo->oldpage_pagename, PARAM_FILE);
+            $filerecord = array('contextid' => $context->id,
+                                'component' => 'mod_wiki',
+                                'filearea'  => 'attachments',
+                                'itemid'    => $pageinfo->subwikiid,
+                                'filepath'  => '/',
+                                'filename'  => $filename,
+                                'userid'    => $pageinfo->oldpage_userid);
+            if (!$fs->file_exists($context->id, 'mod_wiki', 'attachments', $pageinfo->subwikiid, '/', $pageinfo->pagename)) {
+                $storedfile = $fs->create_file_from_string($filerecord, $pageinfo->content);
+            }
+
+            // replace page content to a link point to the file
+            $pageinfo->content = "<a href='@@PLUGINFILE@@/$filename'>$pageinfo->oldpage_pagename</a>";
+        }
 
         $oldpage = new StdClass();
         $oldpage->id = $pageinfo->oldpage_id;
@@ -276,8 +305,9 @@ function wiki_upgrade_migrate_versions() {
 
         $version = new StdClass();
         $version->pageid = $page->id;
+        // convert wiki content to html format
         $version->content = wiki_ewiki_2_html($entry, $oldpage, $wiki);
-        $version->contentformat = "html";
+        $version->contentformat = 'html';
         $version->version = $oldpage->version;
         $version->timecreated = $oldpage->lastmodified;
         $version->userid = $oldpage->userid;
@@ -292,14 +322,14 @@ function wiki_upgrade_migrate_versions() {
                 $version->version = 1;
                 $version->content = $content;
                 $DB->insert_record('wiki_versions', $version);
-            } catch (Exception $e) {
-                echo $OUTPUT->notification('Cannot insert this record, page id: ' . $page->id);
+            } catch (dml_exception $e) {
+                debugging($e->getMessage());
             }
         } else {
             try {
                 $DB->insert_record('wiki_versions', $version);
-            } catch (Exception $e) {
-                echo $OUTPUT->notification('Cannot insert this record, page id: ' . $page->id);
+            } catch (dml_exception $e) {
+                debugging($e->getMessage());
             }
         }
     }
index 6f07795..2ff2741 100644 (file)
@@ -261,6 +261,9 @@ function wiki_refresh_cachedcontent($page, $newcontent = null) {
     global $DB;
 
     $version = wiki_get_current_version($page->id);
+    if (empty($version)) {
+        return null;
+    }
     if (!isset($newcontent)) {
         $newcontent = $version->content;
     }
@@ -299,7 +302,11 @@ function wiki_refresh_page_links($page, $links) {
             $newlink->topageid = $linkinfo['pageid'];
         }
 
-        $DB->insert_record('wiki_links', $newlink);
+        try {
+            $DB->insert_record('wiki_links', $newlink);
+        } catch (dml_exception $e) {
+            debugging($e->getMessage());
+        }
 
     }
 }
index a0ae412..26b09fe 100644 (file)
@@ -67,10 +67,13 @@ class description_qtype extends default_questiontype {
         // For editing teachers print a link to an editing popup window
         $editlink = $this->get_question_edit_link($question, $cmoptions, $options);
 
+        $context = $this->get_context_by_category_id($question->category);
+        $question->questiontext = quiz_rewrite_question_urls($question->questiontext, 'pluginfile.php', $context->id, 'question', 'questiontext', array($state->attempt, $state->question), $question->id);
         $questiontext = $this->format_text($question->questiontext, $question->questiontextformat, $cmoptions);
 
         $generalfeedback = '';
         if ($isfinished && $options->generalfeedback) {
+            $question->generalfeedback = quiz_rewrite_question_urls($question->generalfeedback, 'pluginfile.php', $context->id, 'question', 'generalfeedback', array($state->attempt, $state->question), $question->id);
             $generalfeedback = $this->format_text($question->generalfeedback,
                     $question->generalfeedbackformat, $cmoptions);
         }
index 6f07bda..2721fdb 100644 (file)
@@ -66,8 +66,7 @@ class user_filter_globalrole extends user_filter_type {
 
         $sql = "id IN (SELECT userid
                          FROM {role_assignments} a
-                        WHERE a.contextid=".SYSCONTEXTID." AND a.roleid=$value AND a.timestart<$timenow
-                              AND (a.timeend=0 OR a.timeend>$timenow))";
+                        WHERE a.contextid=".SYSCONTEXTID." AND a.roleid=$value)";
         return array($sql, array());
     }
 
index 37b89d0..da41cb3 100644 (file)
@@ -37,6 +37,7 @@
 require_once(dirname(__FILE__) . '/../config.php');
 require_once($CFG->dirroot . '/my/lib.php');
 require_once($CFG->dirroot . '/user/profile/lib.php');
+require_once($CFG->libdir.'/filelib.php');
 
 $userid = optional_param('id', 0, PARAM_INT);
 $edit   = optional_param('edit', null, PARAM_BOOL);    // Turn editing on and off
index 06482ba..ccd4a71 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version = 2010122900;  // YYYYMMDD   = date of the last version bump
+$version = 2011010400;  // YYYYMMDD   = date of the last version bump
                         //         XX = daily increments
 
-$release = '2.0.1+ (Build: 20101229)';  // Human-friendly version name
+$release = '2.0.1+ (Build: 20110105)';  // Human-friendly version name