Merge branch 'mdl-26299' of git://github.com/mackensen/moodle
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 14 Feb 2011 17:23:56 +0000 (18:23 +0100)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 14 Feb 2011 17:23:56 +0000 (18:23 +0100)
104 files changed:
admin/cli/automated_backups.php
admin/report/courseoverview/index.php
admin/settings/server.php
admin/uploaduser.php
auth/shibboleth/auth.php
backup/util/helper/backup_cron_helper.class.php
blocks/moodleblock.class.php
blocks/news_items/block_news_items.php
blocks/online_users/block_online_users.php
blog/rsslib.php
course/format/topics/format.php
course/format/weeks/format.php
course/lib.php
course/report/completion/index.php
course/view.php
enrol/authorize/lang/en/enrol_authorize.php
enrol/database/settings.php
enrol/ldap/settings.php
enrol/renderer.php
filter/mediaplugin/filter.php
filter/mediaplugin/simpletest/testfiltermediaplugin.php [new file with mode: 0644]
group/import.php
group/import_form.php
group/index.php
install.php
install/lang/ca/admin.php
install/lang/de/install.php
install/lang/pl/install.php
install/lang/pt_br/install.php
install/lang/sv/admin.php
lang/en/admin.php
lang/en/dbtransfer.php
lang/en/edufields.php
lang/en/grades.php
lang/en/group.php
lang/en/hub.php
lang/en/moodle.php
lib/accesslib.php
lib/db/install.xml
lib/db/upgrade.php
lib/ddl/oracle_sql_generator.php
lib/ddl/postgres_sql_generator.php
lib/dml/mysqli_native_moodle_database.php
lib/dml/simpletest/testdml.php
lib/dml/sqlsrv_native_moodle_database.php
lib/dml/sqlsrv_native_moodle_recordset.php
lib/filelib.php
lib/minify/MOODLE_README.txt [deleted file]
lib/minify/config.php
lib/modinfolib.php
lib/moodlelib.php
lib/navigationlib.php
lib/outputrenderers.php
lib/outputrequirementslib.php
lib/pagelib.php
lib/sessionlib.php
lib/setuplib.php
lib/textlib.class.php
lib/upgradelib.php
lib/weblib.php
login/index.php
mod/chat/gui_basic/index.php
mod/chat/gui_header_js/index.php
mod/chat/gui_sockets/index.php
mod/data/export_form.php
mod/data/import.php
mod/data/lang/en/data.php
mod/data/lib.php
mod/data/rsslib.php
mod/data/templates.php
mod/data/view.php
mod/feedback/lang/en/feedback.php
mod/forum/lib.php
mod/forum/rsslib.php
mod/forum/user.php
mod/glossary/rsslib.php
mod/glossary/view.php
mod/lesson/editpage.php
mod/quiz/report/overview/overview_table.php
mod/resource/lang/en/resource.php
mod/wiki/lang/en/wiki.php
mod/workshop/allocation/manual/lib.php
mod/workshop/allocation/manual/styles.css
mod/workshop/allocation/random/lib.php
mod/workshop/allocation/random/settings_form.php
mod/workshop/lib.php
rating/rate_ajax.php
repository/boxnet/lang/en/repository_boxnet.php
repository/dropbox/lang/en/repository_dropbox.php
repository/flickr_public/lang/en/repository_flickr_public.php
repository/merlot/lang/en/repository_merlot.php
repository/upload/lib.php
repository/url/lang/en/repository_url.php
tag/lib.php
theme/splash/lang/en/theme_splash.php
theme/splash/style/blue.css
theme/splash/style/green.css
theme/yui_combo.php
user/filters/courserole.php
user/portfolio.php
user/portfoliologs.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 da91b61..21d980f 100644 (file)
@@ -8,9 +8,6 @@
     $time       = optional_param('time', 0, PARAM_INT);
     $numcourses = optional_param('numcourses', 20, PARAM_INT);
 
-    admin_externalpage_setup('reportcourseoverview');
-    echo $OUTPUT->header();
-
     if (empty($CFG->enablestats)) {
         if (has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) {
             redirect("$CFG->wwwroot/$CFG->admin/settings.php?section=stats", get_string('mustenablestats', 'admin'), 3);
@@ -19,6 +16,9 @@
         }
     }
 
+    admin_externalpage_setup('reportcourseoverview');
+    echo $OUTPUT->header();
+
     $course = get_site();
     stats_check_uptodate($course->id);
 
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 605a53d..5ee0e8a 100755 (executable)
@@ -295,7 +295,13 @@ if ($formdata = $mform->is_cancelled()) {
             }
             if (isset($formdata->$field)) {
                 // process templates
-                $user->$field = process_template($formdata->$field, $user);
+                if (is_array($formdata->$field)) {
+                    foreach ($formdata->$field as $k=>$v) {
+                        $user->$field[$k] = process_template($v, $user);
+                    }
+                } else {
+                    $user->$field = process_template($formdata->$field, $user);
+                }
             }
         }
 
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 49c788c..6fcd152 100644 (file)
@@ -110,7 +110,8 @@ class block_news_items extends block_base {
                 } else {
                     $userid = $USER->id;
                 }
-                $this->content->footer .= '<br />'.rss_get_link($this->page->context->id, $userid, 'mod_forum', $forum->id, $tooltiptext);
+
+                $this->content->footer .= '<br />'.rss_get_link($context->id, $userid, 'mod_forum', $forum->id, $tooltiptext);
             }
 
         }
