Merge branch 'MDL-26399_oracle_restore_wip' of git://github.com/stronk7/moodle
authorPetr Skoda <commits@skodak.org>
Mon, 14 Feb 2011 19:34:58 +0000 (20:34 +0100)
committerPetr Skoda <commits@skodak.org>
Mon, 14 Feb 2011 19:34:58 +0000 (20:34 +0100)
49 files changed:
admin/cli/automated_backups.php
admin/settings/server.php
auth/shibboleth/auth.php
backup/util/helper/backup_cron_helper.class.php
blocks/moodleblock.class.php
course/format/topics/format.php
course/format/weeks/format.php
course/lib.php
course/report/completion/index.php
course/view.php
enrol/renderer.php
filter/mediaplugin/filter.php
filter/mediaplugin/simpletest/testfiltermediaplugin.php [new file with mode: 0644]
install.php
install/lang/de/install.php
install/lang/pt_br/install.php
lang/en/admin.php
lib/accesslib.php
lib/db/upgrade.php
lib/ddl/postgres_sql_generator.php
lib/dml/mysqli_native_moodle_database.php
lib/dml/sqlsrv_native_moodle_database.php
lib/filelib.php
lib/minify/MOODLE_README.txt [deleted file]
lib/minify/config.php
lib/moodlelib.php
lib/navigationlib.php
lib/outputrenderers.php
lib/outputrequirementslib.php
lib/sessionlib.php
lib/setuplib.php
lib/weblib.php
login/index.php
mod/data/export_form.php
mod/data/import.php
mod/data/lang/en/data.php
mod/data/lib.php
mod/forum/lib.php
mod/forum/user.php
mod/quiz/report/overview/report.php
mod/quiz/report/responses/report.php
question/qengine.js
question/type/numerical/questiontype.php
rating/rate_ajax.php
repository/upload/lib.php
theme/yui_combo.php
user/profile.php
user/view.php
version.php

index 8126c5a..dc80c7a 100644 (file)
@@ -92,7 +92,7 @@ mtrace("Server Time: ".date('r',$timenow)."\n\n");
 // Run automated backups if required.
 require_once($CFG->dirroot.'/backup/util/includes/backup_includes.php');
 require_once($CFG->dirroot.'/backup/util/helper/backup_cron_helper.class.php');
-backup_cron_automated_helper::run_automated_backup(backup_cron_automated_helper::RUN_IMMEDIATLY);
+backup_cron_automated_helper::run_automated_backup(backup_cron_automated_helper::RUN_IMMEDIATELY);
 
 mtrace("Automated cron backups completed correctly");
 
index 052405d..7f6647f 100644 (file)
@@ -266,5 +266,6 @@ $ADMIN->add('server', $temp);
 
 
 $ADMIN->add('server', new admin_externalpage('adminregistration', get_string('registration','admin'), "$CFG->wwwroot/$CFG->admin/registration/index.php"));
+$ADMIN->add('root', new admin_externalpage('bloglevelupgrade', get_string('bloglevelupgrade', 'admin'), $CFG->wwwroot.'/'.$CFG->admin.'/blocklevelupgrade.php', 'moodle/site:config', true));
 
 } // end of speedup
index d5062bc..fa0591e 100644 (file)
@@ -242,7 +242,7 @@ class auth_plugin_shibboleth extends auth_plugin_base {
 
         // set to defaults if undefined
         if (!isset($config->auth_instructions) or empty($config->user_attribute)) {
-            $config->auth_instructions = get_string('shibboleth_instructions', 'auth', $CFG->wwwroot.'/auth/shibboleth/index.php');
+            $config->auth_instructions = get_string('auth_shib_instructions', 'auth_shibboleth', $CFG->wwwroot.'/auth/shibboleth/index.php');
         }
         if (!isset ($config->user_attribute)) {
             $config->user_attribute = '';
@@ -292,7 +292,7 @@ class auth_plugin_shibboleth extends auth_plugin_base {
         } else {
             // Check if integrated WAYF was enabled and is now turned off
             // If it was and only then, reset the Moodle alternate URL
-            if ($this->config->alt_login == 'on'){
+            if (isset($this->config->alt_login) and $this->config->alt_login == 'on'){
                 set_config('alt_login',    'off',    'auth/shibboleth');
                 set_config('alternateloginurl', '');
             }
index 6044872..5c37e18 100644 (file)
@@ -49,8 +49,8 @@ abstract class backup_cron_automated_helper {
 
     /** Run if required by the schedule set in config. Default. **/
     const RUN_ON_SCHEDULE = 0;
-    /** Run immediatly. **/
-    const RUN_IMMEDIATLY = 1;
+    /** Run immediately. **/
+    const RUN_IMMEDIATELY = 1;
 
     const AUTO_BACKUP_DISABLED = 0;
     const AUTO_BACKUP_ENABLED = 1;
@@ -75,7 +75,7 @@ abstract class backup_cron_automated_helper {
             return $state;
         } else if ($state === backup_cron_automated_helper::STATE_RUNNING) {
             mtrace('RUNNING');
-            if ($rundirective == self::RUN_IMMEDIATLY) {
+            if ($rundirective == self::RUN_IMMEDIATELY) {
                 mtrace('automated backups are already. If this script is being run by cron this constitues an error. You will need to increase the time between executions within cron.');
             } else {
                 mtrace("automated backup are already running. Execution delayed");
@@ -130,12 +130,12 @@ abstract class backup_cron_automated_helper {
                     $DB->update_record('backup_courses', $backupcourse);
                     mtrace('Skipping unchanged course '.$course->fullname);
                     $skipped = true;
-                } else if (($backupcourse->nextstarttime >= 0 && $backupcourse->nextstarttime < $now) || $rundirective == self::RUN_IMMEDIATLY) {
+                } else if (($backupcourse->nextstarttime >= 0 && $backupcourse->nextstarttime < $now) || $rundirective == self::RUN_IMMEDIATELY) {
                     mtrace('Backing up '.$course->fullname, '...');
 
                     //We have to send a email because we have included at least one backup
                     $emailpending = true;
-                    
+
                     //Only make the backup if laststatus isn't 2-UNFINISHED (uncontrolled error)
                     if ($backupcourse->laststatus != 2) {
                         //Set laststarttime
@@ -270,7 +270,7 @@ abstract class backup_cron_automated_helper {
         $config = get_config('backup');
         $midnight = usergetmidnight($now, $timezone);
         $date = usergetdate($now, $timezone);
-        
+
         //Get number of days (from today) to execute backups
         $automateddays = substr($config->backup_auto_weekdays,$date['wday']) . $config->backup_auto_weekdays;
         $daysfromtoday = strpos($automateddays, "1");
@@ -335,7 +335,7 @@ abstract class backup_cron_automated_helper {
             $users = $bc->get_plan()->get_setting('users')->get_value();
             $anonymised = $bc->get_plan()->get_setting('anonymize')->get_value();
             $bc->get_plan()->get_setting('filename')->set_value(backup_plan_dbops::get_default_backup_filename($format, $type, $id, $users, $anonymised));
-            
+
             $bc->set_status(backup::STATUS_AWAITING);
 
             $outcome = $bc->execute_plan();
@@ -505,7 +505,7 @@ abstract class backup_cron_automated_helper {
         // Clean up excess backups in the specified external directory
         if (!empty($dir) && ($storage == 1 || $storage == 2)) {
             // Calculate backup filename regex
-            
+
             $filename = $backupword . '-' . backup::FORMAT_MOODLE . '-' . backup::TYPE_1COURSE . '-' .$course->id . '-';
 
             $regex = '#^'.preg_quote($filename, '#').'(\d{8})\-(\d{4})\-[a-z]{2}\.mbz$#S';
index 89f2e14..adf7d68 100644 (file)
@@ -209,7 +209,7 @@ class block_base {
     }
 
     /**
-     * Return a block_contents oject representing the full contents of this block.
+     * Return a block_contents object representing the full contents of this block.
      *
      * This internally calls ->get_content(), and then adds the editing controls etc.
      *
@@ -217,7 +217,7 @@ class block_base {
      * {@link html_attributes()}, {@link formatted_contents()} or {@link get_content()},
      * {@link hide_header()}, {@link (get_edit_controls)}, etc.
      *
-     * @return block_contents a represntation of the block, for rendering.
+     * @return block_contents a representation of the block, for rendering.
      * @since Moodle 2.0.
      */
     public function get_content_for_output($output) {
@@ -243,10 +243,11 @@ class block_base {
 
         if ($this->page->user_is_editing()) {
             $bc->controls = $this->page->blocks->edit_controls($this);
-        }
-
-        if ($this->is_empty() && !$bc->controls) {
-            return null;
+        } else {
+            // we must not use is_empty on hidden blocks
+            if ($this->is_empty() && !$bc->controls) {
+                return null;
+            }
         }
 
         if (empty($CFG->allowuserblockhiding) ||
@@ -620,7 +621,7 @@ class block_base {
 
     /**
      * Can be overridden by the block to prevent the block from being dockable.
-     * 
+     *
      * @return bool
      */
     public function instance_can_be_docked() {
index 905892d..aa1004f 100644 (file)
@@ -35,11 +35,7 @@ $topic = optional_param('topic', -1, PARAM_INT);
 if ($topic != -1) {
     $displaysection = course_set_display($course->id, $topic);
 } else {
-    if (isset($USER->display[$course->id])) {
-        $displaysection = $USER->display[$course->id];
-    } else {
-        $displaysection = course_set_display($course->id, 0);
-    }
+    $displaysection = course_get_display($course->id);
 }
 
 $context = get_context_instance(CONTEXT_COURSE, $course->id);
index c43def7..68e66a4 100644 (file)
@@ -34,11 +34,7 @@ defined('MOODLE_INTERNAL') || die();
     if ($week != -1) {
         $displaysection = course_set_display($course->id, $week);
     } else {
-        if (isset($USER->display[$course->id])) {
-            $displaysection = $USER->display[$course->id];
-        } else {
-            $displaysection = course_set_display($course->id, 0);
-        }
+        $displaysection = course_get_display($course->id);
     }
 
     $streditsummary  = get_string('editsummary');
index 492275d..aad31ff 100644 (file)
@@ -1239,26 +1239,71 @@ function get_all_sections($courseid) {
     return $coursesections[$courseid];
 }
 
-function course_set_display($courseid, $display=0) {
+/**
+ * Returns the course section to display or 0 meaning show all sections. Returns 0 for guests.
+ * It also sets the $USER->display cache to array($courseid=>return value)
+ *
+ * @param int $courseid The course id
+ * @return int Course section to display, 0 means all
+ */
+function course_get_display($courseid) {
+    global $USER, $DB;
+
+    if (!isloggedin() or isguestuser()) {
+        //do not get settings in db for guests
+        return 0; //return the implicit setting
+    }
+
+    if (!isset($USER->display[$courseid])) {
+        if (!$display = $DB->get_field('course_display', 'display', array('userid' => $USER->id, 'course'=>$courseid))) {
+            $display = 0; // all sections option is not stored in DB, this makes the table much smaller
+        }
+        //use display cache for one course only - we need to keep session small
+        $USER->display = array($courseid => $display);
+    }
+
+    return $USER->display[$courseid];
+}
+
+/**
+ * Show one section only or all sections.
+ *
+ * @param int $courseid The course id
+ * @param mixed $display show only this section, 0 or 'all' means show all sections
+ * @return int Course section to display, 0 means all
+ */
+function course_set_display($courseid, $display) {
     global $USER, $DB;
 
-    if ($display == "all" or empty($display)) {
+    if ($display === 'all' or empty($display)) {
         $display = 0;
     }
 
     if (!isloggedin() or isguestuser()) {
         //do not store settings in db for guests
-    } else if ($DB->record_exists("course_display", array("userid" => $USER->id, "course"=>$courseid))) {
-        $DB->set_field("course_display", "display", $display, array("userid"=>$USER->id, "course"=>$courseid));
+        return 0;
+    }
+
+    if ($display == 0) {
+        //show all, do not store anything in database
+        $DB->delete_records('course_display', array('userid' => $USER->id, 'course' => $courseid));
+
     } else {
-        $record = new stdClass();
-        $record->userid = $USER->id;
-        $record->course = $courseid;
-        $record->display = $display;
-        $DB->insert_record("course_display", $record);
+        if ($DB->record_exists('course_display', array('userid' => $USER->id, 'course' => $courseid))) {
+            $DB->set_field('course_display', 'display', $display, array('userid' => $USER->id, 'course' => $courseid));
+        } else {
+            $record = new stdClass();
+            $record->userid = $USER->id;
+            $record->course = $courseid;
+            $record->display = $display;
+            $DB->insert_record('course_display', $record);
+        }
     }
 
-    return $USER->display[$courseid] = $display;  // Note: = not ==
+    //use display cache for one course only - we need to keep session small
+    $USER->display = array($courseid => $display);
+
+    return $display;
 }
 
 /**
@@ -2837,7 +2882,7 @@ function move_section($course, $section, $move) {
     $DB->set_field("course_sections", "section", $section, array("id"=>$sectiondestrecord->id));
 
     // if the focus is on the section that is being moved, then move the focus along
-    if (isset($USER->display[$course->id]) and ($USER->display[$course->id] == $section)) {
+    if (course_get_display($course->id) == $section) {
         course_set_display($course->id, $sectiondest);
     }
 
@@ -2890,7 +2935,7 @@ function move_section_to($course, $section, $destination) {
     }
 
     // if the focus is on the section that is being moved, then move the focus along
-    if (isset($USER->display[$course->id]) and ($USER->display[$course->id] == $section)) {
+    if (course_get_display($course->id) == $section) {
         course_set_display($course->id, $destination);
     }
     return true;
index 9f3df05..470722d 100644 (file)
@@ -474,7 +474,7 @@ if(!$csv) {
 
                 // Display icon
                 $icon = $OUTPUT->pix_url('icon', $criterion->module);
-                $iconlink = $CFG->wwwroot.'/mod/'.$criterion->module.'/view.php?id='.$activity->id;
+                $iconlink = $CFG->wwwroot.'/mod/'.$criterion->module.'/view.php?id='.$criterion->moduleinstance;
                 $icontitle = $activity->name;
                 $iconalt = get_string('modulename', $criterion->module);
                 break;
index e21aada..28ed124 100644 (file)
                     echo $OUTPUT->notification('An error occurred while moving a section');
                 }
                 // Clear the navigation cache at this point so that the affects
-                // are seen immediatly on the navigation.
+                // are seen immediately on the navigation.
                 $PAGE->navigation->clear_cache();
             }
         }
index 20b7972..5235c63 100644 (file)
@@ -632,12 +632,14 @@ class course_enrolment_users_table extends course_enrolment_table {
 
         $instances  = $this->manager->get_enrolment_instances();
         $plugins    = $this->manager->get_enrolment_plugins();
+        $manuals    = array();
         // print enrol link or selection
         $links = array();
         foreach($instances as $instance) {
             $plugin = $plugins[$instance->enrol];
             if ($link = $plugin->get_manual_enrol_link($instance)) {
                 $links[$instance->id] = $link;
+                $manuals[$instance->id] = $instance;
             }
         }
         if (!empty($links)) {
@@ -671,6 +673,7 @@ class course_enrolment_users_table extends course_enrolment_table {
             $startdateoptions[3] = get_string('today') . ' (' . userdate($today, $timeformat) . ')' ;
 
             if ($count == 1) {
+                $instance = reset($manuals);
                 $page->requires->strings_for_js(array(
                     'ajaxoneuserfound',
                     'ajaxxusersfound',
@@ -697,7 +700,7 @@ class course_enrolment_users_table extends course_enrolment_table {
                     'ajaxurl'=>'/enrol/ajax.php',
                     'url'=>$url->out(false),
                     'optionsStartDate'=>$startdateoptions,
-                    'defaultRole'=>get_config('enrol_manual', 'roleid'));
+                    'defaultRole'=>$instance->roleid);
                 $page->requires->yui_module($modules, $function, array($arguments));
             }
             return $control;
index 6a9ec85..fb3801c 100644 (file)
@@ -46,96 +46,101 @@ class filter_mediaplugin extends moodle_text_filter {
             // non string data can not be filtered anyway
             return $text;
         }
+        if (stripos($text, '</a>') === false) {
+            // performance shortcut - all regexes bellow end with the </a> tag,
+            // if not present nothing can match
+            return $text;
+        }
         $newtext = $text; // fullclone is slow and not needed here
 
         if (!empty($CFG->filter_mediaplugin_enable_mp3)) {
-            $search =   '/<a[^>]*?href="([^<]+\.mp3)"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.mp3)"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_mp3_callback', $newtext);
         }
 
         if (!empty($CFG->filter_mediaplugin_enable_ogg)) {
-            $search =   '/<a[^>]*?href="([^<]+\.ogg)"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.ogg)"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_ogg_callback', $newtext);
         }
 
         if (!empty($CFG->filter_mediaplugin_enable_ogv)) {
-            $search =   '/<a[^>]*?href="([^<]+\.ogv)"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.ogv)"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_ogv_callback', $newtext);
         }
 
         if (!empty($CFG->filter_mediaplugin_enable_swf)) {
-            $search = '/<a[^>]*?href="([^<]+\.swf)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.swf)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_swf_callback', $newtext);
         }
 
         if (!empty($CFG->filter_mediaplugin_enable_flv)) {
-            $search = '/<a[^>]*?href="([^<]+\.flv)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.flv)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_flv_callback', $newtext);
         }
 
         if (!empty($CFG->filter_mediaplugin_enable_mov)) {
-            $search = '/<a[^>]*?href="([^<]+\.mov)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.mov)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_qt_callback', $newtext);
 
-            $search = '/<a[^>]*?href="([^<]+\.mp4)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.mp4)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_qt_callback', $newtext);
 
-            $search = '/<a[^>]*?href="([^<]+\.m4v)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.m4v)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_qt_callback', $newtext);
 
-            $search = '/<a[^>]*?href="([^<]+\.m4a)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.m4a)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_qt_callback', $newtext);
         }
 
         if (!empty($CFG->filter_mediaplugin_enable_wmv)) {
-            $search = '/<a[^>]*?href="([^<]+\.wmv)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.wmv)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_wmp_callback', $newtext);
         }
 
         if (!empty($CFG->filter_mediaplugin_enable_mpg)) {
-            $search = '/<a[^>]*?href="([^<]+\.mpe?g)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.mpe?g)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_qt_callback', $newtext);
         }
 
         if (!empty($CFG->filter_mediaplugin_enable_avi)) {
-            $search = '/<a[^>]*?href="([^<]+\.avi)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.avi)(\?d=([\d]{1,3}%?)x([\d]{1,3}%?))?"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_wmp_callback', $newtext);
         }
 
         if (!empty($CFG->filter_mediaplugin_enable_ram)) {
-            $search = '/<a[^>]*?href="([^<]+\.ram)"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.ram)"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_real_callback', $newtext);
         }
 
         if (!empty($CFG->filter_mediaplugin_enable_rpm)) {
-            $search = '/<a[^>]*?href="([^<]+\.rpm)"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.rpm)"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_real_callback', $newtext);
         }
 
         if (!empty($CFG->filter_mediaplugin_enable_rm)) {
-            $search = '/<a[^>]*?href="([^<]+\.rm)"[^>]*>.*?<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.rm)"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_real_callback', $newtext);
         }
 
         if (!empty($CFG->filter_mediaplugin_enable_youtube)) {
-            //see MDL-23903 for description of recent changes to this regex
-            //$search = '/<a.*?href="([^<]*)youtube.com\/watch\?v=([^"]*)"[^>]*>(.*?)<\/a>/is';
-            $search = '/<a[^>]*href="([^<]*?)youtube.com\/watch\?v=([^"]*)"[^>]*>(.*?)<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="(([^"]+youtube\.com)\/watch\?v=([A-Za-z0-9\-_]+))[^>]*>(.*?)<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_youtube_callback', $newtext);
 
-            $search = '/<a[^>]*href="([^<]*)youtube.com\/v\/([^"]*)"[^>]*>(.*?)<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="(([^"]+youtube\.com)\/v\/([A-Za-z0-9\-_]*))[^>]+>(.*?)<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_youtube_callback', $newtext);
 
-            $search = '/<a(\s+[^>]+?)?\s+href="((([^"]+)youtube\.com)\/view_play_list\?p=([^"]*))"[^>]*>(.*?)<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="((([^"]+)youtube\.com)\/view_play_list\?p=([A-Za-z0-9\-_]+))[^>]*>(.*?)<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_youtube_playlist_callback', $newtext);
         }
 
         if (!empty($CFG->filter_mediaplugin_enable_img)) {
-            $search = '/<a[^>]*?href="([^<]+\.jpg)"[^>]*>(.*?)<\/a>/is';
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.jpg)"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_img_callback', $newtext);
-            $search = '/<a[^>]*?href="([^<]+\.png)"[^>]*>(.*?)<\/a>/is';
+
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.png)"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_img_callback', $newtext);
-            $search = '/<a[^>]*?href="([^<]+\.gif)"[^>]*>(.*?)<\/a>/is';
+
+            $search = '/<a(\s+[^>]+?)?\s+href="([^"]+\.gif)"[^>]*>.*?<\/a>/is';
             $newtext = preg_replace_callback($search, 'filter_mediaplugin_img_callback', $newtext);
         }
 
@@ -166,7 +171,7 @@ function filter_mediaplugin_mp3_callback($link) {
     $count++;
     $id = 'filter_mp3_'.time().$count; //we need something unique because it might be stored in text cache
 
-    $url = addslashes_js($link[1]);
+    $url = addslashes_js($link[2]);
 
     $playerpath = $CFG->wwwroot.'/filter/mediaplugin/mp3player.swf';
     $audioplayerpath = $CFG->wwwroot .'/filter/mediaplugin/flowplayer.audio.swf';
@@ -215,7 +220,7 @@ function filter_mediaplugin_ogg_callback($link) {
     $count++;
     $id = 'filter_ogg_'.time().$count; //we need something unique because it might be stored in text cache
 
-    $url = addslashes_js($link[1]);
+    $url = $link[2];
     $printlink = html_writer::link($url, get_string('oggaudio', 'filter_mediaplugin'));
     $unsupportedplugins = get_string('unsupportedplugins', 'filter_mediaplugin', $printlink);
     $output = <<<OET
@@ -234,7 +239,7 @@ function filter_mediaplugin_ogv_callback($link) {
     $count++;
     $id = 'filter_ogv_'.time().$count; //we need something unique because it might be stored in text cache
 
-    $url = addslashes_js($link[1]);
+    $url = $link[2];
     $printlink = html_writer::link($url, get_string('ogvvideo', 'filter_mediaplugin'));
     $unsupportedplugins = get_string('unsupportedplugins', 'filter_mediaplugin', $printlink);
     $output = <<<OET
@@ -252,9 +257,9 @@ function filter_mediaplugin_swf_callback($link) {
     $count++;
     $id = 'filter_swf_'.time().$count; //we need something unique because it might be stored in text cache
 
-    $width  = empty($link[3]) ? '400' : $link[3];
-    $height = empty($link[4]) ? '300' : $link[4];
-    $url = addslashes_js($link[1]);
+    $width  = empty($link[4]) ? '400' : $link[4];
+    $height = empty($link[5]) ? '300' : $link[5];
+    $url = $link[2];
 
     $args = Array();
     $args['movie'] = $url;
@@ -279,16 +284,17 @@ function filter_mediaplugin_flv_callback($link) {
     $count++;
     $id = 'filter_flv_'.time().$count; //we need something unique because it might be stored in text cache
 
-    $width  = empty($link[3]) ? '480' : $link[3];
-    $height = empty($link[4]) ? '360' : $link[4];
-    $url = addslashes_js($link[1]);
+    // note: in 1.9.x this used to be 480x360
+    $width  = empty($link[4]) ? '800' : $link[4];
+    $height = empty($link[5]) ? '600' : $link[5];
+    $url = addslashes_js($link[2]);
 
     $playerpath = $CFG->wwwroot.'/filter/mediaplugin/flvplayer.swf';
 
     $output = <<<EOT
     <span class="mediaplugin mediaplugin_flv" id="$id"></span>
     <noscript><div>
-    <object width="800" height="600" id="undefined" name="undefined" data="$playerpath" type="application/x-shockwave-flash">
+    <object width="$width" height="$height" id="undefined" name="undefined" data="$playerpath" type="application/x-shockwave-flash">
     <param name="movie" value="$playerpath" />
     <param name="allowfullscreen" value="true" />
     <param name="allowscriptaccess" value="always" />
@@ -305,7 +311,8 @@ EOT;
 }
 
 function filter_mediaplugin_real_callback($link, $autostart=false) {
-    $url = addslashes_js($link[1]);
+    $url = $link[2];
+    $jsurl = addslashes_js($link[2]);
     $mimetype = mimeinfo('type', $url);
     $autostart = $autostart ? 'true' : 'false';
 
@@ -315,19 +322,19 @@ function filter_mediaplugin_real_callback($link, $autostart=false) {
 <script type="text/javascript">
 //<![CDATA[
 document.write(\'<object classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="240" height="180">\\
-  <param name="src" value="'.$url.'" />\\
+  <param name="src" value="'.$jsurl.'" />\\
   <param name="autostart" value="'.$autostart.'" />\\
   <param name="controls" value="imagewindow" />\\
   <param name="console" value="video" />\\
   <param name="loop" value="true" />\\
-  <embed src="'.$url.'" width="240" height="180" loop="true" type="'.$mimetype.'" controls="imagewindow" console="video" autostart="'.$autostart.'" />\\
+  <embed src="'.$jsurl.'" width="240" height="180" loop="true" type="'.$mimetype.'" controls="imagewindow" console="video" autostart="'.$autostart.'" />\\
   </object><br />\\
   <object classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="240" height="30">\\
-  <param name="src" value="'.$url.'" />\\
+  <param name="src" value="'.$jsurl.'" />\\
   <param name="autostart" value="'.$autostart.'" />\\
   <param name="controls" value="ControlPanel" />\\
   <param name="console" value="video" />\\
-  <embed src="'.$url.'" width="240" height="30" controls="ControlPanel" type="'.$mimetype.'" console="video" autostart="'.$autostart.'" />\\
+  <embed src="'.$jsurl.'" width="240" height="30" controls="ControlPanel" type="'.$mimetype.'" console="video" autostart="'.$autostart.'" />\\
   </object>\');
 //]]>
 </script></span>';
@@ -337,15 +344,15 @@ document.write(\'<object classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" wi
  * Change links to Youtube into embedded Youtube videos
  */
 function filter_mediaplugin_youtube_callback($link, $autostart=false) {
+    $site = s($link[3]);
+    $param = $link[4]; // video id
+    $info = s(strip_tags($link[5]));
 
-    $site = addslashes_js($link[1]);
-    $url = addslashes_js($link[2]);
-    $info = addslashes_js(strip_tags($link[3]));//strip out html tags as they won't work in the title attribute
 
     return '<object title="'.$info.'"
                     class="mediaplugin mediaplugin_youtube" type="application/x-shockwave-flash"
-                    data="'.$site.'youtube.com/v/'.$url.'&amp;fs=1&amp;rel=0" width="425" height="344">'.
-           '<param name="movie" value="'.$site.'youtube.com/v/'.$url.'&amp;fs=1&amp;rel=0" />'.
+                    data="'.$site.'/v/'.$param.'&amp;fs=1&amp;rel=0" width="400" height="320">'.
+           '<param name="movie" value="'.$site.'/v/'.$param.'&amp;fs=1&amp;rel=0" />'.
            '<param name="FlashVars" value="playerMode=embedded" />'.
            '<param name="wmode" value="transparent" />'.
            '<param name="allowFullScreen" value="true" />'.
@@ -358,8 +365,8 @@ function filter_mediaplugin_youtube_callback($link, $autostart=false) {
 function filter_mediaplugin_youtube_playlist_callback($link, $autostart=false) {
 
     $site = s($link[4]);
-    $param = s($link[5]);
-    $info = s($link[6]);
+    $param = $link[5]; // playlist id
+    $info = s(strip_tags($link[6]));
 
     return '<object title="'.$info.'"
                     class="mediaplugin mediaplugin_youtube" type="application/x-shockwave-flash"
@@ -375,9 +382,8 @@ function filter_mediaplugin_youtube_playlist_callback($link, $autostart=false) {
  * Change links to images into embedded images
  */
 function filter_mediaplugin_img_callback($link, $autostart=false) {
-    $url = addslashes_js($link[1]);
-    $info = addslashes_js($link[2]);
-
+    $url = $link[2];
+    $info = s(strip_tags($link[2]));
     return '<img class="mediaplugin mediaplugin_img" alt="" title="'.$info.'" src="'.$url.'" />';
 }
 
@@ -385,13 +391,13 @@ function filter_mediaplugin_img_callback($link, $autostart=false) {
  * Embed video using window media player if available
  */
 function filter_mediaplugin_wmp_callback($link, $autostart=false) {
-    $url = $link[1];
-    if (empty($link[3]) or empty($link[4])) {
+    $url = $link[2];
+    if (empty($link[4]) or empty($link[5])) {
         $mpsize = '';
         $size = 'width="300" height="260"';
         $autosize = 'true';
     } else {
-        $size = 'width="'.$link[3].'" height="'.$link[4].'"';
+        $size = 'width="'.$link[4].'" height="'.$link[5].'"';
         $mpsize = $size;
         $autosize = 'false';
     }
@@ -428,11 +434,11 @@ function filter_mediaplugin_wmp_callback($link, $autostart=false) {
 }
 
 function filter_mediaplugin_qt_callback($link, $autostart=false) {
-    $url = $link[1];
-    if (empty($link[3]) or empty($link[4])) {
+    $url = $link[2];
+    if (empty($link[4]) or empty($link[5])) {
         $size = 'width="440" height="315"';
     } else {
-        $size = 'width="'.$link[3].'" height="'.$link[4].'"';
+        $size = 'width="'.$link[4].'" height="'.$link[5].'"';
     }
     $mimetype = mimeinfo('type', $url);
     $autostart = $autostart ? 'true' : 'false';
diff --git a/filter/mediaplugin/simpletest/testfiltermediaplugin.php b/filter/mediaplugin/simpletest/testfiltermediaplugin.php
new file mode 100644 (file)
index 0000000..362206b
--- /dev/null
@@ -0,0 +1,124 @@
+<?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 test for the filter_mediaplugin
+ *
+ * @package    filter
+ * @subpackage Mediaplugin
+ * @copyright  2011 Rossiani Wijaya <rwijaya@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->dirroot . '/filter/mediaplugin/filter.php'); // Include the code to test
+
+/**
+ * Test cases for filter_mediaplugin class
+ */
+class filter_mediaplugin_test extends UnitTestCase {
+
+    function test_filter_mediaplugin_link() {
+        global $CFG;
+
+        // we need to enable the plugins somehow
+        $oldcfg = clone($CFG); // very, very ugly hack
+        $CFG->filter_mediaplugin_enable_mp3     = 1;
+        $CFG->filter_mediaplugin_enable_ogg     = 1;
+        $CFG->filter_mediaplugin_enable_ogv     = 1;
+        $CFG->filter_mediaplugin_enable_swf     = 1;
+        $CFG->filter_mediaplugin_enable_flv     = 1;
+        $CFG->filter_mediaplugin_enable_mov     = 1;
+        $CFG->filter_mediaplugin_enable_wmv     = 1;
+        $CFG->filter_mediaplugin_enable_mpg     = 1;
+        $CFG->filter_mediaplugin_enable_avi     = 1;
+        $CFG->filter_mediaplugin_enable_ram     = 1;
+        $CFG->filter_mediaplugin_enable_rpm     = 1;
+        $CFG->filter_mediaplugin_enable_rm      = 1;
+        $CFG->filter_mediaplugin_enable_youtube = 1;
+        $CFG->filter_mediaplugin_enable_img     = 1;
+
+
+        $filterplugin = new filter_mediaplugin(null, array());
+
+        $validtexts = array (
+                        '<a href="http://moodle.org/testfile/test.mp3">test mp3</a>',
+                        '<a href="http://moodle.org/testfile/test.ogg">test ogg</a>',
+                        '<a id="movie player" class="center" href="http://moodle.org/testfile/test.mpg">test mpg</a>',
+                        '<a href="http://moodle.org/testfile/test.ram">test</a>',
+                        '<a href="http://www.youtube.com/watch?v=JghQgA2HMX8" class="href=css">test file</a>',
+                        '<a class="youtube" href="http://www.youtube.com/watch?v=JghQgA2HMX8">test file</a>',
+                        '<a class="_blanktarget" href="http://moodle.org/testfile/test.flv?d=100x100">test flv</a>',
+                        '<a class="hrefcss" href="http://www.youtube.com/watch?v=JghQgA2HMX8">test file</a>',
+                        '<a href="http://www.moodle.org/logo.jpg"><img src="http://moodle.org/test.jpg" /></a>',
+                        '<a href="http://www.moodle.org/logo.rpm">rpm file</a>',
+                        '<a  class="content"     href="http://moodle.org/testfile/test.avi">test mp3</a>',
+                        '<a     id="audio"      href="http://moodle.org/testfile/test.mp3">test mp3</a>',
+                        '<a  href="http://moodle.org/testfile/test.mp3">test mp3</a>',
+                        '<a     href="http://moodle.org/testfile/test.mp3">test mp3</a>',
+                        '<a     href="http://www.youtube.com/watch?v=JghQgA2HMX8?d=200x200">youtube\'s</a>',
+                        '<a
+                            href="http://moodle.org/testfile/test.mp3">
+                            test mp3</a>',
+                        '<a                         class="content"
+
+
+                            href="http://moodle.org/testfile/test.avi">test mp3
+                                    </a>',
+                        '<a             href="http://www.youtube.com/watch?v=JghQgA2HMX8?d=200x200"     >youtube\'s</a>'
+                    );
+
+        //test for valid link
+        foreach ($validtexts as $text) {
+            $msg = "Testing text: ". $text;
+            $filter = $filterplugin->filter($text);
+            $this->assertNotEqual($text, $filter, $msg);
+        }
+
+        $invalidtexts = array(
+                            '<a class="_blanktarget">href="http://moodle.org/testfile/test.mp3"</a>',
+                            '<a>test test</a>',
+                            '<a >test test</a>',
+                            '<a     >test test</a>',
+                            '<a >test test</a>',
+                            '<ahref="http://moodle.org/testfile/test.mp3">sample</a>',
+                            '<a href="" test></a>',
+                            '<a class="_blanktarget" href="http://moodle.org/testfile/test.flv?d=100x">test flv</a>',
+                            '<a href="http://www.moodle.com/path/to?#param=29">test</a>',
+                            '<a href="http://moodle.org/testfile/test.mp3">test mp3',
+                            '<a href="http://moodle.org/testfile/test.mp3"test</a>',
+                            '<a href="http://moodle.org/testfile/">test</a>',
+                            '<a href="http://www.moodle.org/path/to/test.flv#param2=1?d=100x100">test</a>',
+                            '<href="http://moodle.org/testfile/test.avi">test</a>',
+                            '<a ahref="http://moodle.org/testfile/test.mp3">test mp3</a>',
+                            '<abbr href="http://moodle.org/testfile/test.mp3">test mp3</abbr>',
+                            '<ahref="http://moodle.org/testfile/test.mp3">test mp3</a>',
+                            '<a class="content"href="http://moodle.org/testfile/test.mp3">test mp3</a>',
+                            '<aclass="content" href="http://moodle.org/testfile/test.mp3">test mp3</a>'
+                        );
+
+        //test for invalid link
+        foreach ($invalidtexts as $text) {
+            $msg = "Testing text: ". $text;
+            $filter = $filterplugin->filter($text);
+            $this->assertEqual($text, $filter, $msg);
+        }
+
+        $CFG = $oldcfg; // very, very ugly hack
+    }
+}
index d4f2699..4a4896a 100644 (file)
@@ -415,7 +415,7 @@ if ($config->stage == INSTALL_DATABASE) {
 
     $disabled = empty($distro->dbhost) ? '' : 'disabled="disabled';
     echo '<div class="formrow"><label for="id_dbhost" class="formlabel">'.$strdbhost.'</label>';
-    echo '<input id="id_dbhost" name="dbhost" '.$disabled.' type="text" value="'.s($config->dbhost).'" size="30" class="forminput" />';
+    echo '<input id="id_dbhost" name="dbhost" '.$disabled.' type="text" value="'.s($config->dbhost).'" size="50" class="forminput" />';
     echo '</div>';
 
     echo '<div class="formrow"><label for="id_dbname" class="formlabel">'.$strdbname.'</label>';
@@ -552,15 +552,15 @@ if ($config->stage == INSTALL_PATHS) {
 
     echo '<div class="userinput">';
     echo '<div class="formrow"><label for="id_wwwroot" class="formlabel">'.$paths['wwwroot'].'</label>';
-    echo '<input id="id_wwwroot" name="wwwroot" type="text" value="'.s($CFG->wwwroot).'" disabled="disabled" size="45" class="forminput" />';
+    echo '<input id="id_wwwroot" name="wwwroot" type="text" value="'.s($CFG->wwwroot).'" disabled="disabled" size="70" class="forminput" />';
     echo '</div>';
 
     echo '<div class="formrow"><label for="id_dirroot" class="formlabel">'.$paths['dirroot'].'</label>';
-    echo '<input id="id_dirroot" name="dirroot" type="text" value="'.s($CFG->dirroot).'" disabled="disabled" size="45"class="forminput" />';
+    echo '<input id="id_dirroot" name="dirroot" type="text" value="'.s($CFG->dirroot).'" disabled="disabled" size="70"class="forminput" />';
     echo '</div>';
 
     echo '<div class="formrow"><label for="id_dataroot" class="formlabel">'.$paths['dataroot'].'</label>';
-    echo '<input id="id_dataroot" name="dataroot" type="text" value="'.s($config->dataroot).'" size="45" class="forminput" />';
+    echo '<input id="id_dataroot" name="dataroot" type="text" value="'.s($config->dataroot).'" size="70" class="forminput" />';
     if ($hint_dataroot !== '') {
         echo '<div class="hint">'.$hint_dataroot.'</div>';
     }
index beedc30..f06fce6 100644 (file)
@@ -62,8 +62,8 @@ $string['pathsroparentdataroot'] = 'Das Verzeichnis ({$a->parent}) ist schreibge
 $string['pathssubadmindir'] = 'Einige Webserver benutzen /admin als speziellen Link, um auf Einstellungsseiten oder Ähnliches zu verweisen. Unglücklicherweise kollidiert dies mit dem standardmäßigen Verzeichnis für die Moodle-Administration. Sie können dieses Problem beheben, indem Sie das Verzeichnis admin in Ihrer Moodle-Installation umbenennen und den neuen Namen hier eingeben (z.B. <em>moodleadmin</em>). Mit dieser Änderung werden alle Admin-Links korrigiert.';
 $string['pathssubdataroot'] = 'Sie benötigen einen Platz, wo Moodle hochgeladene Dateien abspeichern kann. Dieses Verzeichnis muss Lese- und Schreibrechte für das Nutzerkonto besitzen, mit dem Ihr Webservers läuft (üblicherweise \'nobody\', \'apache\' oder \'www\'). Außerdem sollte das Verzeichnis nicht direkt aus dem Internet erreichbar sein. Das Intallationsskript wird versuchen, ein solches Verzeichnis zu erstellen, falls es nicht existiert.</p>';
 $string['pathssubdirroot'] = 'Vollständiger Pfad der Moodle-Installation';
-$string['pathssubwwwroot'] = 'Vollständige Webadresse für den Zugriff auf Moodle. Es ist nicht möglich, auf Moodle über unterschiedliche Adressen zuzugreifen. Sollten Sie für Ihre Website mehrere öffentliche Adressen verwenden, so müssen Sie eine Adresse auswählen und für die übrigen Adressen dauerhafte Weiterleitungen einrichten. 
-<p>Falls Ihre Website gleichzeitig im Intranet und im Internet erreichbar ist, so tragen Sie hier die öffentliche Adresse ein. Konfigurieren Sie den DNS-Eintrag des Servers so, dass für alle Intranet-Nutzer ebenfalls die öffentliche Adresse erreichbar ist.
+$string['pathssubwwwroot'] = 'Vollständige Webadresse für den Zugriff auf Moodle. Es ist nicht möglich, über unterschiedliche Adressen auf Moodle zuzugreifen. Sollte Ihre Website mehrere öffentliche Adressen verwenden, so müssen Sie eine Adresse festlegen und für die übrigen Adressen dauerhafte Weiterleitungen dorthin einrichten. 
+<p>Falls Ihre Website gleichzeitig im Intranet und im Internet erreichbar ist, so tragen Sie die öffentliche Adresse ein. Konfigurieren Sie den DNS so, dass Moodle auch aus dem Intranet über die öffentliche Adresse erreichbar ist.
 <p>Führen Sie Ihre Moodle-Installation unbedingt mit der richtigen Adresse durch, weil es andernfalls zu Problemen kommen könnte.';
 $string['pathsunsecuredataroot'] = 'Der Speicherort des Verzeichnisses \'dataroot\' ist unsicher';
 $string['pathswrongadmindir'] = 'Das Admin-Verzeichnis existiert nicht';
index 87532ab..2fb9431 100644 (file)
@@ -41,6 +41,8 @@ $string['dataroot'] = 'Diretório de Dados';
 $string['dbprefix'] = 'Prefixo das tabelas';
 $string['dirroot'] = 'Diretório Moodle';
 $string['environmenthead'] = 'Verificando o ambiente ...';
+$string['environmentsub2'] = 'Cada release do Moodle requer uma versão mínima do PHP e diversas extensões do PHP.
+A verificação completa do ambiente é feita antes de cada instalação e atualização.';
 $string['errorsinenvironment'] = 'Verificação do Ambiente falhou!';
 $string['installation'] = 'Instalação';
 $string['langdownloaderror'] = 'Infelizmente o idioma "{$a}" não foi instalado. A instalação vai continuar em Inglês.';
index ce096ce..513be3c 100644 (file)
@@ -27,11 +27,11 @@ $string['accessdenied'] = 'Access denied';
 $string['accounts'] = 'Accounts';
 $string['additionalhtml'] = 'Additional HTML';
 $string['additionalhtml_heading'] = 'Additional HTML to be added to every page.';
-$string['additionalhtml_desc'] = 'These settings allow you to specify HTML that you want added to every page. You can set HTML that will be added within the HEAD tag for the page, immediatly after the BODY tag has been opened, or immediatly before the body tag is closed.<br />Doing this allows you add custom headers or footers on every page, or add support for services like Google Analytics very easily and independent of your chosen theme.';
+$string['additionalhtml_desc'] = 'These settings allow you to specify HTML that you want added to every page. You can set HTML that will be added within the HEAD tag for the page, immediately after the BODY tag has been opened, or immediately before the body tag is closed.<br />Doing this allows you add custom headers or footers on every page, or add support for services like Google Analytics very easily and independent of your chosen theme.';
 $string['additionalhtmlhead'] = 'Within HEAD';
 $string['additionalhtmlhead_desc'] = 'Content here will be added to the bottom of the HEAD tag for every page.';
 $string['additionalhtmltopofbody'] = 'When BODY is opened';
-$string['additionalhtmltopofbody_desc'] = 'Content here will be added in to every page immediatly after the opening body tag.';
+$string['additionalhtmltopofbody_desc'] = 'Content here will be added in to every page immediately after the opening body tag.';
 $string['additionalhtmlfooter'] = 'Before BODY is closed';
 $string['additionalhtmlfooter_desc'] = 'Content here will be added in to every page right before the body tag is closed.';
 $string['adminseesall'] = 'Admins see all';
index e36c126..f59fe2e 100755 (executable)
@@ -2352,6 +2352,10 @@ function get_context_info_array($contextid) {
  * @return int|bool related course id or false
  */
 function get_courseid_from_context($context) {
+    if (empty($context->contextlevel)) {
+        debugging('Invalid context object specified in get_courseid_from_context() call');
+        return false;
+    }
     if ($context->contextlevel == CONTEXT_COURSE) {
         return $context->instanceid;
     }
@@ -2370,7 +2374,7 @@ function get_courseid_from_context($context) {
     if ($context->contextlevel == CONTEXT_BLOCK) {
         $parentcontexts = get_parent_contexts($context, false);
         $parent = reset($parentcontexts);
-        return get_courseid_from_context($parent);
+        return get_courseid_from_context(get_context_instance_by_id($parent));
     }
 
     return false;
index 0e1aad1..3bd79d8 100644 (file)
@@ -4091,10 +4091,12 @@ WHERE gradeitemid IS NOT NULL AND grademax IS NOT NULL");
     }
 
     if ($oldversion < 2010061900.10) {
-        // migrate existing setup of meta courses
+        // migrate existing setup of meta courses, ignore records referencing invalid courses
         $sql = "INSERT INTO {enrol} (enrol, status, courseid, sortorder, customint1)
-                SELECT 'meta', 0, parent_course, 5, child_course
-                  FROM {course_meta}";
+                SELECT 'meta', 0, cm.parent_course, 5, cm.child_course
+                  FROM {course_meta} cm
+                  JOIN {course} p ON p.id = cm.parent_course
+                  JOIN {course} c ON c.id = cm.child_course";
         $DB->execute($sql);
 
         upgrade_main_savepoint(true, 2010061900.10);
@@ -6021,6 +6023,11 @@ WHERE gradeitemid IS NOT NULL AND grademax IS NOT NULL");
         upgrade_main_savepoint(true, 2011020200.01);
     }
 
+    if ($oldversion < 2011020900.07) {
+        $DB->delete_records('course_display', array('display' => 0));
+        upgrade_main_savepoint(true, 2011020900.07);
+    }
+
 
     return true;
 }
index 1961137..240a67b 100644 (file)
@@ -56,6 +56,8 @@ class postgres_sql_generator extends sql_generator {
     public $rename_key_sql = null; //SQL sentence to rename one key (PostgreSQL doesn't support this!)
                                           //TABLENAME, OLDKEYNAME, NEWKEYNAME are dynamically replaced
 
+    protected $strd_strings = null;  // '' or \' quotes
+
     /**
      * Reset a sequence to the id field of a table.
      * @param string $table name of table or xmldb_table object
@@ -404,6 +406,24 @@ class postgres_sql_generator extends sql_generator {
         return $results;
     }
 
+    public function addslashes($s) {
+        // Postgres is gradually switching to ANSY quotes, we need to check what is expected
+        if (!isset($this->std_strings)) {
+            $this->std_strings = ($this->mdb->get_field_sql("select setting from pg_settings where name = 'standard_conforming_strings'") === 'on');
+        }
+
+        if ($this->std_strings) {
+            $s = str_replace("'",  "''", $s);
+        } else {
+            // do not use php addslashes() because it depends on PHP quote settings!
+            $s = str_replace('\\','\\\\',$s);
+            $s = str_replace("\0","\\\0", $s);
+            $s = str_replace("'",  "\\'", $s);
+        }
+
+        return $s;
+    }
+
 /**
  * Given one xmldb_table returns one string with the sequence of the table
  * in the table (fetched from DB)
index c9064ad..b3c1ceb 100644 (file)
@@ -56,17 +56,23 @@ class mysqli_native_moodle_database extends moodle_database {
             throw new dml_exception('dbdriverproblem', $driverstatus);
         }
 
-        if (empty($this->dboptions['dbport'])) {
+        if (!empty($dboptions['dbsocket'])
+                and (strpos($dboptions['dbsocket'], '/') !== false or strpos($dboptions['dbsocket'], '\\') !== false)) {
+            $dbsocket = $dboptions['dbsocket'];
+        } else {
+            $dbsocket = ini_get('mysqli.default_socket');
+        }
+        if (empty($dboptions['dbport'])) {
             $dbport = (int)ini_get('mysqli.default_port');
         } else {
-            $dbport = (int)$this->dboptions['dbport'];
+            $dbport = (int)$dboptions['dbport'];
         }
         // verify ini.get does not return nonsense
         if (empty($dbport)) {
             $dbport = 3306;
         }
         ob_start();
-        $conn = new mysqli($dbhost, $dbuser, $dbpass, '', $dbport); /// Connect without db
+        $conn = new mysqli($dbhost, $dbuser, $dbpass, '', $dbport, $dbsocket); /// Connect without db
         $dberr = ob_get_contents();
         ob_end_clean();
         $errorno = @$conn->connect_errno;
index d932e87..ac6e42a 100644 (file)
@@ -771,7 +771,7 @@ class sqlsrv_native_moodle_database extends moodle_database {
      * @return string sql
      */
     private function limit_to_top_n($sql, $offset, $limit) {
-        // If there is no limit we can return immediatly
+        // If there is no limit we can return immediately
         if ($limit < 1 && $offset < 1) {
             return $sql;
         }
index adaaedc..6ef1fa3 100644 (file)
@@ -719,18 +719,26 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea
         return null;
     }
 
-    // relink embedded files if text submitted - no absolute links allowed in database!
-    if ($CFG->slasharguments) {
-        $draftbase = "$CFG->wwwroot/draftfile.php/$usercontext->id/user/draft/$draftitemid/";
-    } else {
-        $draftbase = "$CFG->wwwroot/draftfile.php?file=/$usercontext->id/user/draft/$draftitemid/";
+    $wwwroot = $CFG->wwwroot;
+    if ($forcehttps) {
+        $wwwroot = str_replace('http://', 'https://', $wwwroot);
     }
 
-    if ($forcehttps) {
-        $draftbase = str_replace('http://', 'https://', $draftbase);
+    // relink embedded files if text submitted - no absolute links allowed in database!
+    $text = str_ireplace("$wwwroot/draftfile.php/$usercontext->id/user/draft/$draftitemid/", '@@PLUGINFILE@@/', $text);
+
+    if (strpos($text, 'draftfile.php?file=') !== false) {
+        $matches = array();
+        preg_match_all("!$wwwroot/draftfile.php\?file=%2F{$usercontext->id}%2Fuser%2Fdraft%2F{$draftitemid}%2F[^'\",&<>|`\s:\\\\]+!iu", $text, $matches);
+        if ($matches) {
+            foreach ($matches[0] as $match) {
+                $replace = str_ireplace('%2F', '/', $match);
+                $text = str_replace($match, $replace, $text);
+            }
+        }
+        $text = str_ireplace("$wwwroot/draftfile.php?file=/$usercontext->id/user/draft/$draftitemid/", '@@PLUGINFILE@@/', $text);
     }
 
-    $text = str_ireplace($draftbase, '@@PLUGINFILE@@/', $text);
 
     return $text;
 }
@@ -1704,7 +1712,7 @@ function send_file($path, $filename, $lifetime = 'default' , $filter=0, $pathiss
                     $ranges = false;
                 }
                 if ($ranges) {
-                    $handle = fopen($filename, 'rb');
+                    $handle = fopen($path, 'rb');
                     byteserving_send_file($handle, $mimetype, $ranges, $filesize);
                 }
             }
diff --git a/lib/minify/MOODLE_README.txt b/lib/minify/MOODLE_README.txt
deleted file mode 100644 (file)
index e69de29..0000000
index 5db2e12..4ea33d1 100644 (file)
@@ -4,12 +4,13 @@
  * @package Minify
  */
 
+defined('MOODLE_INTERNAL') || die();
 
 /**
- * In 'debug' mode, Minify can combine files with no minification and 
- * add comments to indicate line #s of the original files. 
- * 
- * To allow debugging, set this option to true and add "&debug=1" to 
+ * In 'debug' mode, Minify can combine files with no minification and
+ * add comments to indicate line #s of the original files.
+ *
+ * To allow debugging, set this option to true and add "&debug=1" to
  * a URI. E.g. /min/?f=script1.js,script2.js&debug=1
  */
 $min_allowDebugFlag = ($CFG->debug);
@@ -20,7 +21,7 @@ $min_allowDebugFlag = ($CFG->debug);
  * Set to false for no error logging (Minify may be slightly faster).
  * @link http://www.firephp.org/
  *
- * If you want to use a custom error logger, set this to your logger 
+ * If you want to use a custom error logger, set this to your logger
  * instance. Your object should have a method log(string $message).
  *
  * @todo cache system does not have error logging yet.
@@ -29,10 +30,10 @@ $min_errorLogger = false;
 
 
 /**
- * Allow use of the Minify URI Builder app. If you no longer need 
+ * Allow use of the Minify URI Builder app. If you no longer need
  * this, set to false.
  **/
-$min_enableBuilder = true;
+$min_enableBuilder = false;
 
 
 /**
@@ -45,11 +46,11 @@ $min_cachePath = $CFG->dataroot.'/temp';
 /**
  * Leave an empty string to use PHP's $_SERVER['DOCUMENT_ROOT'].
  *
- * On some servers, this value may be misconfigured or missing. If so, set this 
+ * On some servers, this value may be misconfigured or missing. If so, set this
  * to your full document root path with no trailing slash.
  * E.g. '/home/accountname/public_html' or 'c:\\xampp\\htdocs'
  *
- * If /min/ is directly inside your document root, just uncomment the 
+ * If /min/ is directly inside your document root, just uncomment the
  * second line. The third line might work on some Apache servers.
  */
 $min_documentRoot = $CFG->dirroot.'/lib/minify';
@@ -58,7 +59,7 @@ $min_documentRoot = $CFG->dirroot.'/lib/minify';
 
 
 /**
- * Cache file locking. Set to false if filesystem is NFS. On at least one 
+ * Cache file locking. Set to false if filesystem is NFS. On at least one
  * NFS system flock-ing attempts stalled PHP for 30 seconds!
  */
 $min_cacheFileLocking = true;
@@ -67,9 +68,9 @@ $min_cacheFileLocking = true;
 /**
  * Combining multiple CSS files can place @import declarations after rules, which
  * is invalid. Minify will attempt to detect when this happens and place a
- * warning comment at the top of the CSS output. To resolve this you can either 
- * move the @imports within your CSS files, or enable this option, which will 
- * move all @imports to the top of the output. Note that moving @imports could 
+ * warning comment at the top of the CSS output. To resolve this you can either
+ * move the @imports within your CSS files, or enable this option, which will
+ * move all @imports to the top of the output. Note that moving @imports could
  * affect CSS values (which is why this option is disabled by default).
  */
 $min_serveOptions['bubbleCssImports'] = false;
@@ -92,8 +93,8 @@ $min_serveOptions['maxAge'] = 1800;
  * particular directories below DOCUMENT_ROOT, set this here.
  * You will still need to include the directory in the
  * f or b GET parameters.
- * 
- * // = shortcut for DOCUMENT_ROOT 
+ *
+ * // = shortcut for DOCUMENT_ROOT
  */
 //$min_serveOptions['minApp']['allowDirs'] = array('//js', '//css');
 
@@ -113,8 +114,8 @@ $min_serveOptions['minApp']['maxFiles'] = 10;
  * If you minify CSS files stored in symlink-ed directories, the URI rewriting
  * algorithm can fail. To prevent this, provide an array of link paths to
  * target paths, where the link paths are within the document root.
- * 
- * Because paths need to be normalized for this to work, use "//" to substitute 
+ *
+ * Because paths need to be normalized for this to work, use "//" to substitute
  * the doc root in the link paths (the array keys). E.g.:
  * <code>
  * array('//symlink' => '/real/target/path') // unix
@@ -126,17 +127,17 @@ $min_symlinks = array();
 
 /**
  * If you upload files from Windows to a non-Windows server, Windows may report
- * incorrect mtimes for the files. This may cause Minify to keep serving stale 
+ * incorrect mtimes for the files. This may cause Minify to keep serving stale
  * cache files when source file changes are made too frequently (e.g. more than
  * once an hour).
- * 
- * Immediately after modifying and uploading a file, use the touch command to 
+ *
+ * Immediately after modifying and uploading a file, use the touch command to
  * update the mtime on the server. If the mtime jumps ahead by a number of hours,
- * set this variable to that number. If the mtime moves back, this should not be 
+ * set this variable to that number. If the mtime moves back, this should not be
  * needed.
  *
- * In the Windows SFTP client WinSCP, there's an option that may fix this 
- * issue without changing the variable below. Under login > environment, 
+ * In the Windows SFTP client WinSCP, there's an option that may fix this
+ * issue without changing the variable below. Under login > environment,
  * select the option "Adjust remote timestamp with DST".
  * @link http://winscp.net/eng/docs/ui_login_environment#daylight_saving_time
  */
@@ -144,7 +145,7 @@ $min_uploaderHoursBehind = 0;
 
 
 /**
- * Path to Minify's lib folder. If you happen to move it, change 
+ * Path to Minify's lib folder. If you happen to move it, change
  * this accordingly.
  */
 $min_libPath = $CFG->libdir . '/minify/lib';
index c59449a..c9542bd 100644 (file)
@@ -3784,12 +3784,6 @@ function get_complete_user_data($field, $value, $mnethostid = null) {
 
 /// Get various settings and preferences
 
-    if ($displays = $DB->get_records('course_display', array('userid'=>$user->id))) {
-        foreach ($displays as $display) {
-            $user->display[$display->course] = $display->display;
-        }
-    }
-
     // preload preference cache
     check_user_preferences_loaded($user);
 
@@ -3808,18 +3802,23 @@ function get_complete_user_data($field, $value, $mnethostid = null) {
 
     // this is a special hack to speedup calendar display
     $user->groupmember = array();
-    if ($groups = $DB->get_records_sql($sql, array($user->id))) {
-        foreach ($groups as $group) {
-            if (!array_key_exists($group->courseid, $user->groupmember)) {
-                $user->groupmember[$group->courseid] = array();
+    if (!isguestuser($user)) {
+        if ($groups = $DB->get_records_sql($sql, array($user->id))) {
+            foreach ($groups as $group) {
+                if (!array_key_exists($group->courseid, $user->groupmember)) {
+                    $user->groupmember[$group->courseid] = array();
+                }
+                $user->groupmember[$group->courseid][$group->id] = $group->id;
             }
-            $user->groupmember[$group->courseid][$group->id] = $group->id;
         }
     }
 
 /// Add the custom profile fields to the user record
-    require_once($CFG->dirroot.'/user/profile/lib.php');
-    profile_load_custom_fields($user);
+    $user->profile = array();
+    if (!isguestuser($user)) {
+        require_once($CFG->dirroot.'/user/profile/lib.php');
+        profile_load_custom_fields($user);
+    }
 
 /// Rewrite some variables if necessary
     if (!empty($user->description)) {
index 1fbd58a..5376bed 100644 (file)
@@ -1023,7 +1023,7 @@ class global_navigation extends navigation_node {
                 $this->add_course_essentials($coursenode, $course);
                 // Load the course sections into the page
                 $sections = $this->load_course_sections($course, $coursenode);
-                if ($course->id !== SITEID) {
+                if ($course->id != SITEID) {
                     // Find the section for the $CM associated with the page and collect
                     // its section number.
                     if (isset($cm->sectionnum)) {
@@ -1105,7 +1105,7 @@ class global_navigation extends navigation_node {
         }
         // Load each extending user into the navigation.
         foreach ($this->extendforuser as $user) {
-            if ($user->id !== $USER->id) {
+            if ($user->id != $USER->id) {
                 $this->load_for_user($user);
             }
         }
@@ -1384,11 +1384,7 @@ class global_navigation extends navigation_node {
 
         $viewhiddensections = has_capability('moodle/course:viewhiddensections', $this->page->context);
 
-        if (isloggedin() && !isguestuser()) {
-            $activesection = $DB->get_field("course_display", "display", array("userid"=>$USER->id, "course"=>$course->id));
-        } else {
-            $activesection = null;
-        }
+        $activesection = course_get_display($course->id);
 
         $namingfunction = 'callback_'.$courseformat.'_get_section_name';
         $namingfunctionexists = (function_exists($namingfunction));
@@ -1418,7 +1414,7 @@ class global_navigation extends navigation_node {
                 $sectionnode = $coursenode->add($sectionname, $url, navigation_node::TYPE_SECTION, null, $section->id);
                 $sectionnode->nodetype = navigation_node::NODETYPE_BRANCH;
                 $sectionnode->hidden = (!$section->visible);
-                if ($this->page->context->contextlevel != CONTEXT_MODULE && ($sectionnode->isactive || ($activesection != null && $section->section == $activesection))) {
+                if ($this->page->context->contextlevel != CONTEXT_MODULE && ($sectionnode->isactive || ($activesection && $section->section == $activesection))) {
                     $sectionnode->force_open();
                     $this->load_section_activities($sectionnode, $section->section, $modinfo);
                 }
@@ -1517,7 +1513,7 @@ class global_navigation extends navigation_node {
      */
     protected function load_activity($cm, stdClass $course, navigation_node $activity) {
         global $CFG, $DB;
-        
+
         // make sure we have a $cm from get_fast_modinfo as this contains activity access details
         if (!($cm instanceof cm_info)) {
             $modinfo = get_fast_modinfo($course);
@@ -1569,7 +1565,7 @@ class global_navigation extends navigation_node {
         // Get the course set against the page, by default this will be the site
         $course = $this->page->course;
         $baseargs = array('id'=>$user->id);
-        if ($course->id !== SITEID && (!$iscurrentuser || $forceforcontext)) {
+        if ($course->id != SITEID && (!$iscurrentuser || $forceforcontext)) {
             if (array_key_exists($course->id, $this->mycourses)) {
                 $coursenode = $this->mycourses[$course->id]->coursenode;
             } else {
@@ -1857,9 +1853,15 @@ class global_navigation extends navigation_node {
      */
     public function add_course(stdClass $course, $forcegeneric = false) {
         global $CFG;
-        $canviewhidden = has_capability('moodle/course:viewhiddencourses', $this->page->context);
-        if ($course->id !== SITEID && !$canviewhidden && !$course->visible) {
-            return false;
+
+        if ($course->id != SITEID) {
+            if (!$course->visible) {
+                if (is_role_switched($course->id)) {
+                    // user has to be able to access course in order to switch, let's skip the visibility test here
+                } else if (!has_capability('moodle/course:viewhiddencourses', get_context_instance(CONTEXT_COURSE, $course->id))) {
+                    return false;
+                }
+            }
         }
 
         $issite = ($course->id == SITEID);
@@ -2984,7 +2986,7 @@ class settings_navigation extends navigation_node {
             $availableroles = get_switchable_roles($coursecontext);
             if (is_array($availableroles)) {
                 foreach ($availableroles as $key=>$role) {
-                    if ($assumedrole===(int)$key) {
+                    if ($assumedrole == (int)$key) {
                         continue;
                     }
                     $roles[$key] = $role;
index bbcad53..3231669 100644 (file)
@@ -2409,12 +2409,12 @@ EOD;
             return '';
         }
         if ($item->action instanceof action_link) {
-            //TODO: to be replaced with something else
             $link = $item->action;
             if ($item->hidden) {
                 $link->add_class('dimmed');
             }
-            $content = $this->output->render($link);
+            $link->text = $content.$link->text; // add help icon
+            $content = $this->render($link);
         } else if ($item->action instanceof moodle_url) {
             $attributes = array();
             if ($title !== '') {
index 7be9328..a9d5127 100644 (file)
@@ -37,7 +37,7 @@ defined('MOODLE_INTERNAL') || die();
  *
  * Typical usage would be
  * <pre>
- *     $PAGE->requires->init_js_call('M.mod_forum.init_view');
+ *     $PAGE->requires->js_init_call('M.mod_forum.init_view');
  * </pre>
  *
  * It also supports obsoleted coding style withouth YUI3 modules.
index f655068..f528082 100644 (file)
@@ -216,19 +216,8 @@ abstract class session_stub implements moodle_session {
         $user = null;
 
         if (!empty($CFG->opentogoogle) and !NO_MOODLE_COOKIES) {
-            if (!empty($_SERVER['HTTP_USER_AGENT'])) {
-                // allow web spiders in as guest users
-                if (strpos($_SERVER['HTTP_USER_AGENT'], 'Googlebot') !== false ) {
-                    $user = guest_user();
-                } else if (strpos($_SERVER['HTTP_USER_AGENT'], 'google.com') !== false ) { // Google
-                    $user = guest_user();
-                } else if (strpos($_SERVER['HTTP_USER_AGENT'], 'Yahoo! Slurp') !== false ) {  // Yahoo
-                    $user = guest_user();
-                } else if (strpos($_SERVER['HTTP_USER_AGENT'], '[ZSEBOT]') !== false ) {  // Zoomspider
-                    $user = guest_user();
-                } else if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSNBOT') !== false ) {  // MSN Search
-                    $user = guest_user();
-                }
+            if (is_web_crawler()) {
+                $user = guest_user();
             }
             if (!empty($CFG->guestloginbutton) and !$user and !empty($_SERVER['HTTP_REFERER'])) {
                 // automaticaly log in users coming from search engine results
index 46028a7..d86f1b8 100644 (file)
@@ -1123,6 +1123,38 @@ function init_eaccelerator() {
     return false;
 }
 
+/**
+ * Checks if current user is a web crawler.
+ *
+ * This list can not be made complete, this is not a security
+ * restriction, we make the list only to help these sites
+ * especially when automatic guest login is disabled.
+ *
+ * If admin needs security they should enable forcelogin
+ * and disable guest access!!
+ *
+ * @return bool
+ */
+function is_web_crawler() {
+    if (!empty($_SERVER['HTTP_USER_AGENT'])) {
+        if (strpos($_SERVER['HTTP_USER_AGENT'], 'Googlebot') !== false ) {
+            return true;
+        } else if (strpos($_SERVER['HTTP_USER_AGENT'], 'google.com') !== false ) { // Google
+            return true;
+        } else if (strpos($_SERVER['HTTP_USER_AGENT'], 'Yahoo! Slurp') !== false ) {  // Yahoo
+            return true;
+        } else if (strpos($_SERVER['HTTP_USER_AGENT'], '[ZSEBOT]') !== false ) {  // Zoomspider
+            return true;
+        } else if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSNBOT') !== false ) {  // MSN Search
+            return true;
+        } else if (strpos($_SERVER['HTTP_USER_AGENT'], 'Yandex') !== false ) {
+            return true;
+        } else if (strpos($_SERVER['HTTP_USER_AGENT'], 'AltaVista') !== false ) {
+            return true;
+        }
+    }
+    return false;
+}
 
 /**
  * This class solves the problem of how to initialise $OUTPUT.
index 69b13a4..15ea95c 100644 (file)
@@ -1967,7 +1967,7 @@ function get_separator() {
  * @return string|void If $return is false, returns nothing, otherwise returns a string of HTML.
  */
 function print_collapsible_region($contents, $classes, $id, $caption, $userpref = '', $default = false, $return = false) {
-    $output  = print_collapsible_region_start($classes, $id, $caption, $userpref, true, true);
+    $output  = print_collapsible_region_start($classes, $id, $caption, $userpref, $default, true);
     $output .= $contents;
     $output .= print_collapsible_region_end(true);
 
@@ -1983,21 +1983,20 @@ function print_collapsible_region($contents, $classes, $id, $caption, $userpref
  * be clicked to expand or collapse the region. If JavaScript is off, then the region
  * will always be expanded.
  *
- * @global object
  * @param string $classes class names added to the div that is output.
  * @param string $id id added to the div that is output. Must not be blank.
  * @param string $caption text displayed at the top. Clicking on this will cause the region to expand or contract.
- * @param boolean $userpref the name of the user preference that stores the user's preferred default state.
+ * @param string $userpref the name of the user preference that stores the user's preferred default state.
  *      (May be blank if you do not wish the state to be persisted.
  * @param boolean $default Initial collapsed state to use if the user_preference it not set.
  * @param boolean $return if true, return the HTML as a string, rather than printing it.
  * @return string|void if $return is false, returns nothing, otherwise returns a string of HTML.
  */
-function print_collapsible_region_start($classes, $id, $caption, $userpref = false, $default = false, $return = false) {
+function print_collapsible_region_start($classes, $id, $caption, $userpref = '', $default = false, $return = false) {
     global $CFG, $PAGE, $OUTPUT;
 
     // Work out the initial state.
-    if (is_string($userpref)) {
+    if (!empty($userpref) and is_string($userpref)) {
         user_preference_allow_ajax_update($userpref, PARAM_BOOL);
         $collapsed = get_user_preferences($userpref, $default);
     } else {
index 53892cb..b0791ed 100644 (file)
@@ -182,7 +182,7 @@ if ($frm and isset($frm->username)) {                             // Login WITH
             $urltogo = $CFG->wwwroot.'/user/edit.php';
             // We don't delete $SESSION->wantsurl yet, so we get there later
 
-        } else if (isset($SESSION->wantsurl) and (strpos($SESSION->wantsurl, $CFG->wwwroot) === 0)) {
+        } else if (isset($SESSION->wantsurl) and (strpos($SESSION->wantsurl, $CFG->wwwroot) === 0 or strpos($SESSION->wantsurl, str_replace('http://', 'https://', $CFG->wwwroot)) === 0)) {
             $urltogo = $SESSION->wantsurl;    /// Because it's an address in this site
             unset($SESSION->wantsurl);
 
index 61bf349..3bd234e 100644 (file)
@@ -55,7 +55,7 @@ class mod_data_export_form extends moodleform {
             }
         }
         $this->add_checkbox_controller(1, null, null, 1);
-        $this->add_action_buttons(true, get_string('exportdatabaserecords', 'data'));
+        $this->add_action_buttons(true, get_string('exportentries', 'data'));
     }
 
 }
index 346c54f..3110490 100755 (executable)
@@ -48,28 +48,16 @@ if ($fieldenclosure !== '') {
 if ($id) {
     $url->param('id', $id);
     $PAGE->set_url($url);
-    if (! $cm = get_coursemodule_from_id('data', $id)) {
-        print_error('invalidcoursemodule');
-    }
-    if (! $course = $DB->get_record('course', array('id'=>$cm->course))) {
-        print_error('coursemisconf');
-    }
-    if (! $data = $DB->get_record('data', array('id'=>$cm->instance))) {
-        print_error('invalidcoursemodule');
-    }
+    $cm     = get_coursemodule_from_id('data', $id, 0, false, MUST_EXIST);
+    $course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST);
+    $data   = $DB->get_record('data', array('id'=>$cm->instance), '*', MUST_EXIST);
 
 } else {
     $url->param('d', $d);
     $PAGE->set_url($url);
-    if (! $data = $DB->get_record('data', array('id'=>$d))) {
-        print_error('invalidid', 'data');
-    }
-    if (! $course = $DB->get_record('course', array('id'=>$data->course))) {
-        print_error('coursemisconf');
-    }
-    if (! $cm = get_coursemodule_from_instance('data', $data->id, $course->id)) {
-        print_error('coursemisconf');
-    }
+    $data   = $DB->get_record('data', array('id'=>$d), '*', MUST_EXIST);
+    $course = $DB->get_record('course', array('id'=>$data->course), '*', MUST_EXIST);
+    $cm     = get_coursemodule_from_instance('data', $data->id, $course->id, false, MUST_EXIST);
 }
 
 require_login($course, false, $cm);
@@ -82,8 +70,9 @@ $form = new mod_data_import_form(new moodle_url('/mod/data/import.php'));
 $PAGE->navbar->add(get_string('add', 'data'));
 $PAGE->set_title($data->name);
 $PAGE->set_heading($course->fullname);
+navigation_node::override_active_url(new moodle_url('/mod/data/import.php', array('d' => $data->id)));
 echo $OUTPUT->header();
-echo $OUTPUT->heading(format_string($data->name));
+echo $OUTPUT->heading_with_help(get_string('uploadrecords', 'mod_data'), 'uploadrecords', 'mod_data');
 
 /// Groups needed for Add entry tab
 $currentgroup = groups_get_activity_group($cm);
@@ -93,7 +82,6 @@ if (!$formdata = $form->get_data()) {
     /// Upload records section. Only for teachers and the admin.
     echo $OUTPUT->box_start('generalbox boxaligncenter boxwidthwide');
     require_once('import_form.php');
-    echo $OUTPUT->heading(get_string('uploadrecords', 'data'), 3);
     $form = new mod_data_import_form(new moodle_url('/mod/data/import.php'));
     $formdata = new stdClass();
     $formdata->d = $data->id;
index 351b143..b8d029f 100755 (executable)
@@ -122,8 +122,8 @@ $string['excel'] = 'Excel';
 $string['export'] = 'Export';
 $string['exportaszip'] = 'Export as zip';
 $string['exportaszip_help'] = 'The export as zip feature allows you to save the templates and fields as a preset zip for download. The zip may then be imported to another course.';
-$string['exportdatabaserecords'] = 'Export database records';
 $string['exportedtozip'] = 'Exported to temporary zip...';
+$string['exportentries'] = 'Export entries';
 $string['exportownentries'] = 'Export your own entries only? ({$a->mine}/{$a->all})';
 $string['failedpresetdelete'] = 'Error deleting a preset!';
 $string['fieldadded'] = 'Field added';
@@ -170,6 +170,7 @@ $string['chooseexportfields'] = 'Choose the fields you wish to export:';
 $string['chooseexportformat'] = 'Choose the format you wish to export to:';
 $string['chooseorupload'] = 'Choose file';
 $string['expired'] = 'Sorry, this activity closed on {$a} and is no longer available';
+$string['importentries'] = 'Import entries';
 $string['importsuccess'] = 'The preset has been successfully applied.';
 $string['insufficiententries'] = 'more entries needed to view this database';
 $string['intro'] = 'Introduction';
@@ -307,6 +308,14 @@ $string['unsupportedexport'] = '({$a->fieldtype}) cannot be exported.';
 $string['updatefield'] = 'Update an existing field';
 $string['uploadfile'] = 'Upload file';
 $string['uploadrecords'] = 'Upload entries from a file';
+$string['uploadrecords_help'] = 'Entries may be uploaded via text file. The format of the file should be as follows:
+
+* Each line of the file contains one record
+* Each record is a series of data separated by commas (or other delimiters)
+* The first record contains a list of fieldnames defining the format of the rest of the file
+
+The field enclosure is a character that surrounds each field in each record. It can normally be left unset.';
+$string['uploadrecords_link'] = 'mod/data/import';
 $string['url'] = 'Url';
 $string['usestandard'] = 'Use a preset';
 $string['usestandard_help'] = 'To use a preset available to the whole site, select it from the list. (If you have added a preset to the list using the save as preset feature then you have the option of deleting it.)';
index 534e424..6c02c04 100755 (executable)
@@ -2848,10 +2848,10 @@ function data_extend_settings_navigation(settings_navigation $settings, navigati
     if (has_capability(DATA_CAP_EXPORT, $PAGE->cm->context)) {
         // The capability required to Export database records is centrally defined in 'lib.php'
         // and should be weaker than those required to edit Templates, Fields and Presets.
-        $datanode->add(get_string('export', 'data'), new moodle_url('/mod/data/export.php', array('d'=>$data->id)));
+        $datanode->add(get_string('exportentries', 'data'), new moodle_url('/mod/data/export.php', array('d'=>$data->id)));
     }
     if (has_capability('mod/data:manageentries', $PAGE->cm->context)) {
-        $datanode->add(get_string('import'), new moodle_url('/mod/data/import.php', array('d'=>$data->id)));
+        $datanode->add(get_string('importentries', 'data'), new moodle_url('/mod/data/import.php', array('d'=>$data->id)));
     }
 
     if (has_capability('mod/data:managetemplates', $PAGE->cm->context)) {
index cf69cb7..a32d74b 100644 (file)
@@ -1812,7 +1812,7 @@ function forum_get_readable_forums($userid, $courseid=0) {
     } else {
         // If no course is specified, then the user can see SITE + his courses.
         $courses1 = $DB->get_records('course', array('id' => SITEID));
-        $courses2 = enrol_get_users_courses($userid, true);
+        $courses2 = enrol_get_users_courses($userid, true, array('modinfo'));
         $courses = array_merge($courses1, $courses2);
     }
     if (!$courses) {
@@ -1929,8 +1929,8 @@ function forum_search_posts($searchterms, $courseid=0, $limitfrom=0, $limitnum=5
         $select = array();
 
         if (!$forum->viewhiddentimedposts) {
-            $select[] = "(d.userid = :userid OR (d.timestart < : AND (d.timeend = 0 OR d.timeend > :timeend)))";
-            $params = array('userid'=>$USER->id, 'timestart'=>$now, 'timeend'=>$now);
+            $select[] = "(d.userid = :userid{$forumid} OR (d.timestart < :timestart{$forumid} AND (d.timeend = 0 OR d.timeend > :timeend{$forumid})))";
+            $params = array_merge($params, array('userid'.$forumid=>$USER->id, 'timestart'.$forumid=>$now, 'timeend'.$forumid=>$now));
         }
 
         $cm = $forum->cm;
@@ -1939,7 +1939,7 @@ function forum_search_posts($searchterms, $courseid=0, $limitfrom=0, $limitnum=5
         if ($forum->type == 'qanda'
             && !has_capability('mod/forum:viewqandawithoutposting', $context)) {
             if (!empty($forum->onlydiscussions)) {
-                list($discussionid_sql, $discussionid_params) = $DB->get_in_or_equal($forum->onlydiscussions, SQL_PARAMS_NAMED, 'qanda0');
+                list($discussionid_sql, $discussionid_params) = $DB->get_in_or_equal($forum->onlydiscussions, SQL_PARAMS_NAMED, 'qanda'.$forumid.'_0000');
                 $params = array_merge($params, $discussionid_params);
                 $select[] = "(d.id $discussionid_sql OR p.parent = 0)";
             } else {
@@ -1948,15 +1948,15 @@ function forum_search_posts($searchterms, $courseid=0, $limitfrom=0, $limitnum=5
         }
 
         if (!empty($forum->onlygroups)) {
-            list($groupid_sql, $groupid_params) = $DB->get_in_or_equal($forum->onlygroups, SQL_PARAMS_NAMED, 'grps0');
+            list($groupid_sql, $groupid_params) = $DB->get_in_or_equal($forum->onlygroups, SQL_PARAMS_NAMED, 'grps'.$forumid.'_0000');
             $params = array_merge($params, $groupid_params);
             $select[] = "d.groupid $groupid_sql";
         }
 
         if ($select) {
             $selects = implode(" AND ", $select);
-            $where[] = "(d.forum = :forum AND $selects)";
-            $params['forum'] = $forumid;
+            $where[] = "(d.forum = :forum{$forumid} AND $selects)";
+            $params['forum'.$forumid] = $forumid;
         } else {
             $fullaccess[] = $forumid;
         }
index 6a03912..6576056 100644 (file)
@@ -106,11 +106,10 @@ switch ($mode) {
 echo '<div class="user-content">';
 
 if ($course->id == SITEID) {
-    if (empty($CFG->forceloginforprofiles) || isloggedin()) {
+    $searchcourse = SITEID;
+    if (empty($CFG->forceloginforprofiles) or (isloggedin() and !isguestuser() and !is_web_crawler())) {
         // Search throughout the whole site.
         $searchcourse = 0;
-    } else {
-        $searchcourse = SITEID;
     }
 } else {
     // Search only for posts the user made in this course.
index 0ef2a32..7a9b5e1 100644 (file)
@@ -202,7 +202,7 @@ class quiz_overview_report extends quiz_default_report {
         if (!$nostudents || ($attemptsmode == QUIZ_REPORT_ATTEMPTS_ALL)) {
 
             // Construct the SQL
-            $fields = $DB->sql_concat('u.id', '\'#\'', 'COALESCE(qa.attempt, \'0\')').' AS uniqueid, ';
+            $fields = $DB->sql_concat('u.id', '\'#\'', 'COALESCE(qa.attempt, 0)').' AS uniqueid, ';
             if ($qmsubselect) {
                 $fields .=
                     "(CASE " .
index b73ccfd..01662ff 100644 (file)
@@ -185,7 +185,7 @@ class quiz_responses_report extends quiz_default_report {
             $hasfeedback = quiz_has_feedback($quiz);
 
             // Construct the SQL
-            $fields = $DB->sql_concat('u.id', '\'#\'', 'COALESCE(qa.attempt, \'0\')').' AS concattedid, ';
+            $fields = $DB->sql_concat('u.id', '\'#\'', 'COALESCE(qa.attempt, 0)').' AS concattedid, ';
             if ($qmsubselect) {
                 $fields .=
                     "(CASE " .
index 7c5b745..36bf82c 100644 (file)
@@ -15,7 +15,7 @@ M.core_question_engine.init_form = function(Y, form) {
     Y.one(form).setAttribute('autocomplete', 'off');
     Y.on('key', function (e) {
         if (!e.target.test('a') && !e.target.test('input[type=submit]') &&
-                !e.target.test('input[type=img]')) {
+                !e.target.test('input[type=img]') && !e.target.test('textarea')) {
             e.preventDefault();
         }
     }, form, 'press:13');
index 5d83737..ebc37b8 100644 (file)
@@ -1044,7 +1044,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
         $penaltygrp = array();
         $penaltygrp[] =& $mform->createElement('text', 'unitpenalty', get_string('unitpenalty', 'qtype_numerical') ,
                 array('size' => 6));
-        $unitgradingtypes = array('1' => get_string('decfractionofquestiongrade', 'qtype_numerical'), '2' => get_string('decfractionofresponsegrade', 'qtype_numerical'));
+        $unitgradingtypes = array('1' => get_string('decfractionofresponsegrade', 'qtype_numerical'), '2' => get_string('decfractionofquestiongrade', 'qtype_numerical'));
         $penaltygrp[] =& $mform->createElement('select', 'unitgradingtypes', '' , $unitgradingtypes );
         $mform->addGroup($penaltygrp, 'penaltygrp', get_string('unitpenalty', 'qtype_numerical'),' ' , false);
         $multichoicedisplaygrp = array();
@@ -1151,6 +1151,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
                         break;
                     case 2 : // NUMERICALQUESTIONUNITTEXTDISPLAY
                         $default_values['unitrole'] = 1 ;
+                        break;
                     case 3 : // NUMERICALQUESTIONUNITNODISPLAY
                         $default_values['unitrole'] = 0 ;
                         //  $default_values['showunits1'] = $question->options->showunits ;
index 331529d..a1a2cb7 100644 (file)
@@ -141,10 +141,10 @@ $aggregatetoreturn = round($items[0]->rating->aggregate,1);
 // Output a dash if aggregation method == COUNT as the count is output next to the aggregate anyway
 if ($items[0]->rating->settings->aggregationmethod==RATING_AGGREGATE_COUNT or $items[0]->rating->count == 0) {
     $aggregatetoreturn = ' - ';
-} else if($rating->scaleid < 0) { //if its non-numeric scale
+} else if($items[0]->rating->settings->scale->id < 0) { //if its non-numeric scale
     //dont use the scale item if the aggregation method is sum as adding items from a custom scale makes no sense
     if ($items[0]->rating->settings->aggregationmethod!= RATING_AGGREGATE_SUM) {
-        $scalerecord = $DB->get_record('scale', array('id' => -$rating->scaleid));
+        $scalerecord = $DB->get_record('scale', array('id' => -$items[0]->rating->settings->scale->id));
         if ($scalerecord) {
             $scalearray = explode(',', $scalerecord->scale);
             $aggregatetoreturn = $scalearray[$aggregatetoreturn-1];
index 0edc42c..3619d4f 100755 (executable)
@@ -105,7 +105,21 @@ class repository_upload extends repository {
         if (empty($saveas_filename)) {
             $record->filename = clean_param($_FILES[$elname]['name'], PARAM_FILE);
         } else {
-            $record->filename = $saveas_filename;
+            $ext = '';
+            $match = array();
+            $filename = clean_param($_FILES[$elname]['name'], PARAM_FILE);
+            if (preg_match('/\.([a-z0-9]+)$/i', $filename, $match)) {
+                if (isset($match[1])) {
+                    $ext = $match[1];
+                }
+            }
+            $ext = !empty($ext) ? $ext : '';
+            if (preg_match('#\.(' . $ext . ')$#i', $saveas_filename)) {
+                // saveas filename contains file extension already
+                $record->filename = $saveas_filename;
+            } else {
+                $record->filename = $saveas_filename . '.' . $ext;
+            }
         }
 
         if ($this->mimetypes != '*') {
index 2228465..464638a 100644 (file)
@@ -93,18 +93,18 @@ foreach ($parts as $part) {
 
     if ($mimetype === 'text/css') {
         if ($version == 'moodle') {
-            $filecontent = preg_replace('/([a-z_-]+)\.(png|gif)/', 'yui_image.php?file='.$version.'/'.$frankenstyle.'/'.array_shift($bits).'/$1.$2', $filecontent);
+            $filecontent = preg_replace('/([a-z0-9_-]+)\.(png|gif)/', 'yui_image.php?file='.$version.'/'.$frankenstyle.'/'.array_shift($bits).'/$1.$2', $filecontent);
         } else if ($version == 'gallery') {
             // search for all images in gallery module CSS and serve them through the yui_image.php script
-            $filecontent = preg_replace('/([a-z_-]+)\.(png|gif)/', 'yui_image.php?file='.$version.'/'.$bits[0].'/'.$bits[1].'/$1.$2', $filecontent);
+            $filecontent = preg_replace('/([a-z0-9_-]+)\.(png|gif)/', 'yui_image.php?file='.$version.'/'.$bits[0].'/'.$bits[1].'/$1.$2', $filecontent);
         } else {
             // First we need to remove relative paths to images. These are used by YUI modules to make use of global assets.
             // I've added this as a separate regex so it can be easily removed once
             // YUI standardise there CSS methods
-            $filecontent = preg_replace('#(\.\./\.\./\.\./\.\./assets/skins/sam/)?([a-z_-]+)\.(png|gif)#', '$2.$3', $filecontent);
+            $filecontent = preg_replace('#(\.\./\.\./\.\./\.\./assets/skins/sam/)?([a-z0-9_-]+)\.(png|gif)#', '$2.$3', $filecontent);
 
             // search for all images in yui2 CSS and serve them through the yui_image.php script
-            $filecontent = preg_replace('/([a-z_-]+)\.(png|gif)/', 'yui_image.php?file='.$version.'/$1.$2', $filecontent);
+            $filecontent = preg_replace('/([a-z0-9_-]+)\.(png|gif)/', 'yui_image.php?file='.$version.'/$1.$2', $filecontent);
         }
     }
 
index da41cb3..a373051 100644 (file)
@@ -42,9 +42,12 @@ 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
 
+$PAGE->set_url('/user/profile.php', array('id'=>$userid));
+
 if (!empty($CFG->forceloginforprofiles)) {
     require_login();
     if (isguestuser()) {
+        $SESSION->wantsurl = $PAGE->url->out(false);
         redirect(get_login_url());
     }
 } else if (!empty($CFG->forcelogin)) {
@@ -106,8 +109,6 @@ if (has_capability('moodle/user:viewhiddendetails', $context)) {
 // Start setting up the page
 $strpublicprofile = get_string('publicprofile');
 
-$params = array('id'=>$userid);
-$PAGE->set_url('/user/profile.php', $params);
 $PAGE->blocks->add_region('content');
 $PAGE->set_subpage($currentpage->id);
 $PAGE->set_title(fullname($user).": $strpublicprofile");
index e70df1c..1cd701b 100644 (file)
@@ -40,8 +40,7 @@ if ($courseid == SITEID) {   // Since Moodle 2.0 all site-level profiles are sho
     redirect($CFG->wwwroot.'/user/profile.php?id='.$id);  // Immediate redirect
 }
 
-$url = new moodle_url('/user/view.php', array('id'=>$id,'course'=>$courseid));
-$PAGE->set_url($url);
+$PAGE->set_url('/user/view.php', array('id'=>$id,'course'=>$courseid));
 
 $user = $DB->get_record('user', array('id'=>$id), '*', MUST_EXIST);
 $course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
@@ -57,6 +56,14 @@ if (isguestuser($user)) {
     print_error('invaliduserid');
 }
 
+if (!empty($CFG->forceloginforprofiles)) {
+    require_login(); // we can not log in to course due to the parent hack bellow
+    if (isguestuser()) {
+        $SESSION->wantsurl = $PAGE->url->out(false);
+        redirect(get_login_url());
+    }
+}
+
 $PAGE->set_context($coursecontext);
 $PAGE->set_course($course);
 $PAGE->set_pagetype('course-view-' . $course->format);  // To get the blocks exactly like the course
@@ -76,7 +83,7 @@ if (!$currentuser
 } else {
     // normal course
     require_login($course);
-    // what to do with users temporary accessing this course? shoudl they see the details?
+    // what to do with users temporary accessing this course? should they see the details?
 }
 
 $strpersonalprofile = get_string('personalprofile');
index bb4daa9..ab374d9 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version = 2011020900;  // YYYYMMDD   = date of the last version bump
+$version = 2011020900.07;  // YYYYMMDD   = date of the last version bump
                         //         XX = daily increments
 
 $release = '2.0.1+ (Build: 20110209)';  // Human-friendly version name