index 4fb8972..622f96b 100644 (file)
@@ -54,7 +54,7 @@ class block_online_users extends block_base {
 
         $userfields = user_picture::fields('u', array('username'));
 
-        if ($this->page->course->id == SITEID) {  // Site-level
+        if ($this->page->course->id == SITEID or $this->page->context->contextlevel < CONTEXT_COURSE) {  // Site-level
             $sql = "SELECT $userfields, MAX(u.lastaccess) AS lastaccess
                       FROM {user} u $groupmembers
                      WHERE u.lastaccess > $timefrom
index 70a723a..3fea97f 100755 (executable)
@@ -191,7 +191,7 @@ function blog_rss_get_feed($context, $args) {
             $info = $SITE->fullname;
             break;
         case 'group':
-            $group = groups_get_group($id, false);
+            $group = groups_get_group($id);
             $info = $group->name; //TODO: $DB->get_field('groups', 'name', array('id'=>$id))
             break;
         default:
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..cb7aab6 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='.$activity->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 edd077c..c24a38e 100644 (file)
@@ -197,7 +197,7 @@ You have to accept or deny payments manually because of the admin hasn\'t enable
 
 {$a->url}';
 $string['pendingorderssubject'] = 'WARNING: {$a->course}, {$a->pending} order(s) will expire within {$a->days} day(s).';
-$string['pluginname'] = 'Authorize.net';
+$string['pluginname'] = 'Authorize.Net';
 $string['reason11'] = 'A duplicate transaction has been submitted.';
 $string['reason13'] = 'The merchant Login ID is invalid or the account is inactive.';
 $string['reason16'] = 'The transaction was not found.';
@@ -254,14 +254,13 @@ You may view your payment details or edit your profile:
  {$a->profileurl}';
 $string['youcantdo'] = 'You can\'t do this action: {$a->action}';
 $string['zipcode'] = 'Zip Code';
-$string['pluginname'] = 'Authorize';
 $string['cost'] = 'Cost';
 $string['currency'] = 'Currency';
 $string['enrolperiod'] = 'Enrolment period';
 $string['enrolstartdate'] = 'Start date';
 $string['enrolenddate'] = 'End date';
 $string['enrolenddaterror'] = 'Enrolment end date cannot be earlier than start date';
-$string['status'] = 'Allow Autorize.net enrolments';
+$string['status'] = 'Allow Autorize.Net enrolments';
 $string['nocost'] = 'There is no cost associated with enrolling in this course via Authorize.Net!';
 $string['firstnameoncard'] = 'Firstname on card';
 $string['lastnameoncard'] = 'Lastname on card';
index 0fb9e28..8e85f9b 100644 (file)
@@ -108,6 +108,7 @@ if ($ADMIN->fulltree) {
     $settings->add(new admin_setting_configtext('enrol_database/newcoursecategory', get_string('newcoursecategory', 'enrol_database'), '', ''));
 
     if (!during_initial_install()) {
+        require_once($CFG->dirroot.'/course/lib.php');
         $options = array();
         $parentlist = array();
         make_categories_list($options, $parentlist);
index 85dc17a..edd0217 100644 (file)
@@ -92,6 +92,7 @@ if ($ADMIN->fulltree) {
         $options = $yesno;
         $settings->add(new admin_setting_configselect('enrol_ldap/autocreate', get_string('autocreate_key', 'enrol_ldap'), get_string('autocreate', 'enrol_ldap'), 0, $options));
         if (!during_initial_install()) {
+            require_once($CFG->dirroot.'/course/lib.php');
             $parentlist = array();
             $options = array();
             make_categories_list($options, $parentlist);
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 c485388..159cd43 100644 (file)
@@ -39,15 +39,13 @@ $context = get_context_instance(CONTEXT_COURSE, $id);
 
 require_capability('moodle/course:managegroups', $context);
 
-$strimportgroups   = get_string("importgroups");
+$strimportgroups = get_string('importgroups', 'core_group');
 
-/// Print the header
-$PAGE->navbar->add($course->shortname, new moodle_url('/course/view.php', array('id'=>$course->id)));
-$PAGE->navbar->add(get_string('import'), new moodle_url('/course/import.php', array('id'=>$course->id)));
 $PAGE->navbar->add($strimportgroups);
-
+navigation_node::override_active_url(new moodle_url('/group/index.php', array('id' => $course->id)));
 $PAGE->set_title("$course->shortname: $strimportgroups");
 $PAGE->set_heading($course->fullname);
+$PAGE->set_pagelayout('standard');
 
 $returnurl = new moodle_url('/group/index.php', array('id'=>$id));
 
@@ -188,6 +186,6 @@ if ($mform_post->is_cancelled()) {
 
 /// Print the form
 echo $OUTPUT->header();
-echo $OUTPUT->heading($strimportgroups);
+echo $OUTPUT->heading_with_help($strimportgroups, 'importgroups', 'core_group');
 $mform_post ->display();
 echo $OUTPUT->footer();
index f59a0e4..99e3206 100644 (file)
@@ -23,7 +23,7 @@ class groups_import_form extends moodleform {
 
         $mform->addElement('hidden', 'id');
 
-        $this->add_action_buttons(true, get_string('importgroups'));
+        $this->add_action_buttons(true, get_string('importgroups', 'core_group'));
 
         $this->set_data($data);
     }
index 5df39bf..0eeaf4d 100644 (file)
@@ -215,7 +215,7 @@ echo '<p><input type="submit" name="act_showautocreategroupsform" id="showautocr
         . get_string('autocreategroups', 'group') . '" /></p>'."\n";
 
 echo '<p><input type="submit" name="act_showimportgroups" id="showimportgroups" value="'
-        . get_string('importgroups') . '" /></p>'."\n";
+        . get_string('importgroups', 'core_group') . '" /></p>'."\n";
 
 echo '</td>'."\n";
 echo '<td>'."\n";
index ab17818..4a4896a 100644 (file)
@@ -306,7 +306,7 @@ if ($config->stage == INSTALL_DOWNLOADLANG) {
         $a = new stdClass();
         $a->parent = dirname($CFG->dataroot);
         $a->dataroot = $CFG->dataroot;
-        if (!is_writable(dirname($CFG->dataroot))) {
+        if (!is_writable($a->parent)) {
             $hint_dataroot = get_string('pathsroparentdataroot', 'install', $a);
             $config->stage = INSTALL_PATHS;
         } else {
@@ -317,7 +317,7 @@ if ($config->stage == INSTALL_DOWNLOADLANG) {
         }
 
     } else if (!install_init_dataroot($CFG->dataroot, $CFG->directorypermissions)) {
-        $hint_dataroot = get_string('pathserrcreatedataroot', 'install', $a);
+        $hint_dataroot = get_string('pathserrcreatedataroot', 'install', array('dataroot' => $CFG->dataroot));
         $config->stage = INSTALL_PATHS;
     }
 
@@ -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 ad2e8e4..8e0afaf 100644 (file)
@@ -28,6 +28,8 @@
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+$string['clianswerno'] = 'No';
+$string['cliansweryes'] = 'Sí';
 $string['cliincorrectvalueerror'] = 'Error, valor incorrecte "{$a->value}" per a "{$a->option}"';
 $string['cliincorrectvalueretry'] = 'Valor incorrecte, si us plau, torneu-ho a provar.';
 $string['clitypevalue'] = 'Valor de tipus';
@@ -35,5 +37,6 @@ $string['clitypevaluedefault'] = 'valor de tipus, premeu Intro per fer servir un
 $string['cliunknowoption'] = 'Opcions invàlides: 
  {$a}
 L\'opció --help us orientarà.';
+$string['cliyesnoprompt'] = 'Escriu y (significa Sí) o n (significa No)';
 $string['environmentrequireinstall'] = 'es requereix instal·lar/habilitar';
 $string['environmentrequireversion'] = 'esteu executant la versió {$a->current} i es requereix la {$a->needed}';
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 6c1aa02..5e2ea90 100644 (file)
@@ -35,33 +35,37 @@ $string['chooselanguagesub'] = 'Proszę wybrać język TYLKO do instalacji. Stro
 $string['databasehost'] = 'Host bazy danych';
 $string['databasename'] = 'Nazwa bazy danych';
 $string['dataroot'] = 'Katalog z danymi';
-$string['dbprefix'] = 'prefiksy tabel';
+$string['dbprefix'] = 'Prefiks tabel';
 $string['dirroot'] = 'Katalog Moodle';
 $string['environmenthead'] = 'Sprawdzam środowisko (ustawienia) ...';
 $string['installation'] = 'Instalacja';
-$string['langdownloaderror'] = 'Niestety język "{$a}" nie jest zainstalowany. Instalacja będzie przebiegać dalej po angielsku.';
-$string['memorylimithelp'] = 'Limit pamięci PHP dla Twojego serwera jest ustawiony obecnie na {$a}.</p>
+$string['langdownloaderror'] = 'Niestety język "{$a}" nie może zostać pobrany. Proces instalacji będzie kontynuowany w języku angielskim.';
+$string['memorylimithelp'] = '<p>Limit pamięci PHP dla Twojego serwera jest ustawiony obecnie na {$a}.</p>
 
 <p> Może to stworzyć sytuację, w której Moodle będzie miał w przyszłości problemy z pamięcią, zwłaszcza jeśli masz udostępnionych wiele modułów i/lub wielu użytkowników.</p>
 
-<p> Jeśli jest to możliwe, zalecamy ustawienie konfiguracji PHP z wyższym limitem, np. 40M.
-Istnieje kilka sposobów przeprowadzenia tej operacji, których możesz spróbować: </p>
+<p>Jeśli jest to możliwe, zalecamy ustawienie konfiguracji PHP z wyższym limitem, np. 40M.
+Istnieje kilka sposobów przeprowadzenia tej operacji, których możesz spróbować:</p>
 <ol>
-<li> Jeśli możesz przekompiluj PHP za pomocą <i>--enable-memory-limit</i>.
-Pozwoli to Moodle ustawić samoczynnie limit pamięci. </li>
-<li> Jeśli masz dostęp do swojego pliku php.ini, możesz w nim zmienić ustawienie <b>memory_limit</b> do wielkođci 40M. Jeśli nie posiadasz tego dostępu możesz poprosić swojego administratora aby zrobił to za Ciebie.</li>
-<li> Na niektórych serwerach PHP można stworzyć plik. htaccess w katalogu Moodle zawierający poniższą linię:
-<p><blockquote>php_value memory_limit 40M</blockquote></p>
-<p> jednakże na niektórych serwerach będzie uniemożliwiało to działanie <b> wszystkich </b> stron PHP (ujrzysz błędy na stronie), a więc będziesz zmuszony usunąć plik .htaccess. </p></li></ol>”';
+<li>Jeśli możesz przekompiluj PHP za pomocą <i>--enable-memory-limit</i>.
+Pozwoli to Moodle ustawić samoczynnie limit pamięci.</li>
+<li>Jeśli masz dostęp do pliku konfiguracyjnego php.ini, możesz w nim zmienić ustawienie <b>memory_limit</b> do wielkości np. 40M. W przypadku, gdy nie posiadasz dostępu możesz poprosić swojego administratora aby zrobił to za Ciebie.</li>
+<li>Na niektórych serwerach PHP można stworzyć plik. htaccess w katalogu Moodle zawierający poniższą linię:
+<blockquote><div>php_value memory_limit 40M</div></blockquote>
+<p>Jednakże na niektórych serwerach będzie uniemożliwiało to poprawne działanie <b>wszystkich</b> stron PHP (ujrzysz błędy na wyświetlanych stronach), wtedy będziesz musiał usunąć plik .htaccess.</p></li>
+</ol>';
+$string['pathsroparentdataroot'] = 'Nadrzędny katalog ({$a->parent}) jest tylko do odczytu. Katalog danych ({$a->dataroot}) nie może zostać utworzony przez instalator. ';
+$string['pathswrongadmindir'] = 'Katalog admin nie istnieje';
+$string['phpextension'] = '{$a} rozszerzenie PHP';
 $string['phpversion'] = 'Wersja PHP';
-$string['phpversionhelp'] = '<p> Moodle wymaga wersji PHP co najmniej 4.1.0. </p> 
+$string['phpversionhelp'] = '<p>Moodle wymaga wersji PHP co najmniej 4.3.0 lub 5.1.0 (5.0.x posiada kilka znanych problemów).</p> 
 <p>Obecnie jest uruchomiona wersja {$a}</p>
-<p> Musisz uaktualnić wersje PHP lub przenieść na host z nowszą wersją PHP!</p>';
+<p>Musisz uaktualnić wersję PHP lub przenieść na host z nowszą wersją PHP!<br />(W przypadku wersji 5.0.x możesz dokonać downgrade do wersji 4.4.x)</p>';
 $string['welcomep10'] = '{$a->installername} ({$a->installerversion})';
-$string['welcomep20'] = 'Widzisz tę stronę, ponieważ z powodzeniem zainstalowałeś i uruchomiłeś <strong>{$a->packname} {$a->packversion}</strong>  na swoim komputerze.';
+$string['welcomep20'] = 'Widzisz tę stronę, ponieważ z powodzeniem zainstalowałeś i uruchomiłeś <strong>{$a->packname} {$a->packversion}</strong> na swoim komputerze.';
 $string['welcomep30'] = 'Ten instalator <strong>{$a->installername}</strong> zawiera aplikacje, by stworzyć środowisko, w którym będzie działać <strong>Moodle</strong>, czyli';
-$string['welcomep40'] = 'Pakiet zawiera<strong>Moodle {$a->moodlerelease} ({$a->moodleversion})</strong>.';
+$string['welcomep40'] = 'Pakiet zawiera <strong>Moodle {$a->moodlerelease} ({$a->moodleversion})</strong>.';
 $string['welcomep50'] = 'Wszystkie aplikacje w tym pakiecie maja własne, oddzielne licencje. Kompletny pakiet <strong>{$a->installername}</strong> jest <a href="http://www.opensource.org/docs/definition_plain.html">open source</a> i jest dystrybuowany na <a href="http://www.gnu.org/copyleft/gpl.html">GPL</a> licencji.';
-$string['welcomep60'] = 'Nastepujące strony przeprowadzą cię przez instalację Moodle na twoim komputerze. Możesz zaakceptować ustawienia domyślne lub, opcjonalnie, dostosować je do swoich potrzeb.';
-$string['welcomep70'] = 'Kliknij "Dalej" żeby kontynuować instalację Moodle';
+$string['welcomep60'] = 'Nastepujące strony przeprowadzą cię przez instalację <strong>Moodle</strong> na twoim komputerze. Możesz zaakceptować ustawienia domyślne, lub opcjonalnie, dostosować je do swoich potrzeb.';
+$string['welcomep70'] = 'Kliknij przycisk "Dalej" żeby kontynuować instalację <strong>Moodle</strong>.';
 $string['wwwroot'] = 'Adres w sieci';
index 0dd99a8..2fb9431 100644 (file)
@@ -33,12 +33,16 @@ $string['availablelangs'] = 'Pacotes de idioma disponíveis';
 $string['chooselanguagehead'] = 'Escolha um idioma';
 $string['chooselanguagesub'] = 'Escolha um idioma a ser usado durante a instalação. Após a instalação você pode definir o idioma principal do site e outros idiomas a serem utilizados pelos usuários.';
 $string['clialreadyinstalled'] = 'O arquivo config.php já existe, por favor use admin/cli/upgrade.php, se você quiser atualizar o seu site.';
+$string['cliinstallheader'] = 'Programa de instalação por linha de comando do Moodle {$a}';
+$string['databasehost'] = 'Host da Base de Dados.';
 $string['databasename'] = 'Nome da Base de Dados';
 $string['databasetypehead'] = 'Escolha o driver da base de dados';
 $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.';
@@ -55,16 +59,25 @@ Com esta operação Moodle será capaz de configurar o limite de memória sózin
 <p><blockquote>php_value memory_limit 40M</blockquote></p>
 <p>Alguns servidores não aceitam este procedimento e <b>todas</b> as páginas PHP do servidor ficam bloqueadas ou imprimem mensagens de erro. Neste caso será necessário excluir o arquivo .htaccess .</p>
 </li></ol>';
+$string['paths'] = 'Caminhos';
+$string['pathserrcreatedataroot'] = 'O Diretório de Dados ({&a->dataroot}) não pode ser criado pelo instalador.';
+$string['pathshead'] = 'Confirme os caminhos';
+$string['pathsrodataroot'] = 'O Diretório de Dados raiz não pode ser acessada para escrita.';
+$string['pathsroparentdataroot'] = 'O diretório pai ({$a->parent}) não pode ser escrito. O diretório de dados ({$a->dataroot)) não pode ser criado pelo instalador.';
+$string['pathssubadmindir'] = 'Alguns poucos webhosts usam /admin como um URL especial para acesso ao painel de controle ou outras coisas. Infelizmente isto conflita com a localizaçao padrão das páginas do administrador Moodle. Você pode corrigir isso renomeando a pasta admin na sua instalação, e colocando esse novo nome aqui. Por exemplo: <em>moodleadmin</em>. Isto irá corrigir os links das páginas do administrador Moodle.';
 $string['pathssubdataroot'] = 'Você precisa de um local onde o Moodle possa salvar arquivos enviados. Este diretório deve possuir permissões de leitura e escrita pelo usuário do servidor web
 (geralmente \'nobody\' ou \'apache \'), mas não deverá ser acessível diretamente através da web. O instalador irá tentar criá-lo se ele não existir.';
 $string['pathssubdirroot'] = 'Caminho completo do diretório para instalação do Moddle.';
 $string['pathssubwwwroot'] = 'Endereço web completo onde o Moodle será acessado.
 Não é possível acessar o Moodle usando múltiplos endereços. Se seu site tem múltiplos endereços públicos você deve configurar redirecionamentos permantentes em todos eles exceto esse. Se seu site é acessado tanto da Intranet como Internet, use o endereço público aqui e configure o DNS para que os usuários da Intranet possam usar o endereço público também. Se o endereço não estiver correto, por favo mude a URL no seu navegador para reiniciar a instalação com um valor diferente.';
+$string['pathsunsecuredataroot'] = 'A localização da pasta de dados não é segura.';
 $string['pathswrongadmindir'] = 'Diretório Admin não existe';
+$string['phpextension'] = 'Extensão PHP {$a}';
 $string['phpversion'] = 'Versão do PHP';
-$string['phpversionhelp'] = '<p>Moodle requer a versão 4.1.0 de PHP ou posterior.</p>
-<p>A sua versão é {$a}</p>
-<p>Atualize a versão do PHP!</p>';
+$string['phpversionhelp'] = '<p>Moodle requer a versão 4.3.0 de PHP ou posterior.</p>
+<p>A sua versão é  a {$a}</p>
+<p>Atualize a versão do PHP!</p>
+(atenção, a versão 5.0.x tem muitos problemas - use a versão 5.1.0 ou a 4.4)';
 $string['welcomep10'] = '{$a->installername} ({$a->installerversion})';
 $string['welcomep20'] = 'Se você chegou nesta página, o pacote <strong>{$a->packname} {$a->packversion}</strong> foi instalado. Parabéns!';
 $string['welcomep30'] = 'Esta versão do <strong>{$a->installername}</strong> inclui as aplicações para a criação de um ambiente em que <strong>Moodle</strong> possa operar:';
index 289bb88..bfd5f6c 100644 (file)
 
 $string['clianswerno'] = 'n';
 $string['cliansweryes'] = 'y';
+$string['cliincorrectvalueerror'] = 'Fel, värdet "{$a->value}" för "{$a->option}" är inte korrekt.';
 $string['cliincorrectvalueretry'] = 'Felaktigt värde, var snäll och försök igen';
 $string['clitypevalue'] = 'Värde för typ';
+$string['clitypevaluedefault'] = 'skriv in värdet, klicka på "Enter" om Du vill använda standardvärdet ({$a})';
 $string['cliunknowoption'] = 'Ej identifierade alternativ: {$a} Var snäll och använd alternativet Hjälp.';
 $string['cliyesnoprompt'] = 'skriv in y (betyder ja) eller n (betyder nej)';
 $string['environmentrequireinstall'] = 'är nödvändig att installera/aktivera';
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 2476663..be7f303 100644 (file)
@@ -34,7 +34,7 @@ $string['exportdata'] = 'Export data';
 $string['exportschemaexception'] = 'Current database structure does not match all install.xml files. <br /> {$a}';
 $string['checkingsourcetables'] = 'Checking source table structure';
 $string['importschemaexception'] = 'Current database structure does not match all install.xml files. <br /> {$a}';
-$string['importversionmismatchexception'] = 'Current version {$a->currentver} does match exported version {$a->schemaver}.';
+$string['importversionmismatchexception'] = 'Current version {$a->currentver} does not match exported version {$a->schemaver}.';
 $string['malformedxmlexception'] = 'Malformed XML found, can not continue.';
 $string['notargetconectexception'] = 'Can not connect target database, sorry.';
 $string['transferdata'] = 'Transfer data';
index fcafae7..ed6da26 100644 (file)
@@ -107,7 +107,6 @@ $string['field1030303']='Mining Engineering';
 $string['field1030305']='Materials Engineering';
 $string['field1030307']='Food Processing Technology';
 $string['field1030399']='Process and Resources Engineering (Other)';
-$string['field1030399']='Process and Resources Engineering (Other)';
 $string['field10305']='Automotive Engineering and Technology';
 $string['field1030501']='Automotive Engineering';
 $string['field1030503']='Vehicle Mechanics';
index 4ab4aa0..4a177de 100644 (file)
@@ -555,7 +555,6 @@ $string['showcalculations'] = 'Show calculations';
 $string['showcalculations_help'] = 'If enabled, when editing is turned on, a calculator icon is shown for each grade item and category, with tool tips over calculated items and a visual indicator that a column is calculated.';
 $string['showeyecons'] = 'Show show/hide icons';
 $string['showeyecons_help'] = 'If enabled, when editing is turned on, a show/hide icon is shown for each grade for controlling its visibility to the student.';
-$string['showfeedback'] = 'Show feedback';
 $string['showgroups'] = 'Show groups';
 $string['showhiddenitems'] = 'Show hidden items';
 $string['showhiddenitems_help'] = 'Whether hidden grade items are hidden entirely or if the names of hidden grade items are visible to students.
index e72ec0f..7a98c5b 100644 (file)
@@ -114,6 +114,15 @@ $string['groupsseparate'] = 'Separate groups';
 $string['groupsvisible'] = 'Visible groups';
 $string['grouptemplate'] = 'Group @';
 $string['hidepicture'] = 'Hide picture';
+$string['importgroups'] = 'Import groups';
+$string['importgroups_help'] = 'Groups may be imported 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
+* The first record contains a list of fieldnames defining the format of the rest of the file
+* Required fieldname is groupname
+* Optional fieldnames are description, enrolmentkey, picture, hidepicture';
+$string['importgroups_link'] = 'group/import';
 $string['javascriptrequired'] = 'This page requires JavaScript to be enabled.';
 $string['members'] = 'Members per group';
 $string['membersofselectedgroup'] = 'Members of:';
index 807c1f1..016a815 100644 (file)
@@ -105,7 +105,6 @@ $string['forceunregister'] = 'Yes, clean registration data';
 $string['forceunregisterconfirmation'] = 'Your site cannot reach {$a}. This hub could be temporarily down. Unless you are sure you want to continue to remove registration locally, please cancel and try again later.';
 $string['geolocation'] = 'Geolocation';
 $string['geolocation_help'] = 'In future we may provide location-based searching. If you want to specify the location for your course use a latitude/longitude value here (eg: -31.947884,115.871285).  One way to find this is to use Google Maps.';
-$string['siteemail'] = 'Email address';
 $string['hub'] = 'Hub';
 $string['imageurl'] = 'Image URL';
 $string['imageurl_help'] = 'This image will be displayed on the hub. This image must be available from the hub at any moment. The image should have a maximum size of {$a->width} X {$a->height}';
@@ -241,7 +240,6 @@ $string['statistics'] = 'Statistics privacy';
 $string['status'] = 'Hub listing';
 $string['statuspublished'] = 'Listed';
 $string['statusunpublished'] = 'Not listed';
-$string['subject'] = 'Subject';
 $string['tags'] = 'Tags';
 $string['tags_help'] = 'Tags help to further categorise your course and help it to be found. Please use simple, meaningful words and separate them with a comma. Example: math, algebra, geometry';
 $string['trustme'] = 'Trust';
index 593bf21..05b7957 100644 (file)
@@ -859,7 +859,6 @@ $string['importdata'] = 'Import course data';
 $string['importdataexported'] = 'Exported data from \'from\' course successfully.<br /> Continue to import into your \'to\' course.';
 $string['importdatafinished'] = 'Import complete! Continue to your course';
 $string['importdatafrom'] = 'Find a course to import data from:';
-$string['importgroups'] = 'Import groups';
 $string['inactive'] = 'Inactive';
 $string['include'] = 'Include';
 $string['includeallusers'] = 'Include all users';
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 2088df6..e7676bb 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="lib/db" VERSION="20110125" COMMENT="XMLDB file for core Moodle tables"
+<XMLDB PATH="lib/db" VERSION="20110206" COMMENT="XMLDB file for core Moodle tables"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
 >
@@ -50,8 +50,9 @@
         <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="type"/>
         <FIELD NAME="type" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" SEQUENCE="false" COMMENT="type: 0==info, 1==notice, 2==error" PREVIOUS="id" NEXT="plugin"/>
         <FIELD NAME="plugin" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false" PREVIOUS="type" NEXT="version"/>
-        <FIELD NAME="version" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false" COMMENT="plugin or main version if known" PREVIOUS="plugin" NEXT="info"/>
-        <FIELD NAME="info" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" PREVIOUS="version" NEXT="details"/>
+        <FIELD NAME="version" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false" COMMENT="plugin or main version if known" PREVIOUS="plugin" NEXT="targetversion"/>
+        <FIELD NAME="targetversion" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false" COMMENT="version of plugin or core specified in version.php at the time of upgrade loggging" PREVIOUS="version" NEXT="info"/>
+        <FIELD NAME="info" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" PREVIOUS="targetversion" NEXT="details"/>
         <FIELD NAME="details" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" PREVIOUS="info" NEXT="backtrace"/>
         <FIELD NAME="backtrace" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" PREVIOUS="details" NEXT="userid"/>
         <FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="backtrace" NEXT="timemodified"/>
index 1be183d..3bd79d8 100644 (file)
@@ -74,6 +74,7 @@ function xmldb_main_upgrade($oldversion) {
         $table->add_field('type', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
         $table->add_field('plugin', XMLDB_TYPE_CHAR, '100', null, null, null, null);
         $table->add_field('version', XMLDB_TYPE_CHAR, '100', null, null, null, null);
+        $table->add_field('targetversion', XMLDB_TYPE_CHAR, '100', null, null, null, null);
         $table->add_field('info', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
         $table->add_field('details', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
         $table->add_field('backtrace', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
@@ -4090,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);
@@ -6005,6 +6008,27 @@ WHERE gradeitemid IS NOT NULL AND grademax IS NOT NULL");
         upgrade_main_savepoint(true, 2011012501);
     }
 
+    if ($oldversion < 2011020200.01) {
+
+        // Define field targetversion to be added to upgrade_log
+        $table = new xmldb_table('upgrade_log');
+        $field = new xmldb_field('targetversion', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'version');
+
+        // Conditionally launch add field targetversion
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+
+        // Main savepoint reached
+        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 0ce070a..2e0b37c 100644 (file)
@@ -396,7 +396,10 @@ class oracle_sql_generator extends sql_generator {
     ///     - drop the old column
     ///     - rename the temp column to the original name
         if (($typechanged) || (($oldmetatype == 'N' || $oldmetatype == 'I')  && ($precisionchanged || $decimalchanged))) {
-            $tempcolname = $xmldb_field->getName() . '_alter_column_tmp';
+            $tempcolname = $xmldb_field->getName() . '___tmp'; // Short tmp name, surely not conflicting ever
+            if (strlen($tempcolname) > 30) { // Safeguard we don't excess the 30cc limit
+                $tempcolname = 'ongoing_alter_column_tmp';
+            }
         /// Prevent temp field to have both NULL/NOT NULL and DEFAULT constraints
             $skip_notnull_clause = true;
             $skip_default_clause = 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 b22ca09..b3c1ceb 100644 (file)
@@ -56,13 +56,23 @@ class mysqli_native_moodle_database extends moodle_database {
             throw new dml_exception('dbdriverproblem', $driverstatus);
         }
 
-        if (empty($this->dboptions['dbport'])) {
-            $dbport = ini_get('mysqli.default_port');
+        if (!empty($dboptions['dbsocket'])
+                and (strpos($dboptions['dbsocket'], '/') !== false or strpos($dboptions['dbsocket'], '\\') !== false)) {
+            $dbsocket = $dboptions['dbsocket'];
         } else {
-            $dbport = (int)$this->dboptions['dbport'];
+            $dbsocket = ini_get('mysqli.default_socket');
+        }
+        if (empty($dboptions['dbport'])) {
+            $dbport = (int)ini_get('mysqli.default_port');
+        } else {
+            $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;
@@ -267,16 +277,21 @@ class mysqli_native_moodle_database extends moodle_database {
 
         // dbsocket is used ONLY if host is NULL or 'localhost',
         // you can not disable it because it is always tried if dbhost is 'localhost'
-        if (!empty($this->dboptions['dbsocket']) and strpos($this->dboptions['dbsocket'], '/') !== false) {
+        if (!empty($this->dboptions['dbsocket'])
+                and (strpos($this->dboptions['dbsocket'], '/') !== false or strpos($this->dboptions['dbsocket'], '\\') !== false)) {
             $dbsocket = $this->dboptions['dbsocket'];
         } else {
             $dbsocket = ini_get('mysqli.default_socket');
         }
         if (empty($this->dboptions['dbport'])) {
-            $dbport = ini_get('mysqli.default_port');
+            $dbport = (int)ini_get('mysqli.default_port');
         } else {
             $dbport = (int)$this->dboptions['dbport'];
         }
+        // verify ini.get does not return nonsense
+        if (empty($dbport)) {
+            $dbport = 3306;
+        }
         ob_start();
         $this->mysqli = new mysqli($dbhost, $dbuser, $dbpass, $dbname, $dbport, $dbsocket);
         $dberr = ob_get_contents();
index a302282..ab7107e 100755 (executable)
@@ -3610,6 +3610,118 @@ class dml_test extends UnitTestCase {
         $this->assertTrue($records = $DB->get_records_sql($sqlnamed, array('content' => '2')));
         $this->assertEqual(1, count($records));
     }
+
+    public function test_limits_and_offsets() {
+        $DB = $this->tdb;
+        $dbman = $DB->get_manager();
+
+        if (false) $DB = new moodle_database ();
+
+        $table = $this->get_test_table();
+        $tablename = $table->getName();
+
+        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+        $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
+        $table->add_field('content', XMLDB_TYPE_TEXT, 'big', XMLDB_UNSIGNED, XMLDB_NOTNULL);
+        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+        $dbman->create_table($table);
+
+        $this->assertTrue($DB->insert_record($tablename, array('name' => 'a', 'content'=>'one')));
+        $this->assertTrue($DB->insert_record($tablename, array('name' => 'b', 'content'=>'two')));
+        $this->assertTrue($DB->insert_record($tablename, array('name' => 'c', 'content'=>'three')));
+        $this->assertTrue($DB->insert_record($tablename, array('name' => 'd', 'content'=>'four')));
+        $this->assertTrue($DB->insert_record($tablename, array('name' => 'e', 'content'=>'five')));
+        $this->assertTrue($DB->insert_record($tablename, array('name' => 'f', 'content'=>'six')));
+
+        $sqlqm = "SELECT *
+                    FROM {{$tablename}}";
+        $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 4));
+        $this->assertEqual(2, count($records));
+        $this->assertEqual('e', reset($records)->name);
+        $this->assertEqual('f', end($records)->name);
+
+        $sqlqm = "SELECT *
+                    FROM {{$tablename}}";
+        $this->assertFalse($records = $DB->get_records_sql($sqlqm, null, 8));
+
+        $sqlqm = "SELECT *
+                    FROM {{$tablename}}";
+        $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 0, 4));
+        $this->assertEqual(4, count($records));
+        $this->assertEqual('a', reset($records)->name);
+        $this->assertEqual('d', end($records)->name);
+
+        $sqlqm = "SELECT *
+                    FROM {{$tablename}}";
+        $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 0, 8));
+        $this->assertEqual(6, count($records));
+        $this->assertEqual('a', reset($records)->name);
+        $this->assertEqual('f', end($records)->name);
+
+        $sqlqm = "SELECT *
+                    FROM {{$tablename}}";
+        $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 1, 4));
+        $this->assertEqual(4, count($records));
+        $this->assertEqual('b', reset($records)->name);
+        $this->assertEqual('e', end($records)->name);
+
+        $sqlqm = "SELECT *
+                    FROM {{$tablename}}";
+        $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 4, 4));
+        $this->assertEqual(2, count($records));
+        $this->assertEqual('e', reset($records)->name);
+        $this->assertEqual('f', end($records)->name);
+
+        $sqlqm = "SELECT t.*, t.name AS test
+                    FROM {{$tablename}} t
+                    ORDER BY t.id ASC";
+        $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 4, 4));
+        $this->assertEqual(2, count($records));
+        $this->assertEqual('e', reset($records)->name);
+        $this->assertEqual('f', end($records)->name);
+
+        $sqlqm = "SELECT DISTINCT t.name, t.name AS test
+                    FROM {{$tablename}} t
+                    ORDER BY t.name DESC";
+        $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 4, 4));
+        $this->assertEqual(2, count($records));
+        $this->assertEqual('b', reset($records)->name);
+        $this->assertEqual('a', end($records)->name);
+
+        $sqlqm = "SELECT 1
+                    FROM {{$tablename}} t
+                    WHERE t.name = 'a'";
+        $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 0, 1));
+        $this->assertEqual(1, count($records));
+
+        $sqlqm = "SELECT 'constant'
+                    FROM {{$tablename}} t
+                    WHERE t.name = 'a'";
+        $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 0, 8));
+        $this->assertEqual(1, count($records));
+
+        $this->assertTrue($DB->insert_record($tablename, array('name' => 'a', 'content'=>'one')));
+        $this->assertTrue($DB->insert_record($tablename, array('name' => 'b', 'content'=>'two')));
+        $this->assertTrue($DB->insert_record($tablename, array('name' => 'c', 'content'=>'three')));
+
+        $sqlqm = "SELECT t.name, COUNT(DISTINCT t2.id) AS count, 'Test' AS teststring
+                    FROM {{$tablename}} t
+                    LEFT JOIN (
+                        SELECT t.id, t.name
+                        FROM {{$tablename}} t
+                    ) t2 ON t2.name = t.name
+                    GROUP BY t.name
+                    ORDER BY t.name ASC";
+        $this->assertTrue($records = $DB->get_records_sql($sqlqm));
+        $this->assertEqual(6, count($records));         // a,b,c,d,e,f
+        $this->assertEqual(2, reset($records)->count);  // a has 2 records now
+        $this->assertEqual(1, end($records)->count);    // f has 1 record still
+
+        $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 0, 2));
+        $this->assertEqual(2, count($records));
+        $this->assertEqual(2, reset($records)->count);
+        $this->assertEqual(2, end($records)->count);
+    }
 }
 
 /**
index 88539aa..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;
         }
@@ -797,23 +797,17 @@ class sqlsrv_native_moodle_database extends moodle_database {
         $firstcolumn = 'id'; // The default first column is id
         $orderby = '';       // The order by of the main query
 
-        // We need to find all the columns so that we can request JUST the desired
-        // columns in the end transaction. We also need to do a couple of maintenance
-        // tasks on the columns seeing as they are going to be wrapped in a 
-        // sub select.
+        // We need to do a couple of maintenance tasks on the columns seeing as
+        // they are going to be wrapped in a sub select.
         //
         // 1. Collect the first column to use for an order by if there isn't an
         //    explicit order by within the query.
-        // 2. Make we use the aliases for columns that have it because of next point.
-        // 3. Strip off table aliases they will be incorrect outside of the immediate
-        //    sub select.
-        // 4. Give all constant columns a proper alias, this is required because
+        // 2. Give all constant columns a proper alias, this is required because
         //    of the subselect.
         if (preg_match('#^(\s*SELECT\s+)(DISTINCT\s+)?(.*?)(\sFROM\s)#is', $sql, $columnmatches)) {
             // Make sure we have some columns
             if (!empty($columnmatches[3])) {
                 $columns = explode(',', $columnmatches[3]);
-                $columnnames = array();
                 $firstcolumn = null;
                 $constantcount = 0;
                 foreach ($columns as $key=>$column) {
@@ -822,7 +816,7 @@ class sqlsrv_native_moodle_database extends moodle_database {
                     if (preg_match('#\sAS\s+(\w+)\s*$#si', $column, $matches)) {
                         // Make sure we use the column alias if available.
                         $column = $matches[1];
-                    } else if (preg_match("#^'[^']*'$#", $column)) {
+                    } else if (preg_match("#^('[^']*'|\d+)$#", $column)) {
                         // Give constants an alias in the main query and use the
                         // alias for the new outer queries.
                         $constantcount++;
@@ -834,16 +828,8 @@ class sqlsrv_native_moodle_database extends moodle_database {
                     if ($firstcolumn === null) {
                         $firstcolumn = $column;
                     }
-
-                    // Remove any table aliases from the column name for the outer
-                    // queries.
-                    if (preg_match('#^\w+\.(.*)$#s', $column, $matches)) {
-                        $column = $matches[1];
-                    }
-                    $columnnames[] = $column;
                 }
                 // Glue things back together
-                $columnnames = join(', ', $columnnames);
                 $columns = join(', ', $columns);
                 // Switch out the fixed main columns (added constant aliases).
                 $sql = str_replace($columnmatches[0], $columnmatches[1].$columnmatches[2].$columns.$columnmatches[4], $sql);
@@ -867,10 +853,18 @@ class sqlsrv_native_moodle_database extends moodle_database {
             $orderby = 'id';
         }
 
+        // Now we need to build the queries up so that we collect a row count field and then sort on it.
+        // To do this we need to nest the query twice. The first nesting selects all the rows from the
+        // query and then proceeds to use OVER to generate a row number.
+        // The second nesting we limit by selecting where rownumber between offset and limit
+        // In both cases we will select the original query fields using q.* this is important
+        // as there can be any number of crafty things going on. It does however mean that we
+        // end up with the first field being sqlsrvrownumber however sqlsrv_native_moodle_recordset
+        // strips that off during processing if it exists.
         // Build the inner outer query.
-        $sql = "SELECT TOP $bigint ROW_NUMBER() OVER(ORDER BY $orderby) AS sqlsrvrownumber, $columnnames FROM ($sql) AS q";
+        $sql = "SELECT TOP $bigint ROW_NUMBER() OVER(ORDER BY $orderby) AS sqlsrvrownumber, q.* FROM ($sql) AS q";
         // Build the outer most query.
-        $sql = "SELECT $columnnames FROM ($sql) AS q WHERE q.sqlsrvrownumber > $offset AND q.sqlsrvrownumber <= $limit";
+        $sql = "SELECT q.* FROM ($sql) AS q WHERE q.sqlsrvrownumber > $offset AND q.sqlsrvrownumber <= $limit";
 
         // Return the now mangled query for use.
         return $sql;
index 815bfed..8ee18fd 100644 (file)
@@ -44,6 +44,7 @@ class sqlsrv_native_moodle_recordset extends moodle_recordset {
 
     private function fetch_next() {
         if ($row = sqlsrv_fetch_array($this->rsrc, SQLSRV_FETCH_ASSOC)) {
+            unset($row['sqlsrvrownumber']);
             $row = array_change_key_case($row, CASE_LOWER);
         }
         return $row;
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 0d5bf93..8785e50 100644 (file)
@@ -489,6 +489,14 @@ class cm_info extends stdClass  {
      */
     public $uservisible;
 
+    /**
+     * Module context - hacky shortcut
+     * @deprecated
+     * @var stdClass
+     */
+    public $context;
+
+
     // New data available only via functions
     ////////////////////////////////////////
 
@@ -706,7 +714,7 @@ class cm_info extends stdClass  {
      */
     public function set_no_view_link() {
         $this->check_not_view_only();
-        $url = null;
+        $this->url = null;
     }
 
     /**
@@ -791,6 +799,7 @@ class cm_info extends stdClass  {
         $this->icon             = isset($mod->icon) ? $mod->icon : '';
         $this->iconcomponent    = isset($mod->iconcomponent) ? $mod->iconcomponent : '';
         $this->customdata       = isset($mod->customdata) ? $mod->customdata : '';
+        $this->context          = get_context_instance(CONTEXT_MODULE, $mod->cm);
         $this->state = self::STATE_BASIC;
 
         // This special case handles old label data. Labels used to use the 'name' field for
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 1a9f007..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);
                 }
@@ -1510,7 +1506,7 @@ class global_navigation extends navigation_node {
      *  * {@see forum_extend_navigation()}
      *  * {@see workshop_extend_navigation()}
      *
-     * @param stdClass $cm
+     * @param cm_info|stdClass $cm
      * @param stdClass $course
      * @param navigation_node $activity
      * @return bool
@@ -1518,6 +1514,12 @@ 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);
+            $cm = $modinfo->get_cm($cm->id);
+        }
+
         $activity->make_active();
         $file = $CFG->dirroot.'/mod/'.$cm->modname.'/lib.php';
         $function = $cm->modname.'_extend_navigation';
@@ -1563,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 {
@@ -1851,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);
@@ -2239,8 +2247,9 @@ class global_navigation_for_ajax extends global_navigation {
                 $this->load_section_activities($sections[$course->sectionnumber]->sectionnode, $course->sectionnumber, get_fast_modinfo($course));
                 break;
             case self::TYPE_ACTIVITY :
-                $cm = get_coursemodule_from_id(false, $this->instanceid, 0, false, MUST_EXIST);
                 $course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST);
+                $modinfo = get_fast_modinfo($course);
+                $cm = $modinfo->get_cm($this->instanceid);
                 require_course_login($course, true, $cm);
                 $this->page->set_context(get_context_instance(CONTEXT_MODULE, $cm->id));
                 $coursenode = $this->load_course($course);
@@ -2977,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;
@@ -3398,26 +3407,10 @@ class settings_navigation extends navigation_node {
             if (portfolio_instances(true, false)) {
                 $portfolio = $usersetting->add(get_string('portfolios', 'portfolio'), null, self::TYPE_SETTING);
 
-                $config  = optional_param('config', 0, PARAM_INT);
-                $hide    = optional_param('hide', 0, PARAM_INT);
                 $url = new moodle_url('/user/portfolio.php', array('courseid'=>$course->id));
-                if ($hide !== 0) {
-                    $url->param('hide', $hide);
-                }
-                if ($config !== 0) {
-                    $url->param('config', $config);
-                }
                 $portfolio->add(get_string('configure', 'portfolio'), $url, self::TYPE_SETTING);
 
-                $page = optional_param('page', 0, PARAM_INT);
-                $perpage = optional_param('perpage', 10, PARAM_INT);
                 $url = new moodle_url('/user/portfoliologs.php', array('courseid'=>$course->id));
-                if ($page !== 0) {
-                    $url->param('page', $page);
-                }
-                if ($perpage !== 0) {
-                    $url->param('perpage', $perpage);
-                }
                 $portfolio->add(get_string('logs', 'portfolio'), $url, self::TYPE_SETTING);
             }
         }
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 5e5de36..7764aba 100644 (file)
@@ -102,9 +102,8 @@ class moodle_page {
     protected $_course = null;
 
     /**
-     * If this page belongs to a module, this is the row from the course_modules
-     * table, as fetched by get_coursemodule_from_id or get_coursemodule_from_instance,
-     * so the extra modname and name fields are present.
+     * If this page belongs to a module, this is the cm_info module description object.
+     * @var cm_info
      */
     protected $_cm = null;
 
@@ -272,6 +271,7 @@ class moodle_page {
      * if this page is not within a module. This is a full cm object, as loaded
      * by get_coursemodule_from_id or get_coursemodule_from_instance,
      * so the extra modname and name fields are present.
+     * @return cm_info
      */
     protected function magic_get_cm() {
         return $this->_cm;
@@ -775,7 +775,7 @@ class moodle_page {
     /**
      * The course module that this page belongs to (if it does belong to one).
      *
-     * @param stdClass $cm a full cm object obtained from get_coursemodule_from_id or get_coursemodule_from_instance.
+     * @param stdClass|cm_info $cm a record from course_modules table or cm_info from get_fast_modinfo().
      * @param stdClass $course
      * @param stdClass $module
      * @return void
@@ -783,23 +783,29 @@ class moodle_page {
     public function set_cm($cm, $course = null, $module = null) {
         global $DB;
 
-        if (!isset($cm->name) || !isset($cm->modname) || !isset($cm->id)) {
-            throw new coding_exception('The $cm you set on $PAGE must have been obtained with get_coursemodule_from_id or get_coursemodule_from_instance. That is, the ->name and -> modname fields must be present and correct.');
-        }
-        $this->_cm = $cm;
-        $this->_cm->context = get_context_instance(CONTEXT_MODULE, $cm->id); // hacky shortcut
-        if (!$this->_context) {
-            $this->set_context($this->_cm->context);
+        if (!isset($cm->id) || !isset($cm->course)) {
+            throw new coding_exception('Invalid $cm parameter for $PAGE object, it has to be instance of cm_info or record from the course_modules table.');
         }
+
         if (!$this->_course || $this->_course->id != $cm->course) {
             if (!$course) {
                 $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
             }
             if ($course->id != $cm->course) {
-                throw new coding_exception('The course you passed to $PAGE->set_cm does not seem to correspond to the $cm.');
+                throw new coding_exception('The course you passed to $PAGE->set_cm does not correspond to the $cm.');
             }
             $this->set_course($course);
         }
+
+        // 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($this->_course);
+            $cm = $modinfo->get_cm($cm->id);
+        }
+        $this->_cm = $cm;
+        $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+        $this->set_context($context); // the content of page MUST match the cm, this prints warning if there is any problem
+
         if ($module) {
             $this->set_activity_record($module);
         }
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 0c58538..1adceea 100644 (file)
@@ -474,10 +474,11 @@ class textlib {
      */
     function asort(array &$arr) {
         if (function_exists('collator_asort')) {
-            $coll = collator_create(get_string('locale', 'langconfig'));
-            collator_asort($coll, $arr);
-        } else {
-            asort($arr, SORT_LOCALE_STRING);
+            if ($coll = collator_create(get_string('locale', 'langconfig'))) {
+                collator_asort($coll, $arr);
+                return;
+            }
         }
+        asort($arr, SORT_LOCALE_STRING);
     }
 }
index 81de9b7..53c8727 100644 (file)
@@ -987,11 +987,8 @@ function upgrade_handle_exception($ex, $plugin = null) {
 /**
  * Adds log entry into upgrade_log table
  *
- * @global object
- * @global object
- * @global object
  * @param int $type UPGRADE_LOG_NORMAL, UPGRADE_LOG_NOTICE or UPGRADE_LOG_ERROR
- * @param string $plugin plugin or null if main
+ * @param string $plugin frankenstyle component name
  * @param string $info short description text of log entry
  * @param string $details long problem description
  * @param string $backtrace string used for errors only
@@ -1000,54 +997,80 @@ function upgrade_handle_exception($ex, $plugin = null) {
 function upgrade_log($type, $plugin, $info, $details=null, $backtrace=null) {
     global $DB, $USER, $CFG;
 
-    $plugin = ($plugin==='moodle') ? null : $plugin;
+    if (empty($plugin)) {
+        $plugin = 'core';
+    }
+
+    list($plugintype, $pluginname) = normalize_component($plugin);
+    $component = is_null($pluginname) ? $plugintype : $plugintype . '_' . $pluginname;
 
     $backtrace = format_backtrace($backtrace, true);
 
-    $version = null;
+    $currentversion = null;
+    $targetversion  = null;
 
     //first try to find out current version number
-    if (empty($plugin) or $plugin === 'moodle') {
+    if ($plugintype === 'core') {
         //main
-        $version = $CFG->version;
+        $currentversion = $CFG->version;
 
-    } else if ($plugin === 'local') {
-        //customisation
-        $version = $CFG->local_version;
+        $version = null;
+        include("$CFG->dirroot/version.php");
+        $targetversion = $version;
 
-    } else if (strpos($plugin, 'mod/') === 0) {
+    } else if ($plugintype === 'mod') {
         try {
-            $modname = substr($plugin, strlen('mod/'));
-            $version = $DB->get_field('modules', 'version', array('name'=>$modname));
-            $version = ($version === false) ? null : $version;
+            $currentversion = $DB->get_field('modules', 'version', array('name'=>$pluginname));
+            $currentversion = ($currentversion === false) ? null : $currentversion;
         } catch (Exception $ignored) {
         }
+        $cd = get_component_directory($component);
+        if (file_exists("$cd/version.php")) {
+            $module = new stdClass();
+            $module->version = null;
+            include("$cd/version.php");
+            $targetversion = $module->version;
+        }
 
-    } else if (strpos($plugin, 'block/') === 0) {
+    } else if ($plugintype === 'block') {
         try {
-            $blockname = substr($plugin, strlen('block/'));
-            if ($block = $DB->get_record('block', array('name'=>$blockname))) {
-                $version = $block->version;
+            if ($block = $DB->get_record('block', array('name'=>$pluginname))) {
+                $currentversion = $block->version;
             }
         } catch (Exception $ignored) {
         }
+        $cd = get_component_directory($component);
+        if (file_exists("$cd/version.php")) {
+            $plugin = new stdClass();
+            $plugin->version = null;
+            include("$cd/version.php");
+            $targetversion = $plugin->version;
+        }
 
     } else {
-        $pluginversion = get_config(str_replace('/', '_', $plugin), 'version');
+        $pluginversion = get_config($component, 'version');
         if (!empty($pluginversion)) {
-            $version = $pluginversion;
+            $currentversion = $pluginversion;
+        }
+        $cd = get_component_directory($component);
+        if (file_exists("$cd/version.php")) {
+            $plugin = new stdClass();
+            $plugin->version = null;
+            include("$cd/version.php");
+            $targetversion = $plugin->version;
         }
     }
 
     $log = new stdClass();
-    $log->type         = $type;
-    $log->plugin       = $plugin;
-    $log->version      = $version;
-    $log->info         = $info;
-    $log->details      = $details;
-    $log->backtrace    = $backtrace;
-    $log->userid       = $USER->id;
-    $log->timemodified = time();
+    $log->type          = $type;
+    $log->plugin        = $component;
+    $log->version       = $currentversion;
+    $log->targetversion = $targetversion;
+    $log->info          = $info;
+    $log->details       = $details;
+    $log->backtrace     = $backtrace;
+    $log->userid        = $USER->id;
+    $log->timemodified  = time();
     try {
         $DB->insert_record('upgrade_log', $log);
     } catch (Exception $ignored) {
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 425be29..5654214 100644 (file)
@@ -48,7 +48,7 @@ $PAGE->set_pagelayout('base');
 /// Check to see if groups are being used here
  if ($groupmode = groups_get_activity_groupmode($cm)) {   // Groups are being used
     if ($groupid = groups_get_activity_group($cm)) {
-        if (!$group = groups_get_group($groupid, false)) {
+        if (!$group = groups_get_group($groupid)) {
             print_error('invalidgroupid');
         }
         $groupname = ': '.$group->name;
index 8da232b..92621f9 100644 (file)
@@ -33,7 +33,7 @@ require_capability('mod/chat:chat', $context);
 /// Check to see if groups are being used here
  if ($groupmode = groups_get_activity_groupmode($cm)) {   // Groups are being used
     if ($groupid = groups_get_activity_group($cm)) {
-        if (!$group = groups_get_group($groupid, false)) {
+        if (!$group = groups_get_group($groupid)) {
             print_error('invalidgroupid');
         }
         $groupname = ': '.$group->name;
index b6c014a..78b8339 100644 (file)
@@ -33,7 +33,7 @@ if (isguestuser()) {
 /// Check to see if groups are being used here
  if ($groupmode = groups_get_activity_groupmode($cm)) {   // Groups are being used
     if ($groupid = groups_get_activity_group($cm)) {
-        if (!$group = groups_get_group($groupid, false)) {
+        if (!$group = groups_get_group($groupid)) {
             print_error('invalidgroupid');
         }
         $groupname = ': '.$group->name;
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 7020d38..aefe77d 100644 (file)
             return null;
         }
 
-        if (!is_enrolled($context, null, 'mod/data:managetemplates') && !isguestuser()) {
-            return null;
+        $dataid = clean_param($args[3], PARAM_INT);
+        $cm = get_coursemodule_from_instance('data', $dataid, 0, false, MUST_EXIST);
+        if ($cm) {
+            $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
+
+            //context id from db should match the submitted one
+            if ($context->id != $modcontext->id || !has_capability('mod/data:viewentry', $modcontext)) {
+                return null;
+            }
         }
 
-        $dataid = clean_param($args[3], PARAM_INT);
         $data = $DB->get_record('data', array('id' => $dataid), '*', MUST_EXIST);
-
         if (!rss_enabled_for_mod('data', $data, false, true)) {
             return null;
         }
index 90cf012..9a1ee1e 100755 (executable)
@@ -29,7 +29,8 @@ require_once('lib.php');
 $id    = optional_param('id', 0, PARAM_INT);  // course module id
 $d     = optional_param('d', 0, PARAM_INT);   // database id
 $mode  = optional_param('mode', 'singletemplate', PARAM_ALPHA);
-$disableeditor  = optional_param('switcheditor', false, PARAM_ALPHA);
+$disableeditor = optional_param('switcheditor', false, PARAM_RAW);
+$enableeditor = optional_param('useeditor', false, PARAM_RAW);
 
 $url = new moodle_url('/mod/data/templates.php');
 if ($mode !== 'singletemplate') {
@@ -130,10 +131,13 @@ if (($mytemplate = data_submitted()) && confirm_sesskey()) {
 
         // Check for multiple tags, only need to check for add template.
         if ($mode != 'addtemplate' or data_tags_check($data->id, $newtemplate->{$mode})) {
-            $DB->update_record('data', $newtemplate);
-            echo $OUTPUT->notification(get_string('templatesaved', 'data'), 'notifysuccess');
+            // if disableeditor or enableeditor buttons click, don't save instance
+            if (empty($disableeditor) && empty($enableeditor)) {
+                $DB->update_record('data', $newtemplate);
+                echo $OUTPUT->notification(get_string('templatesaved', 'data'), 'notifysuccess');
+                add_to_log($course->id, 'data', 'templates saved', "templates.php?id=$cm->id&amp;d=$data->id", $data->id, $cm->id);
+            }
         }
-        add_to_log($course->id, 'data', 'templates saved', "templates.php?id=$cm->id&amp;d=$data->id", $data->id, $cm->id);
     }
 } else {
     echo '<div class="littleintro" style="text-align:center">'.get_string('header'.$mode,'data').'</div>';
index 037f9fd..d94443d 100755 (executable)
@@ -666,7 +666,7 @@ if ($showactivity) {
                 require_once($CFG->dirroot.'/rating/lib.php');
                 if ($data->assessed!=RATING_AGGREGATE_NONE) {
                     $ratingoptions = new stdclass();
-                    $ratingoptions->context = $cm->context;
+                    $ratingoptions->context = $context;
                     $ratingoptions->items = $records;
                     $ratingoptions->aggregate = $data->assessed;//the aggregation method
                     $ratingoptions->scaleid = $data->scale;
index 105160a..b4cd545 100644 (file)
@@ -150,7 +150,6 @@ $string['item_name'] = 'Question';
 $string['items_are_required'] = 'Answers are required to starred questions.';
 $string['label'] = 'Label';
 $string['line_values'] = 'Rating';
-$string['mapcourse'] = 'Map course';
 $string['mapcourseinfo'] = 'This is a site-wide feedback that is available to all courses using the feedback block. You can however limit the courses to which it will appear by mapping them. Search the course and map it to this feedback.';
 $string['mapcoursenone'] = 'No courses mapped. Feedback available to all courses';
 $string['mapcourse'] = 'Map feedback to courses';
index df7c7cd..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;
         }
@@ -5318,7 +5318,7 @@ function forum_print_discussion($course, $cm, $forum, $discussion, $post, $mode,
     //load ratings
     if ($forum->assessed!=RATING_AGGREGATE_NONE) {
         $ratingoptions = new stdclass();
-        $ratingoptions->context = $cm->context;
+        $ratingoptions->context = $modcontext;
         $ratingoptions->items = $posts;
         $ratingoptions->aggregate = $forum->assessed;//the aggregation method
         $ratingoptions->scaleid = $forum->scale;
index dbdf73e..7115fe7 100644 (file)
@@ -44,25 +44,17 @@ function forum_rss_get_feed($context, $args) {
     }
 
     $forumid  = clean_param($args[3], PARAM_INT);
-
-    $uservalidated = false;
-
     $cm = get_coursemodule_from_instance('forum', $forumid, 0, false, MUST_EXIST);
     if ($cm) {
         $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
 
         //context id from db should match the submitted one
-        if ($context->id==$modcontext->id && has_capability('mod/forum:viewdiscussion', $modcontext)) {
-            $uservalidated = true;
+        if ($context->id != $modcontext->id || !has_capability('mod/forum:viewdiscussion', $modcontext)) {
+            return null;
         }
     }
 
-    if (!$uservalidated) {
-        return null;
-    }
-
     $forum = $DB->get_record('forum', array('id' => $forumid), '*', MUST_EXIST);
-
     if (!rss_enabled_for_mod('forum', $forum)) {
         return null;
     }
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 b9b51dd..3ab155d 100644 (file)
@@ -6,22 +6,26 @@
     function glossary_rss_get_feed($context, $args) {
         global $CFG, $DB;
 
+        $status = true;
+
         if (empty($CFG->glossary_enablerssfeeds)) {
             debugging("DISABLED (module configuration)");
             return null;
         }
 
-        $status = true;
+        $glossaryid  = clean_param($args[3], PARAM_INT);
+        $cm = get_coursemodule_from_instance('glossary', $glossaryid, 0, false, MUST_EXIST);
+        if ($cm) {
+            $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
 
-        //check capabilities
-        //glossary module doesn't require any capabilities to view glossary entries (aside from being logged in)
-        if (!is_enrolled($context) && !isguestuser()) {
-            return null;
+            //context id from db should match the submitted one
+            //no specific capability required to view glossary entries so just check user is enrolled
+            if ($context->id != $modcontext->id || !is_enrolled($context)) {
+                return null;
+            }
         }
 
-        $glossaryid  = clean_param($args[3], PARAM_INT);
         $glossary = $DB->get_record('glossary', array('id' => $glossaryid), '*', MUST_EXIST);
-
         if (!rss_enabled_for_mod('glossary', $glossary)) {
             return null;
         }
index b20a98e..236a525 100644 (file)
@@ -395,7 +395,7 @@ if ($allentries) {
     require_once($CFG->dirroot.'/rating/lib.php');
     if ($glossary->assessed!=RATING_AGGREGATE_NONE) {
         $ratingoptions = new stdclass();
-        $ratingoptions->context = $cm->context;
+        $ratingoptions->context = $context;
         $ratingoptions->items = $allentries;
         $ratingoptions->aggregate = $glossary->assessed;//the aggregation method
         $ratingoptions->scaleid = $glossary->scale;
index c7839b7..e9bffb8 100644 (file)
@@ -56,8 +56,30 @@ if ($edit) {
 $jumpto = lesson_page::get_jumptooptions($pageid, $lesson);
 $manager = lesson_page_type_manager::get($lesson);
 $editoroptions = array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$CFG->maxbytes);
+
+// If the previous page was the Question type selection form, this form
+// will have a different name (e.g. _qf__lesson_add_page_form_selection
+// versus _qf__lesson_add_page_form_multichoice). This causes confusion
+// in moodleform::_process_submission because the array key check doesn't
+// tie up with the current form name, which in turn means the "submitted"
+// check ends up evaluating as false, thus it's not possible to check whether
+// the Question type selection was cancelled. For this reason, a dummy form
+// is created here solely to check whether the selection was cancelled. 
+if ($qtype) {
+    $mformdummy = $manager->get_page_form(0, array('editoroptions'=>$editoroptions, 'jumpto'=>$jumpto, 'lesson'=>$lesson, 'edit'=>$edit, 'maxbytes'=>$PAGE->course->maxbytes));
+    if ($mformdummy->is_cancelled()) {
+        redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$id");
+        exit;
+    }
+}
+
 $mform = $manager->get_page_form($qtype, array('editoroptions'=>$editoroptions, 'jumpto'=>$jumpto, 'lesson'=>$lesson, 'edit'=>$edit, 'maxbytes'=>$PAGE->course->maxbytes));
 
+if ($mform->is_cancelled()) {
+    redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$id");
+    exit;
+}
+
 if ($edit) {
     $data = $editpage->properties();
     $data->pageid = $editpage->id;
index 2e1bb06..0cbbfec 100644 (file)
@@ -57,16 +57,18 @@ class quiz_report_overview_table extends table_sql {
                 $this->add_data_keyed($groupaveragerow);
             }
 
-            list($s_usql, $s_params) = $DB->get_in_or_equal($this->students);
-            $overallaverage = $DB->get_record_sql($averagesql." AND qg.userid $s_usql", array_merge($params, $s_params));
-            $overallaveragerow = array($namekey => get_string('overallaverage', 'grades'),
-                        'sumgrades' => quiz_format_grade($this->quiz, $overallaverage->grade),
-                        'feedbacktext'=> strip_tags(quiz_report_feedback_for_grade($overallaverage->grade, $this->quiz->id, $this->context)));
-            if($this->detailedmarks && ($this->qmsubselect || $this->quiz->attempts == 1)) {
-                $avggradebyq = quiz_get_average_grade_for_questions($this->quiz, $this->students);
-                $overallaveragerow += quiz_format_average_grade_for_questions($avggradebyq, $this->questions, $this->quiz, $this->is_downloading());
+            if ($this->students) {
+                list($s_usql, $s_params) = $DB->get_in_or_equal($this->students);
+                $overallaverage = $DB->get_record_sql($averagesql." AND qg.userid $s_usql", array_merge($params, $s_params));
+                $overallaveragerow = array($namekey => get_string('overallaverage', 'grades'),
+                            'sumgrades' => quiz_format_grade($this->quiz, $overallaverage->grade),
+                            'feedbacktext'=> strip_tags(quiz_report_feedback_for_grade($overallaverage->grade, $this->quiz->id, $this->context)));
+                if($this->detailedmarks && ($this->qmsubselect || $this->quiz->attempts == 1)) {
+                    $avggradebyq = quiz_get_average_grade_for_questions($this->quiz, $this->students);
+                    $overallaveragerow += quiz_format_average_grade_for_questions($avggradebyq, $this->questions, $this->quiz, $this->is_downloading());
+                }
+                $this->add_data_keyed($overallaveragerow);
             }
-            $this->add_data_keyed($overallaveragerow);
         }
     }
 
index 15e0ec5..125bb28 100644 (file)
@@ -82,6 +82,5 @@ $string['printintro'] = 'Display resource description';
 $string['printintroexplain'] = 'Display resource description bellow content? Some display types may not display description even if enabled.';
 $string['resourcecontent'] = 'Files and subfolders';
 $string['resource:exportresource'] = 'Export resource';
-$string['resource:view'] = 'View resource files';
 $string['resource:view'] = 'View resource';
 $string['selectmainfile'] = 'Please select the main file by clicking the icon next to file name.';
index f9a819c..5a2069c 100644 (file)
@@ -51,7 +51,6 @@ $string['editblocks'] = 'Turn edit blocks on';
 $string['editing'] = 'Editing wiki page';
 $string['editingcomment'] = 'Editing comment';
 $string['editingpage'] = 'Editing this page \'{$a}\'';
-$string['editblocks'] = 'Turn edit blocks on';
 $string['filenotuploadederror'] = 'File \'{$a}\' could not be uploaded correctly.';
 $string['filtername'] = 'Wiki auto-linking';
 $string['firstpagetitle'] = 'First page name';
index 7fa6378..fb623a2 100644 (file)
@@ -335,42 +335,6 @@ class workshop_manual_allocator implements workshop_allocator {
     public static function delete_instance($workshopid) {
         return;
     }
-
-    /**
-     * Returns the list of all allocations where the given users are involved
-     *
-     * We must use recordset here because we do not have any unique identifier available
-     *
-     * @param array [userid] => whatever
-     * @return moodle_recordset|null
-     */
-    protected function get_allocations_recordset(array $users) {
-        global $DB, $PAGE;
-
-        if (empty($users)) {
-            return null;
-        }
-
-        list($authorids, $authorparams)     = $DB->get_in_or_equal(array_keys($users), SQL_PARAMS_NAMED, 'a0000');
-        list($reviewerids, $reviewerparams) = $DB->get_in_or_equal(array_keys($users), SQL_PARAMS_NAMED, 'r0000');
-        $params = array_merge($authorparams, $reviewerparams);
-        $params['workshopid'] = $this->workshop->id;
-
-        $sql = "SELECT author.id AS authorid, author.firstname AS authorfirstname, author.lastname AS authorlastname,
-                       author.picture AS authorpicture, author.imagealt AS authorimagealt, author.email AS authoremail,
-                       s.id AS submissionid, s.title AS submissiontitle, s.grade AS submissiongrade,
-                       a.id AS assessmentid, a.timecreated AS timeallocated, a.reviewerid,
-                       reviewer.firstname AS reviewerfirstname, reviewer.lastname AS reviewerlastname,
-                       reviewer.picture as reviewerpicture, reviewer.imagealt AS reviewerimagealt
-                  FROM {user} author
-             LEFT JOIN {workshop_submissions} s ON (s.authorid = author.id)
-             LEFT JOIN {workshop_assessments} a ON (s.id = a.submissionid)
-             LEFT JOIN {user} reviewer ON (a.reviewerid = reviewer.id)
-                 WHERE (author.id $authorids OR reviewer.id $reviewerids) AND (s.id IS NULL OR s.workshopid = :workshopid)
-              ORDER BY author.lastname,author.firstname,author.id,reviewer.lastname,reviewer.firstname,reviewer.id";
-
-        return $DB->get_recordset_sql($sql, $params);
-    }
 }
 
 /**
index 0582feb..3914186 100644 (file)
     background-color: #eee;
 }
 
+.path-mod-workshop .manual-allocator .allocations .r0.highlightreviewerof,
+.path-mod-workshop .manual-allocator .allocations .r0.highlightreviewedby {
+    background-color: inherit;
+}
+
 .path-mod-workshop .manual-allocator .allocations .peer .image {
     margin-right: 5px;
     vertical-align: middle;
index 13a4185..12f6dd3 100644 (file)
@@ -409,7 +409,7 @@ class workshop_random_allocator implements workshop_allocator {
      *      (bool)excludesamegroup - whether to prevent peer submissions from the same group in visible group mode
      *
      * @param array    $authors      structure of grouped authors
-     * @param resource $reviewers    structure of grouped reviewers
+     * @param array    $reviewers    structure of grouped reviewers
      * @param array    $assessments  currently assigned assessments to be kept
      * @param array    $o            reference to an array of log messages
      * @param array    $options      allocation options
index 3762e41..b462035 100644 (file)
@@ -31,7 +31,7 @@ require_once($CFG->dirroot.'/lib/formslib.php');
 /**
  * Allocator settings form
  *
- * This is used by {@see workshop_random_allocator::ui()} to set up allocation paramters.
+ * This is used by {@see workshop_random_allocator::ui()} to set up allocation parameters.
  *
  * @copyright 2009 David Mudrak <david.mudrak@gmail.com>
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
index 4592290..83aded8 100644 (file)
@@ -1305,9 +1305,9 @@ function workshop_get_file_info($browser, $areas, $course, $cm, $context, $filea
  * @param navigation_node $navref An object representing the navigation tree node of the workshop module instance
  * @param stdClass $course
  * @param stdClass $module
- * @param stdClass $cm
+ * @param cm_info $cm
  */
-function workshop_extend_navigation(navigation_node $navref, stdclass $course, stdclass $module, stdclass $cm) {
+function workshop_extend_navigation(navigation_node $navref, stdclass $course, stdclass $module, cm_info $cm) {
     global $CFG;
 
     if (has_capability('mod/workshop:submit', get_context_instance(CONTEXT_MODULE, $cm->id))) {
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 4ceafe6..f30b2af 100644 (file)
@@ -23,7 +23,7 @@
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-$string['apikey'] = 'API Key';
+$string['apikey'] = 'API key';
 $string['boxnet:view'] = 'View box.net repository';
 $string['configplugin'] = 'Box.net configuration';
 $string['information'] = 'Get an API key from the <a href="http://www.box.net/developers/services">Box.net developer page</a> for your Moodle site.';
index 71f4433..58f79e1 100755 (executable)
@@ -27,8 +27,8 @@ $string['configplugin'] = 'Dropbox configuration';
 $string['notitle'] = 'notitle';
 $string['remember'] = 'Remember me';
 $string['pluginname'] = 'Dropbox';
-$string['apikey'] = 'Dropbox API Key';
+$string['apikey'] = 'Dropbox API key';
 $string['dropbox'] = 'Dropbox';
-$string['secret'] = 'Dropbox Secret';
+$string['secret'] = 'Dropbox secret';
 $string['instruction'] = 'You can get your API Key and secret from <a href="http://www.dropbox.com/developers/apps">Dropbox developers</a>';
 $string['dropbox:view'] = 'View a Dropbox folder';
index 145a4b9..1b79768 100644 (file)
 $string['all'] = 'All';
 $string['apikey'] = 'API key';
 $string['backtosearch'] = 'Back to search screen';
-$string['by'] = 'Attribution License';
-$string['by-nc'] = 'Attribution-NonCommercial License';
-$string['by-nc-nd'] = 'Attribution-NonCommercial-NoDerivs License';
-$string['by-nc-sa'] = 'Attribution-NonCommercial-ShareAlike License';
-$string['by-nd'] = 'Attribution-NoDerivs License';
-$string['by-sa'] = 'Attribution-ShareAlike License';
+$string['by'] = 'Attribution license';
+$string['by-nc'] = 'Attribution-NonCommercial license';
+$string['by-nc-nd'] = 'Attribution-NonCommercial-NoDerivs license';
+$string['by-nc-sa'] = 'Attribution-NonCommercial-ShareAlike license';
+$string['by-nd'] = 'Attribution-NoDerivs license';
+$string['by-sa'] = 'Attribution-ShareAlike license';
 $string['callbackurl'] = 'Callback URL';
 $string['commercialuse'] = 'I want to be able to use the images commercially';
 $string['configplugin'] = 'Flickr public configuration';
 $string['creativecommonscommercial'] = 'Only creative commons commercial';
 $string['emailaddress'] = 'Email address';
-$string['flickr_public:view'] = 'View flickr_public repository';
+$string['flickr_public:view'] = 'Use Flickr public repository in file picker';
 $string['fulltext'] = 'Full text';
 $string['information'] = '<div>Get a <a href="http://www.flickr.com/services/api/keys/">Flickr API Key</a> for your Moodle site. </div>';
 $string['invalidemail'] = 'Invalid email account for flickr';
index f062b74..484ce01 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 $string['configplugin'] = 'Merlot.org configuration';
-$string['licensekey'] = 'License Key';
+$string['licensekey'] = 'License key';
 $string['pluginname_help'] = 'Merlot.org';
 $string['pluginname'] = 'Merlot.org';
 $string['merlot:view'] = 'View the Merlot repository';
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 1b20da1..defc6aa 100644 (file)
@@ -25,8 +25,8 @@
 
 $string['download'] = 'Download';
 $string['rename'] = 'Name';
-$string['pluginname'] = 'URL Downloader';
+$string['pluginname'] = 'URL downloader';
 $string['url'] = 'URL';
-$string['url:view'] = 'Use url downloader in file picker';
+$string['url:view'] = 'Use URL downloader in file picker';
 $string['validname'] = 'You must provide a valid file name';
 $string['configplugin'] = 'URL repository type configuration';
index c1d96c3..a28f1bd 100644 (file)
@@ -813,59 +813,94 @@ function tag_cleanup() {
  * It works as a cache for a potentially heavy load query done at the 'tag_instance' table.
  * So, the 'tag_correlation' table stores redundant information derived from the 'tag_instance' table.
  *
- * @param number $min_correlation cutoff percentage (optional, default is 2)
+ * @global moodle_database $DB
+ * @param int $mincorrelation Only tags with more than $mincorrelation correlations will
+ *                             be identified.
+ * @return void
  */
-function tag_compute_correlations($min_correlation=2) {
+function tag_compute_correlations($mincorrelation = 2) {
     global $DB;
 
-    if (!$all_tags = $DB->get_records('tag')) {
-        return;
+    // This mighty one line query fetches a row from the database for every
+    // individual tag correlation. We then need to process the rows collecting
+    // the correlations for each tag id.
+    // The fields used by this query are as follows:
+    //   tagid         : This is the tag id, there should be at least $mincorrelation
+    //                   rows for each tag id.
+    //   correlation   : This is the tag id that correlates to the above tagid field.
+    //   correlationid : This is the id of the row in the tag_correlation table that
+    //                   relates to the tagid field and will be NULL if there are no
+    //                   existing correlations
+    $sql = 'SELECT ta.tagid, tb.tagid AS correlation, co.id AS correlationid, co.correlatedtags 
+              FROM {tag_instance} ta 
+         LEFT JOIN {tag_instance} tb 
+                ON (ta.itemtype = tb.itemtype AND ta.itemid = tb.itemid AND ta.tagid <> tb.tagid) 
+         LEFT JOIN {tag_correlation} co 
+                ON co.tagid = ta.tagid 
+             WHERE tb.tagid IS NOT NULL 
+          GROUP BY ta.tagid, tb.tagid 
+            HAVING COUNT(*) > :mincorrelation 
+          ORDER BY ta.tagid ASC, COUNT(*) DESC, tb.tagid ASC';
+    $rs = $DB->get_recordset_sql($sql, array('mincorrelation' => $mincorrelation));
+
+    // Set up an empty tag correlation object
+    $tagcorrelation = new stdClass;
+    $tagcorrelation->id = null;
+    $tagcorrelation->tagid = null;
+    $tagcorrelation->correlatedtags = array();
+
+    // Iterate each row of the result set and build them into tag correlations.
+    foreach ($rs as $row) {
+        if ($row->tagid != $tagcorrelation->tagid) {
+            // The tag id has changed so its now time to process the tag
+            // correlation information we have.
+            tag_process_computed_correlation($tagcorrelation);
+            // Now we reset the tag correlation object so we can reuse it and set it
+            // up for the current record.
+            $tagcorrelation = new stdClass;
+            $tagcorrelation->id = $row->correlationid;
+            $tagcorrelation->tagid = $row->tagid;
+            $tagcorrelation->correlatedtags = array();
+        }
+        $tagcorrelation->correlatedtags[] = $row->correlation;
     }
+    // Update the current correlation after the last record.
+    tag_process_computed_correlation($tagcorrelation);
 
-    $tag_correlation_obj = new stdClass();
-    foreach($all_tags as $tag) {
-
-        // query that counts how many times any tag appears together in items
-        // with the tag passed as argument ($tag_id)
-        $query = "SELECT tb.tagid
-                    FROM {tag_instance} ta JOIN {tag_instance} tb ON ta.itemid = tb.itemid
-                   WHERE ta.tagid = ? AND tb.tagid <> ?
-                GROUP BY tb.tagid
-                  HAVING COUNT(*) > ?
-                ORDER BY COUNT(*) DESC";
-        $params = array($tag->id, $tag->id, $min_correlation);
-
-        $correlated = array();
-
-        // Correlated tags happen when they appear together in more occasions
-        // than $min_correlation.
-        if ($tag_correlations = $DB->get_records_sql($query, $params)) {
-            foreach($tag_correlations as $correlation) {
-            // commented out - now done in query. kept here in case it breaks on some db
-            // if($correlation->nr >= $min_correlation){
-                    $correlated[] = $correlation->tagid;
-            // }
-            }
-        }
+    // Close the recordset
+    $rs->close();
+}
 
-        if (empty($correlated)) {
-            continue;
-        }
+/**
+ * This function processes a tag correlation and makes changes in the database
+ * as required.
+ *
+ * The tag correlation object needs have both a tagid property and a correlatedtags
+ * property that is an array.
+ *
+ * @param stdClass $tagcorrelation
+ * @return bool True if the function completed, false if something was wrong.
+ */
+function tag_process_computed_correlation(stdClass $tagcorrelation) {
+    global $DB;
 
-        $correlated = implode(',', $correlated);
-        //var_dump($correlated);
+    // You must provide a tagid and correlatedtags must be set and be an array
+    if (empty($tagcorrelation->tagid) || !isset($tagcorrelation->correlatedtags) || !is_array($tagcorrelation->correlatedtags)) {
+        return false;
+    }
 
-        //saves correlation info in the caching table
-        if ($tag_correlation_obj = $DB->get_record('tag_correlation', array('tagid'=>$tag->id), 'id')) {
-            $tag_correlation_obj->correlatedtags = $correlated;
-            $DB->update_record('tag_correlation', $tag_correlation_obj);
-        } else {
-            $tag_correlation_obj = new stdClass();
-            $tag_correlation_obj->tagid          = $tag->id;
-            $tag_correlation_obj->correlatedtags = $correlated;
-            $DB->insert_record('tag_correlation', $tag_correlation_obj);
-        }
+    // The row tagid doesn't match the current tag id which means we are onto
+    // the next tag. Before we switch over we need to either insert or update
+    // the correlation.
+    $tagcorrelation->correlatedtags = join(',', $tagcorrelation->correlatedtags);
+    if (!empty($tagcorrelation->id)) {
+        // The tag correlation already exists so update it
+        $DB->update_record('tag_correlation', $tagcorrelation);
+    } else {
+        // This is a new correlation to insert
+        $DB->insert_record('tag_correlation', $tagcorrelation);
     }
+    return true;
 }
 
 /**
index 26da20b..d64172f 100644 (file)
@@ -24,7 +24,8 @@
  */
 
 
-$string['choosereadme'] = '<div class="clearfix"><div class="theme_screenshot"><h2>Splash</h2><img src="splash/pix/screenshot.jpg" /><h3>Theme Discussion Forum:</h3><p><a href="http://moodle.org/mod/forum/view.php?id=46">http://moodle.org/mod/forum/view.php?id=46</a></p><h3>Theme Credits</h3><p><a href="http://docs.moodle.org/en/Theme_credits">http://docs.moodle.org/en/Theme_credits</a></p><h3>Theme Documentation:</h3><p><a href="http://docs.moodle.org/en/Themes">http://docs.moodle.org/en/Themes</a></p><h3>Report a bug:</h3><p><a href="http://tracker.moodle.org">http://tracker.moodle.org</a></p></div><div class="theme_description"><h2>About</h2><p>Splash is a fluid-width, three-column theme for Moodle 2.0.<h2>Tweaks</h2><p>This theme is built upon both Base and Canvas, two parent themes included in the Moodle core. If you want to modify this theme, we recommend that you first duplicate it then rename it before making your changes. This will prevent your customized theme from being overwritten by future Moodle upgrades, and you\'ll still have the original files if you make a mess. More information on modifying themes can be found in the <a href="http://docs.moodle.org/en/Theme">MoodleDocs</a>.</p><h2>Credits</h2>        <p>This theme was coded and is maintained by Caroline Kennedy of Synergy Learning. She can be contacted by email at caroline.kennedy@synergy-learningw.com. </p><h2>License</h2><p>This, and all other themes included in the Moodle core, are licensed under the <a href="http://www.gnu.org/licenses/gpl.html">GNU General Public License</a>.</div></div>';$string['configtitle'] = 'Splash Theme Settings';
+$string['choosereadme'] = '<div class="clearfix"><div class="theme_screenshot"><h2>Splash</h2><img src="splash/pix/screenshot.jpg" /><h3>Theme Discussion Forum:</h3><p><a href="http://moodle.org/mod/forum/view.php?id=46">http://moodle.org/mod/forum/view.php?id=46</a></p><h3>Theme Credits</h3><p><a href="http://docs.moodle.org/en/Theme_credits">http://docs.moodle.org/en/Theme_credits</a></p><h3>Theme Documentation:</h3><p><a href="http://docs.moodle.org/en/Themes">http://docs.moodle.org/en/Themes</a></p><h3>Report a bug:</h3><p><a href="http://tracker.moodle.org">http://tracker.moodle.org</a></p></div><div class="theme_description"><h2>About</h2><p>Splash is a fluid-width, three-column theme for Moodle 2.0.<h2>Tweaks</h2><p>This theme is built upon both Base and Canvas, two parent themes included in the Moodle core. If you want to modify this theme, we recommend that you first duplicate it then rename it before making your changes. This will prevent your customized theme from being overwritten by future Moodle upgrades, and you\'ll still have the original files if you make a mess. More information on modifying themes can be found in the <a href="http://docs.moodle.org/en/Theme">MoodleDocs</a>.</p><h2>Credits</h2>        <p>This theme was coded and is maintained by Caroline Kennedy of Synergy Learning. She can be contacted by email at caroline.kennedy@synergy-learningw.com. </p><h2>License</h2><p>This, and all other themes included in the Moodle core, are licensed under the <a href="http://www.gnu.org/licenses/gpl.html">GNU General Public License</a>.</div></div>';
+$string['configtitle'] = 'Splash Theme Settings';
 $string['customcss'] = 'Custom CSS';
 $string['customcssdesc'] = 'Any CSS you enter here will be added to every page allowing your to easily customise this theme.';
 $string['defaulttagline'] = 'Virtual learning center';
@@ -32,7 +33,7 @@ $string['footnote'] = 'Footnote';
 $string['footnotedesc'] = 'The content from this textarea will be displayed in the footer of every page. E.g: your copyright info.';
 $string['hide_tagline'] = 'Hide Tagline';
 $string['hide_taglinedesc'] = 'Check this box to hide the tagline under the logo.';
-$string['loginhere'] = "Login here!";
+$string['loginhere'] = 'Login here!';
 $string['logo'] = 'Logo';
 $string['logodesc'] = 'Enter the URL to an image to use as the logo for this site. E.g: http://www.yoursite.com/path/to/logo.png. The logo should be max 230px wide.';
 $string['pluginname'] = 'Splash';
@@ -41,4 +42,4 @@ $string['region-side-pre'] = 'Left';
 $string['tagline'] = 'Tagline';
 $string['taglinedesc'] = 'The content from this textarea will be displayed under the Site logo on the Homepage';
 $string['usergreeting'] = 'Hi {$a}!';
-$string['welcome'] = 'Welcome, {$a}';
\ No newline at end of file
+$string['welcome'] = 'Welcome, {$a}';
index b75b947..d0a9077 100644 (file)
@@ -107,7 +107,10 @@ body.splash-blue {                /* Define margins and background colour/image
 /* Forum
 ------------------------*/
 
-.splash-blue .forumpost .topic .subject {    /* forum subject section inside topic header */
+.splash-blue .forumpost .topic .subject,
+.path-blog.splash-blue .forumpost .subject a,
+.path-blog.splash-blue .forumpost .subject a:link,
+.path-blog.splash-blue .forumpost .subject a:visited {    /* forum subject section inside topic header */
     font-weight: bold;
     font-size: 1.1em;
     padding-left: 5px;
index 00ddefe..47d410e 100644 (file)
@@ -9,7 +9,6 @@
 
 /* Global 
 ------------------------*/
-
 body.splash-green {                /* Define margins and background colour/image */
     background: url([[pix:theme|bggreen]]) top left repeat-x #f4f4f4;
     margin: 0 auto;
@@ -17,7 +16,6 @@ body.splash-green {                /* Define margins and background colour/image
     width: 100%;
 }
 
-
 .splash-green a:link {        /* Defining all link styles*/
     color: #446e4c;
 }
@@ -36,7 +34,6 @@ body.splash-green {                /* Define margins and background colour/image
 
 /* Header 
 -----------------------*/
-
 .splash-green #page-header {            /* Set height for header */
     float: none;
     padding: 0;
@@ -46,7 +43,6 @@ body.splash-green {                /* Define margins and background colour/image
     background: url([[pix:theme|pageheaderbggreen]]) top center no-repeat;
 }
 
-
 .splash-green #logobox{  /* holder background for logo*/
     height: 185px;
     width: 252px;
@@ -56,8 +52,6 @@ body.splash-green {                /* Define margins and background colour/image
     float: left;
 }
 
-
-
 .splash-green #colourswitcher p{
     color:#446e4c;
 }
@@ -83,12 +77,9 @@ body.splash-green {                /* Define margins and background colour/image
 
 }
 
-
 .splash-green .coursebox{
     padding-left:5px;
     border-bottom: 1px dashed #dae0dc;
-
-
 }
 
 /* Sideblocks
@@ -100,21 +91,21 @@ body.splash-green {                /* Define margins and background colour/image
     color: #fff;
 }
 
-
-
 /* Mini Calendar
 ------------------------*/
 .splash-green .block .minicalendar td.weekend {    /* setting weekend date colour */
     color:#446e4c;
 }
 
-
 /* Forum
 ------------------------*/
-.splash-green .forumpost .topic .subject {    /* forum subject section inside topic header */
+.splash-green .forumpost .topic .subject,
+.path-blog.splash-green .forumpost .subject a,
+.path-blog.splash-green .forumpost .subject a:link,
+.path-blog.splash-green .forumpost .subject a:visited {    /* forum subject section inside topic header */
     font-weight: bold;
     font-size: 1.1em;
     padding-left: 5px;
     background:  #446e4c;
     color: #fff;
-}
+}
\ No newline at end of file
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 55fee3c..e8172ec 100644 (file)
@@ -31,6 +31,8 @@ class user_filter_courserole extends user_filter_type {
      * @return array of course categories
      */
     function get_course_categories() {
+        global $CFG;
+        require_once($CFG->dirroot.'/course/lib.php');
         $displaylist = array();
         $parentlist = array();
         make_categories_list($displaylist, $parentlist);
index e5a083a..c91e04e 100644 (file)
@@ -37,9 +37,7 @@ $hide     = optional_param('hide', 0, PARAM_INT);
 $courseid = optional_param('courseid', SITEID, PARAM_INT);
 
 $url = new moodle_url('/user/portfolio.php', array('courseid'=>$courseid));
-if ($hide !== 0) {
-    $url->param('hide', $hide);
-}
+
 if ($config !== 0) {
     $url->param('config', $config);
 }
@@ -69,6 +67,7 @@ echo $OUTPUT->header();
 $showroles = 1;
 
 if (!empty($config)) {
+    navigation_node::override_active_url(new moodle_url('/user/portfolio.php', array('courseid'=>$courseid)));
     $instance = portfolio_instance($config);
     $mform = new portfolio_user_form('', array('instance' => $instance, 'userid' => $user->id));
     if ($mform->is_cancelled()){
index 3993261..1690b1f 100644 (file)
@@ -48,6 +48,8 @@ $strportfolios = get_string('portfolios', 'portfolio');
 
 $url = new moodle_url('/user/portfoliologs.php', array('courseid'=>$courseid));
 
+navigation_node::override_active_url(new moodle_url('/user/portfoliologs.php', array('courseid'=>$courseid)));
+
 if ($page !== 0) {
     $url->param('page', $page);
 }
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 d893cb3..ab374d9 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version = 2011020200;  // 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: 20110204)';  // Human-friendly version name
+$release = '2.0.1+ (Build: 20110209)';  // Human-friendly version name