Merge branch 'MDL-26643' of git://github.com/nebgor/moodle
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 14 Mar 2011 00:57:08 +0000 (01:57 +0100)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 14 Mar 2011 00:57:08 +0000 (01:57 +0100)
34 files changed:
admin/replace.php
admin/user.php
auth/ldap/lang/en/auth_ldap.php
backup/moodle2/backup_theme_plugin.class.php
blocks/html/lib.php
course/modedit.php
filter/algebra/algebra2tex.pl [changed mode: 0644->0755]
filter/algebra/filter.php
filter/tex/db/upgrade.php [new file with mode: 0644]
filter/tex/displaytex.php
filter/tex/filter.php
filter/tex/filtersettings.php
filter/tex/lang/en/filter_tex.php
filter/tex/lib.php
filter/tex/pix.php
filter/tex/texdebug.php
filter/tex/version.php
install/lang/de_kids/langconfig.php [new file with mode: 0644]
install/lang/pl/admin.php
install/lang/pl/install.php
lib/adminlib.php
lib/completionlib.php
lib/enrollib.php
lib/excellib.class.php
lib/weblib.php
mod/forum/lang/en/forum.php
mod/forum/lib.php
mod/quiz/attemptlib.php
mod/quiz/lib.php
mod/quiz/review.php
question/type/essay/questiontype.php
question/type/multianswer/questiontype.php
question/type/numerical/display.html
user/profile.php

index e77070b..8217876 100644 (file)
@@ -11,23 +11,32 @@ admin_externalpage_setup('replace');
 
 $search  = optional_param('search', '', PARAM_RAW);
 $replace = optional_param('replace', '', PARAM_RAW);
+$sure    = optional_param('sure', 0, PARAM_BOOL);
 
 ###################################################################
 echo $OUTPUT->header();
 
 echo $OUTPUT->heading('Search and replace text throughout the whole database');
 
+if ($DB->get_dbfamily() !== 'mysql' and $DB->get_dbfamily() !== 'postgres') {
+    //TODO: add $DB->text_replace() to DML drivers
+    echo $OUTPUT->notification('Sorry, this feature is implemented only for MySQL and PostgreSQL databases.');
+    echo $OUTPUT->footer();
+    die;
+}
 
-if (!data_submitted() or !$search or !$replace or !confirm_sesskey()) {   /// Print a form
+if (!data_submitted() or !$search or !$replace or !confirm_sesskey() or !$sure) {   /// Print a form
+    echo $OUTPUT->notification('This script is not supported, always make complete backup before proceeding!<br />This operation can not be reverted!');
 
     echo $OUTPUT->box_start();
     echo '<div class="mdl-align">';
-    echo '<form action="replace.php" method="post">';
+    echo '<form action="replace.php" method="post"><div>';
     echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
-    echo 'Search whole database for: <input type="text" name="search" /><br />';
-    echo 'Replace with this string: <input type="text" name="replace" /><br />';
-    echo '<input type="submit" value="Yes, do it now" /><br />';
-    echo '</form>';
+    echo '<div><label for="search">Search whole database for: </label><input id="search" type="text" name="search" size="40" /> (usually previous server URL)</div>';
+    echo '<div><label for="replace">Replace with this string: </label><input type="text" id="replace" name="replace" size="40" /> (usually new server URL)</div>';
+    echo '<div><label for="sure">I understand the risks of this operation: </label><input type="checkbox" id="sure" name="sure" value="1" /></div>';
+    echo '<div class="buttons"><input type="submit" class="singlebutton" value="Yes, do it now" /></div>';
+    echo '</div></form>';
     echo '</div>';
     echo $OUTPUT->box_end();
     echo $OUTPUT->footer();
@@ -35,23 +44,9 @@ if (!data_submitted() or !$search or !$replace or !confirm_sesskey()) {   /// Pr
 }
 
 echo $OUTPUT->box_start();
-
-if (!db_replace($search, $replace)) {
-    print_error('erroroccur', debug);
-}
-
+db_replace($search, $replace);
 echo $OUTPUT->box_end();
 
-/// Try to replace some well-known serialised contents (html blocks)
-echo $OUTPUT->notification('Replacing in html blocks...');
-$instances = $DB->get_recordset('block_instances', array('blockname' => 'html'));
-foreach ($instances as $instance) {
-    $blockobject = block_instance('html', $instance);
-    $blockobject->config->text = str_replace($search, $replace, $blockobject->config->text);
-    $blockobject->instance_config_commit();
-}
-$instances->close();
-
 /// Rebuild course cache which might be incorrect now
 echo $OUTPUT->notification('Rebuilding course cache...', 'notifysuccess');
 rebuild_course_cache();
index d2ad915..2827ccf 100644 (file)
         }
 
         foreach ($users as $key => $user) {
-            if (!empty($user->country)) {
+            if (isset($countries[$user->country])) {
                 $users[$key]->country = $countries[$user->country];
             }
         }
index a6e4ff6..7962513 100644 (file)
@@ -101,7 +101,7 @@ $string['auth_ntlmsso_enabled'] = 'Set to yes to attempt Single Sign On with the
 $string['auth_ntlmsso_enabled_key'] = 'Enable';
 $string['auth_ntlmsso_ie_fastpath'] = 'Set to yes to enable the NTLM SSO fast path (bypasses certain steps and only works if the client\'s browser is MS Internet Explorer).';
 $string['auth_ntlmsso_ie_fastpath_key'] = 'MS IE fast path?';
-$string['auth_ntlmsso_subnet'] = 'If set, it will only attempt SSO with clients in this subnet. Format: xxx.xxx.xxx.xxx/bitmask';
+$string['auth_ntlmsso_subnet'] = 'If set, it will only attempt SSO with clients in this subnet. Format: xxx.xxx.xxx.xxx/bitmask. Separate multiple subnets with \',\' (comma).';
 $string['auth_ntlmsso_subnet_key'] = 'Subnet';
 $string['auth_ntlmsso_type_key'] = 'Authentication type';
 $string['auth_ntlmsso_type'] = 'The authentication method configured in the web server to authenticate the users (if in doubt, choose NTLM)';
index 2fd7591..d4a3a09 100644 (file)
  */
 abstract class backup_theme_plugin extends backup_plugin {
 
-    // Stores current theme for course. Lazily initialised.
-    protected $theme;
+    /**
+     * @var string Current theme for course (may not be the same as plugin).
+     */
+    protected $coursetheme;
 
     /**
-     * Checks if an expected theme is actually the current theme for the course.
-     * @param string $expected Name of theme you are expecting e.g. 'standard'
-     * @return bool True if that theme is the current course theme
+     * @param string $plugintype Plugin type (always 'theme')
+     * @param string $pluginname Plugin name (name of theme)
+     * @param backup_optigroup $optigroup Group that will contain this data
+     * @param backup_course_structure_step $step Backup step that this is part of
      */
-    protected function is_current_theme($expected) {
-        if (!$this->theme) {
-            $this->theme = backup_plan_dbops::get_theme_from_courseid(
+    public function __construct($plugintype, $pluginname, $optigroup, $step) {
+
+        parent::__construct($plugintype, $pluginname, $optigroup, $step);
+
+        $this->coursetheme = backup_plan_dbops::get_theme_from_courseid(
                     $this->task->get_courseid());
-        }
-        return $this->theme === $expected;
+
+    }
+
+    /**
+     * Return condition for whether this theme should be backed up (= if it
+     * is the same theme as the one used in this course). This condition has
+     * the theme used in the course. It will be compared against the name
+     * of the theme, by use of third parameter in get_plugin_element; in
+     * subclass, you should do:
+     * $plugin = $this->get_plugin_element(null, $this->get_theme_condition(), 'mytheme');
+     */
+    protected function get_theme_condition() {
+        return array('sqlparam' => $this->coursetheme);
     }
 }
index 6945216..4d8fc11 100644 (file)
@@ -59,3 +59,24 @@ function block_html_pluginfile($course, $birecord_or_cm, $context, $filearea, $a
     session_get_instance()->write_close();
     send_stored_file($file, 60*60, 0, $forcedownload);
 }
+
+/**
+ * Perform global search replace such as when migrating site to new URL.
+ * @param  $search
+ * @param  $replace
+ * @return void
+ */
+function block_html_global_db_replace($search, $replace) {
+    global $DB;
+
+    $instances = $DB->get_recordset('block_instances', array('blockname' => 'html'));
+    foreach ($instances as $instance) {
+        // TODO: intentionally hardcoded until MDL-26800 is fixed
+        $config = unserialize(base64_decode($instance->configdata));
+        if (isset($config->text) and is_string($config->text)) {
+            $config->text = str_replace($search, $replace, $config->text);
+            $DB->set_field('block_instances', 'configdata', base64_encode(serialize($config)), array('id' => $instance->id));
+        }
+    }
+    $instances->close();
+}
\ No newline at end of file
index 4b5c615..4d9cb68 100644 (file)
@@ -325,7 +325,7 @@ if ($mform->is_cancelled()) {
         }
 
         if (!$updateinstancefunction($fromform, $mform)) {
-            print_error('cannotupdatemod', '', 'view.php?id=$course->id', $fromform->modulename);
+            print_error('cannotupdatemod', '', "view.php?id={$course->id}#section-{$cw->section}", $fromform->modulename);
         }
 
         // make sure visibility is set correctly (in particular in calendar)
@@ -416,9 +416,9 @@ if ($mform->is_cancelled()) {
             $DB->delete_records('course_modules', array('id'=>$fromform->coursemodule));
 
             if (!is_number($returnfromfunc)) {
-                print_error('invalidfunction', '', 'view.php?id=$course->id');
+                print_error('invalidfunction', '', "view.php?id={$course->id}#section-{$cw->section}");
             } else {
-                print_error('cannotaddnewmodule', '', "view.php?id=$course->id", $fromform->modulename);
+                print_error('cannotaddnewmodule', '', "view.php?id={$course->id}#section-{$cw->section}", $fromform->modulename);
             }
         }
 
@@ -568,7 +568,7 @@ if ($mform->is_cancelled()) {
     if (isset($fromform->submitbutton)) {
         redirect("$CFG->wwwroot/mod/$module->name/view.php?id=$fromform->coursemodule");
     } else {
-        redirect("$CFG->wwwroot/course/view.php?id=$course->id");
+        redirect("$CFG->wwwroot/course/view.php?id={$course->id}#section-{$cw->section}");
     }
     exit;
 
old mode 100644 (file)
new mode 100755 (executable)
index f5ff028..a6fc6a2 100644 (file)
@@ -50,15 +50,11 @@ function filter_algebra_image($imagefile, $tex= "", $height="", $width="", $alig
   global $CFG, $OUTPUT;
 
   $output = "";
-  $origtex = $tex;
   $style = 'style="border:0px; vertical-align:'.$align.';';
+  $title = '';
   if ($tex) {
-    $tex = str_replace('&','&amp;',$tex);
-    $tex = str_replace('<','&lt;',$tex);
-    $tex = str_replace('>','&gt;',$tex);
-    $tex = str_replace('"','&quot;',$tex);
-    $tex = str_replace("\'",'&#39;',$tex);
-    $title = "title=\"$tex\"";
+    $tex = html_entity_decode($tex, ENT_QUOTES, 'UTF-8');
+    $title = 'title="'.s($tex).'"';
   }
   if ($height) {
     $style .= " height:{$height}px;";
@@ -69,7 +65,7 @@ function filter_algebra_image($imagefile, $tex= "", $height="", $width="", $alig
   $style .= '"';
   $anchorcontents = '';
   if ($imagefile) {
-    $anchorcontents .= "<img $title alt=\"".s($origtex)."\" src=\"";
+    $anchorcontents .= "<img $title alt=\"".s($tex)."\" src=\"";
     if ($CFG->slasharguments) {        // Use this method if possible for better caching
       $anchorcontents .= "$CFG->wwwroot/filter/algebra/pix.php/$imagefile";
     } else {
@@ -77,12 +73,12 @@ function filter_algebra_image($imagefile, $tex= "", $height="", $width="", $alig
     }
     $anchorcontents .= "\" $style />";
 
-    $link = $action = null;
     if (!file_exists("$CFG->dataroot/filter/algebra/$imagefile") && has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) {
         $link = '/filter/algebra/algebradebug.php';
+        $action = null;
     } else {
-        $link = '/filter/algebra/displaytex.php?'.urlencode($tex);
-        $action = new popup_action('click', $link, 'popup', array('height'=>300,'width'=>240));
+        $link = new moodle_url('/filter/tex/displaytex.php', array('texexp'=>$tex));
+        $action = new popup_action('click', $link, 'popup', array('width'=>320,'height'=>240)); //TODO: the popups do not work when text caching is enabled!!
     }
     $output .= $OUTPUT->action_link($link, $anchorcontents, $action, array('title'=>'TeX'));
 
diff --git a/filter/tex/db/upgrade.php b/filter/tex/db/upgrade.php
new file mode 100644 (file)
index 0000000..db04601
--- /dev/null
@@ -0,0 +1,42 @@
+<?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/>.
+
+/**
+ * TeX filter upgrade code.
+ *
+ * @package    filter
+ * @subpackage tex
+ * @copyright  2011 Petr Skoda (http://skodak.org)
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * @param int $oldversion the version we are upgrading from
+ * @return bool result
+ */
+function xmldb_filter_tex_upgrade($oldversion) {
+    global $CFG, $DB, $OUTPUT;
+
+    if ($oldversion < 2011031301) {
+        // clear caches
+        require_once("$CFG->dirroot/filter/tex/lib.php");
+        filter_tex_updatedcallback(null);
+
+        upgrade_plugin_savepoint(true, 2011031301, 'filter', 'tex');
+    }
+
+    return true;
+}
index be70dc7..ddc6ee6 100644 (file)
@@ -1,20 +1,55 @@
 <?php
-      // This script displays tex source code.
+// 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/>.
 
-    require_once('../../config.php');
+/**
+ * This script displays tex source code, it is used also from the algebra filter.
+ *
+ * @package    filter
+ * @subpackage tex
+ * @copyright  2004 Zbigniew Fiedorowicz fiedorow@math.ohio-state.edu
+ *             Originally based on code provided by Bruno Vernier bruno@vsbeducation.ca
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+define('NO_MOODLE_COOKIES', true); // Because it interferes with caching
+
+require('../../config.php');
+
+if (!filter_is_enabled('filter/tex') and !filter_is_enabled('filter/algebra')) {
+    print_error('filternotenabled');
+}
+
+$texexp = optional_param('texexp', '', PARAM_RAW);
+
+$title = get_string('source', 'filter_tex')
 
-    $texexp = urldecode($_SERVER['QUERY_STRING']);
-    // entities are usually encoded twice, first in HTML editor then in tex/filter.php
-    $texexp = html_entity_decode(html_entity_decode($texexp));
-    // encode all entities (saves non-ISO)
-    $texexp = htmlentities($texexp,ENT_COMPAT,'utf-8');
 ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html>
   <head>
-    <title>TeX Source</title>
-    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <title><?php echo $title; ?></title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   </head>
-  <body bgcolor="#FFFFFF">
-    <?php echo $texexp; ?>
+  <body>
+    <div>
+      <dl>
+      <dt><?php echo $title; ?>:</dt>
+        <dd><?php p($texexp); ?></dd>
+      </dl>
+    </div>
   </body>
-</html>
\ No newline at end of file
+</html>
index 78a831e..ddff02c 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-
 // This file is part of Moodle - http://moodle.org/
 //
 // Moodle is free software: you can redistribute it and/or modify
 
 /**
  * Moodle - Filter for converting TeX expressions to cached gif images
+ *
+ * This Moodle text filter converts TeX expressions delimited
+ * by either $$...$$ or by <tex...>...</tex> tags to gif images using
+ * mimetex.cgi obtained from http: *www.forkosh.com/mimetex.html authored by
+ * John Forkosh john@forkosh.com.  Several binaries of this areincluded with
+ * this distribution.
+ * Note that there may be patent restrictions on the production of gif images
+ * in Canada and some parts of Western Europe and Japan until July 2004.
+ *
  * @package    filter
  * @subpackage tex
  * @copyright  2004 Zbigniew Fiedorowicz fiedorow@math.ohio-state.edu
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-//-------------------------------------------------------------------------
-// NOTE: This Moodle text filter converts TeX expressions delimited
-// by either $$...$$ or by <tex...>...</tex> tags to gif images using
-// mimetex.cgi obtained from http://www.forkosh.com/mimetex.html authored by
-// John Forkosh john@forkosh.com.  Several binaries of this areincluded with
-// this distribution.
-// Note that there may be patent restrictions on the production of gif images
-// in Canada and some parts of Western Europe and Japan until July 2004.
-//-------------------------------------------------------------------------
-/////////////////////////////////////////////////////////////////////////////
-//  To activate this filter, add a line like this to your                  //
-//  list of filters in your Filter configuration:                          //
-//                                                                         //
-//       filter/tex/filter.php                                             //
-/////////////////////////////////////////////////////////////////////////////
-
-function filter_text_image($imagefile, $tex= "", $height="", $width="", $align="middle", $alt='') {
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Create TeX image link.
+ *
+ * @param string $imagefile name of file
+ * @param string $tex TeX notation (html entities already decoded)
+ * @param int $height O means automatic
+ * @param int $width O means automatic
+ * @param string $align
+ * @param string $alt
+ * @return string HTML markup
+ */
+function filter_text_image($imagefile, $tex, $height, $width, $align, $alt) {
     global $CFG, $OUTPUT;
 
-    if ($alt==='') {
-        $alt = s($tex);
+    if (!$imagefile) {
+        throw new coding_exception('image file argument empty in filter_text_image()');
     }
 
     // Work out any necessary inline style.
@@ -65,47 +70,46 @@ function filter_text_image($imagefile, $tex= "", $height="", $width="", $align="
     }
 
     // Prepare the title attribute.
-    if ($tex) {
-        $tex = str_replace('&','&amp;',$tex);
-        $tex = str_replace('<','&lt;',$tex);
-        $tex = str_replace('>','&gt;',$tex);
-        $tex = str_replace('"','&quot;',$tex);
-        $tex = str_replace("\'",'&#39;',$tex);
-        // Note that we retain the title tag as TeX format rather than using
-        // the alt text, even if supplied. The alt text is intended for blind
-        // users (to provide a text equivalent to the equation) while the title
-        // is there as a convenience for sighted users who want to see the TeX
-        // code.
-        $title = "title=\"$tex\"";
+    // Note that we retain the title tag as TeX format rather than using
+    // the alt text, even if supplied. The alt text is intended for blind
+    // users (to provide a text equivalent to the equation) while the title
+    // is there as a convenience for sighted users who want to see the TeX
+    // code.
+    $title = 'title="'.s($tex).'"';
+
+    if ($alt === '') {
+        $alt = s($tex);
+    } else {
+        $alt = s(html_entity_decode($tex, ENT_QUOTES, 'UTF-8'));
     }
 
     // Build the output.
-    $output = "";
-    if ($imagefile) {
-        $anchorcontents = "<img class=\"texrender\" $title alt=\"$alt\" src=\"";
-        if ($CFG->slasharguments) {        // Use this method if possible for better caching
-            $anchorcontents .= "$CFG->wwwroot/filter/tex/pix.php/$imagefile";
-        } else {
-            $anchorcontents .= "$CFG->wwwroot/filter/tex/pix.php?file=$imagefile";
-        }
-        $anchorcontents .= "\" $style/>";
-
-        $link = $action = null;
-        if (!file_exists("$CFG->dataroot/filter/tex/$imagefile") && has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) {
-            $link = '/filter/tex/texdebug.php';
-        } else {
-            $link = '/filter/tex/displaytex.php?'.urlencode($tex);
-            $action = new popup_action('click', $link, 'popup', array('height'=>300,'width'=>240));
-        }
-        $output .= $OUTPUT->action_link($link, $anchorcontents, $action, array('title'=>'TeX'));
+    $anchorcontents = "<img class=\"texrender\" $title alt=\"$alt\" src=\"";
+    if ($CFG->slasharguments) {        // Use this method if possible for better caching
+        $anchorcontents .= "$CFG->wwwroot/filter/tex/pix.php/$imagefile";
     } else {
-        $output .= "Error: must pass URL or course";
+        $anchorcontents .= "$CFG->wwwroot/filter/tex/pix.php?file=$imagefile";
     }
+    $anchorcontents .= "\" $style/>";
+
+    if (!file_exists("$CFG->dataroot/filter/tex/$imagefile") && has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) {
+        $link = '/filter/tex/texdebug.php';
+        $action = null;
+    } else {
+        $link = new moodle_url('/filter/tex/displaytex.php', array('texexp'=>$tex));
+        $action = new popup_action('click', $link, 'popup', array('width'=>320,'height'=>240));
+    }
+    $output = $OUTPUT->action_link($link, $anchorcontents, $action, array('title'=>'TeX')); //TODO: the popups do not work when text caching is enabled!!
+
     return $output;
 }
 
+
+/**
+ * TeX filtering class.
+ */
 class filter_tex extends moodle_text_filter {
-    function filter ($text, array $options = array()) {
+    function filter($text, array $options = array()) {
 
         global $CFG, $DB;
 
@@ -132,9 +136,9 @@ class filter_tex extends moodle_text_filter {
 #    }
         $text .= ' ';
         preg_match_all('/\$(\$\$+?)([^\$])/s',$text,$matches);
-        for ($i=0;$i<count($matches[0]);$i++) {
-            $replacement = str_replace('$','&#x00024;',$matches[1][$i]).$matches[2][$i];
-            $text = str_replace($matches[0][$i],$replacement,$text);
+        for ($i=0; $i<count($matches[0]); $i++) {
+            $replacement = str_replace('$','&#x00024;', $matches[1][$i]).$matches[2][$i];
+            $text = str_replace($matches[0][$i], $replacement, $text);
         }
 
         // <tex> TeX expression </tex>
@@ -159,8 +163,17 @@ class filter_tex extends moodle_text_filter {
               $align = "text-top";
               $texexp = preg_replace('/^align=top /','',$texexp);
             }
+
+            // decode entities encoded by editor, luckily there is very little chance of double decoding
+            $texexp = html_entity_decode($texexp, ENT_QUOTES, 'UTF-8');
+
+            if ($texexp === '') {
+                contninue;
+            }
+
             $md5 = md5($texexp);
-            if (! $texcache = $DB->get_record("cache_filters", array("filter"=>"tex", "md5key"=>$md5))) {
+            if (!$DB->record_exists("cache_filters", array("filter"=>"tex", "md5key"=>$md5))) {
+                $texcache = new stdClass();
                 $texcache->filter = 'tex';
                 $texcache->version = 1;
                 $texcache->md5key = $md5;
@@ -169,7 +182,7 @@ class filter_tex extends moodle_text_filter {
                 $DB->insert_record("cache_filters", $texcache, false);
             }
             $filename = $md5 . ".{$CFG->filter_tex_convertformat}";
-            $text = str_replace( $matches[0][$i], filter_text_image($filename, $texexp, '', '', $align, $alt), $text);
+            $text = str_replace( $matches[0][$i], filter_text_image($filename, $texexp, 0, 0, $align, $alt), $text);
         }
         return $text;
     }
index 29ca17d..c0244e8 100644 (file)
@@ -1,4 +1,27 @@
 <?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/>.
+
+/**
+ * TeX filter settings
+ *
+ * @package    filter
+ * @subpackage tex
+ * @copyright  2007 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
 
 defined('MOODLE_INTERNAL') || die;
 
index f7166ed..8290d7b 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-
 // This file is part of Moodle - http://moodle.org/
 //
 // Moodle is free software: you can redistribute it and/or modify
 /**
  * Strings for component 'filter_tex', language 'en', branch 'MOODLE_20_STABLE'
  *
- * @package   filter_tex
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package    filter
+ * @subpackage tex
+ * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 $string['filtername'] = 'TeX notation';
+$string['source'] = 'TeX source';
index a0b7d1c..5f56922 100644 (file)
@@ -1,4 +1,28 @@
 <?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/>.
+
+/**
+ * TeX filter library functions.
+ *
+ * @package    filter
+ * @subpackage tex
+ * @copyright  2004 Zbigniew Fiedorowicz fiedorow@math.ohio-state.edu
+ *             Originally based on code provided by Bruno Vernier bruno@vsbeducation.ca
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
 
 defined('MOODLE_INTERNAL') || die();
 
index 45b1b79..deb43d5 100644 (file)
@@ -42,7 +42,7 @@ define('NO_MOODLE_COOKIES', true); // Because it interferes with caching
             $latex = new latex();
             $density = $CFG->filter_tex_density;
             $background = $CFG->filter_tex_latexbackground;
-            $texexp = html_entity_decode($texcache->rawtext);
+            $texexp = $texcache->rawtext; // the entities are now decoded before inserting to DB
             $latex_path = $latex->render($texexp, $md5, 12, $density, $background);
             if ($latex_path) {
                 copy($latex_path, $pathname);
index a53f2ee..35f1afb 100644 (file)
@@ -1,7 +1,30 @@
 <?php
-      // This function fetches math. images from the data directory
-      // If not, it obtains the corresponding TeX expression from the cache_tex db table
-      // and uses mimeTeX to create the image file
+// 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/>.
+
+/**
+ * This function fetches math. images from the data directory
+ * If not, it obtains the corresponding TeX expression from the cache_tex db table
+ * and uses mimeTeX to create the image file
+ *
+ * @package    filter
+ * @subpackage tex
+ * @copyright  2004 Zbigniew Fiedorowicz fiedorow@math.ohio-state.edu
+ *             Originally based on code provided by Bruno Vernier bruno@vsbeducation.ca
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
 
     require_once("../../config.php");
 
@@ -19,7 +42,6 @@
     require_login();
     require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM), $USER->id); /// Required cap to run this. MDL-18552
 
-    $query = urldecode($_SERVER['QUERY_STRING']);
     $output = '';
 
     // look up in cache if required
         header("Content-type: text/html; charset=utf-8");
         echo "<html><body><pre>\n";
         if ($texexp) {
-            $texexp = str_replace('<', '&lt;', $texexp);
-            $texexp = str_replace('>', '&gt;', $texexp);
-            $texexp = str_replace('"', '&quot;', $texexp);
-            echo "$texexp\n\n";
+            echo s($texexp)."\n\n";
         } else {
             echo "No text output available\n\n";
         }
         $output .= execute($cmd);
 
         if (!$graphic) {
-            echo($output);
-        } else {
+            echo $output;
+        } else if (file_exists($img)){
             send_file($img, "$md5.{$CFG->filter_tex_convertformat}");
-         }
+        } else {
+            echo "Error creating image, see command execution output for more details.";
+        }
     }
 
     function execute($cmd) {
index d7ceba5..9c5df14 100644 (file)
@@ -26,4 +26,4 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2010073000;
+$plugin->version = 2011031301;
diff --git a/install/lang/de_kids/langconfig.php b/install/lang/de_kids/langconfig.php
new file mode 100644 (file)
index 0000000..1ebd9f7
--- /dev/null
@@ -0,0 +1,33 @@
+<?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/>.
+
+/**
+ * Automatically generated strings for Moodle installer
+ *
+ * Do not edit this file manually! It contains just a subset of strings
+ * needed during the very first steps of installation. This file was
+ * generated automatically by export-installer.php (which is part of AMOS
+ * {@link http://docs.moodle.org/en/Development:Languages/AMOS}) using the
+ * list of strings defined in /install/stringnames.txt.
+ *
+ * @package   installer
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$string['parentlanguage'] = 'de_du';
+$string['thisdirection'] = '';
+$string['thislanguage'] = 'Deutsch - Kids';
index 1f5ef1c..f3d7407 100644 (file)
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+$string['clianswerno'] = 'n';
+$string['cliansweryes'] = 't';
 $string['cliincorrectvalueerror'] = 'Błąd, niepoprawna wartość "{$a->value}" dla "{$a->option}"';
 $string['cliincorrectvalueretry'] = 'Nieprawidłowa wartość, spróbuj ponownie';
 $string['clitypevalue'] = 'typ wartości';
 $string['clitypevaluedefault'] = 'typ wartości, naciśnij Enter, aby użyć wartości domyślnej ({$a})';
+$string['cliunknowoption'] = 'Nieznana opcja:
+  {$a}
+Proszę użyć pomocy.';
 $string['cliyesnoprompt'] = 'wpisz y (czyli tak) lub n (czyli nie)';
 $string['environmentrequireinstall'] = 'jest niezbędnę, żeby było zainstalowane/włączone';
 $string['environmentrequireversion'] = 'wersja {$a->needed} jest niezbędna a ty używasz wersji {$a->current}';
index 5e2ea90..c41f37d 100644 (file)
@@ -32,12 +32,14 @@ $string['admindirname'] = 'Katalog admin';
 $string['availablelangs'] = 'Dostępne paczki językowe';
 $string['chooselanguagehead'] = 'Wybierz język';
 $string['chooselanguagesub'] = 'Proszę wybrać język TYLKO do instalacji. Stronę i języki dla użytkowników będzie można wybrać na następnym ekranie.';
+$string['clialreadyinstalled'] = 'Plik config.php już istnieje, użyj admin/cli/upgrade.php jeśli chcesz uaktualnić witrynę.';
 $string['databasehost'] = 'Host bazy danych';
 $string['databasename'] = 'Nazwa bazy danych';
 $string['dataroot'] = 'Katalog z danymi';
 $string['dbprefix'] = 'Prefiks tabel';
 $string['dirroot'] = 'Katalog Moodle';
 $string['environmenthead'] = 'Sprawdzam środowisko (ustawienia) ...';
+$string['errorsinenvironment'] = 'Kontrola środowiska zakończona niepowodzeniem!';
 $string['installation'] = 'Instalacja';
 $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>
@@ -54,7 +56,13 @@ Pozwoli to Moodle ustawić samoczynnie limit pamięci.</li>
 <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['paths'] = 'Ścieżki';
+$string['pathserrcreatedataroot'] = 'Katalog danych ({$a->dataroot}) nie może zostać utworzony przez instalator.';
+$string['pathshead'] = 'Potwierdź ścieżki';
+$string['pathsrodataroot'] = 'Główny katalog danych nie ma uprawnień do zapisu. ';
 $string['pathsroparentdataroot'] = 'Nadrzędny katalog ({$a->parent}) jest tylko do odczytu. Katalog danych ({$a->dataroot}) nie może zostać utworzony przez instalator. ';
+$string['pathssubdirroot'] = 'Pełna ścieżka do katalogu z instalacją Moodle.';
+$string['pathsunsecuredataroot'] = 'Lokalizacja głównego katalogu danych nie jest bezpieczna';
 $string['pathswrongadmindir'] = 'Katalog admin nie istnieje';
 $string['phpextension'] = '{$a} rozszerzenie PHP';
 $string['phpversion'] = 'Wersja PHP';
index 8e38044..f249aa3 100644 (file)
@@ -5967,10 +5967,14 @@ function any_new_admin_settings($node) {
  * @return bool success or fail
  */
 function db_replace($search, $replace) {
+    global $DB, $CFG, $OUTPUT;
 
-    global $DB, $CFG;
+    // TODO: this is horrible hack, we should do whitelisting and each plugin should be responsible for proper replacing...
+    $skiptables = array('config', 'config_plugins', 'config_log', 'upgrade_log',
+                        'filter_config', 'sessions', 'events_queue', 'repository_instance_config',
+                        'block_instances', 'block_pinned_old', 'block_instance_old', '');
 
-    /// Turn off time limits, sometimes upgrades can be slow.
+    // Turn off time limits, sometimes upgrades can be slow.
     @set_time_limit(0);
 
     if (!$tables = $DB->get_tables() ) {    // No tables yet at all.
@@ -5978,7 +5982,7 @@ function db_replace($search, $replace) {
     }
     foreach ($tables as $table) {
 
-        if (in_array($table, array('config'))) {      // Don't process these
+        if (in_array($table, $skiptables)) {      // Don't process these
             continue;
         }
 
@@ -5986,6 +5990,7 @@ function db_replace($search, $replace) {
             $DB->set_debug(true);
             foreach ($columns as $column => $data) {
                 if (in_array($data->meta_type, array('C', 'X'))) {  // Text stuff only
+                    //TODO: this should be definitively moved to DML driver to do the actual replace, this is not going to work for MSSQL and Oracle...
                     $DB->execute("UPDATE {".$table."} SET $column = REPLACE($column, ?, ?)", array($search, $replace));
                 }
             }
@@ -5993,6 +5998,31 @@ function db_replace($search, $replace) {
         }
     }
 
+    // delete modinfo caches
+    rebuild_course_cache(0, true);
+
+    // TODO: we should ask all plugins to do the search&replace, for now let's do only blocks...
+    $blocks = get_plugin_list('block');
+    foreach ($blocks as $blockname=>$fullblock) {
+        if ($blockname === 'NEWBLOCK') {   // Someone has unzipped the template, ignore it
+            continue;
+        }
+
+        if (!is_readable($fullblock.'/lib.php')) {
+            continue;
+        }
+
+        $function = 'block_'.$blockname.'_global_db_replace';
+        include_once($fullblock.'/lib.php');
+        if (!function_exists($function)) {
+            continue;
+        }
+
+        echo $OUTPUT->notification("Replacing in $blockname blocks...", 'notifysuccess');
+        $function($search, $replace);
+        echo $OUTPUT->notification("...finished", 'notifysuccess');
+    }
+
     return true;
 }
 
index 2dcf40f..a747101 100644 (file)
@@ -989,10 +989,10 @@ class completion_info {
 
         $sql  = "SELECT u.id ";
         $sql .= $tracked->sql;
-        $sql .= ' AND u.id = :user';
+        $sql .= ' AND u.id = :userid';
 
         $params = $tracked->data;
-        $params['user'] = (int)$userid;
+        $params['userid'] = (int)$userid;
         return $DB->record_exists_sql($sql, $params);
     }
 
index 5c338b5..96a70f0 100644 (file)
@@ -220,6 +220,47 @@ function enrol_check_plugins($user) {
     unset($inprogress[$user->id]);  // Unset the flag
 }
 
+/**
+ * Do these two students share any course?
+ *
+ * The courses has to be visible and enrolments has to be active,
+ * timestart and timeend restrictions are ignored.
+ *
+ * @param stdClass|int $user1
+ * @param stdClass|int $user2
+ * @return bool
+ */
+function enrol_sharing_course($user1, $user2) {
+    global $DB, $CFG;
+
+    $user1 = !empty($user1->id) ? $user1->id : $user1;
+    $user2 = !empty($user2->id) ? $user2->id : $user2;
+
+    if (empty($user1) or empty($user2)) {
+        return false;
+    }
+
+    if (!$plugins = explode(',', $CFG->enrol_plugins_enabled)) {
+        return false;
+    }
+
+    list($plugins, $params) = $DB->get_in_or_equal($plugins, SQL_PARAMS_NAMED, 'ee00');
+    $params['enabled'] = ENROL_INSTANCE_ENABLED;
+    $params['active1'] = ENROL_USER_ACTIVE;
+    $params['active2'] = ENROL_USER_ACTIVE;
+    $params['user1']   = $user1;
+    $params['user2']   = $user2;
+
+    $sql = "SELECT DISTINCT 'x'
+              FROM {enrol} e
+              JOIN {user_enrolments} ue1 ON (ue1.enrolid = e.id AND ue1.status = :active1 AND ue1.userid = :user1)
+              JOIN {user_enrolments} ue2 ON (ue1.enrolid = e.id AND ue1.status = :active2 AND ue2.userid = :user2)
+              JOIN {course} c ON (c.id = e.courseid AND c.visible = 1)
+             WHERE e.status = :enabled AND e.enrol $plugins";
+
+    return $DB->record_exists_sql($sql, $params);
+}
+
 /**
  * This function adds necessary enrol plugins UI into the course edit form.
  *
index 1addd11..def025c 100644 (file)
@@ -138,6 +138,15 @@ class MoodleExcelWorksheet {
      */
     function MoodleExcelWorksheet($name, &$workbook, $latin_output=false) {
 
+        if (strlen($name) > 31) {
+            // Excel does not seem able to cope with sheet names > 31 chars.
+            // With $latin_output = false, it does not cope at all.
+            // With $latin_output = true it is supposed to work, but in our experience,
+            // it doesn't. Therefore, truncate in all circumstances.
+            $textlib = textlib_get_instance();
+            $name = $textlib->substr($name, 0, 31);
+        }
+
     /// Internally, add one sheet to the workbook
         $this->pear_excel_worksheet =& $workbook->addWorksheet($name);
         $this->latin_output = $latin_output;
index 4abc493..6136507 100644 (file)
@@ -976,7 +976,7 @@ function format_text($text, $format = FORMAT_MOODLE, $options = NULL, $courseid_
     global $CFG, $COURSE, $DB, $PAGE;
     static $croncache = array();
 
-    if ($text === '') {
+    if ($text === '' || is_null($text)) {
         return ''; // no need to do any filters and cleaning
     }
 
index 6985b4e..ad6051a 100644 (file)
@@ -146,7 +146,7 @@ $string['forum'] = 'Forum';
 $string['forum:addnews'] = 'Add news';
 $string['forumauthorhidden'] = 'Author (hidden)';
 $string['forumblockingalmosttoomanyposts'] = 'You are approaching the posting threshold. You have posted {$a->numposts} times in the last {$a->blockperiod} and the limit is {$a->blockafter} posts.';
-$string['forumbodyhidden'] = 'This post cannot be viewed by you, probably because you have not posted in the discussion yet.';
+$string['forumbodyhidden'] = 'This post cannot be viewed by you, probably because you have not posted in the discussion or the maximum editing time hasn\'t passed yet.';
 $string['forum:createattachment'] = 'Create attachments';
 $string['forum:deleteanypost'] = 'Delete any posts (anytime)';
 $string['forum:deleteownpost'] = 'Delete own posts (within deadline)';
index 92220f7..3900fff 100644 (file)
@@ -526,6 +526,11 @@ function forum_cron() {
                     // oops - this user should not receive anything from this course
                     continue;
                 }
+                // Don't send email if the forum is Q&A and the user has not posted
+                if ($forum->type == 'qanda' && !forum_get_user_posted_time($discussion->id, $userto->id)) {
+                    mtrace('Did not email '.$userto->id.' because user has not posted in discussion');
+                    continue;
+                }
 
                 // Get info about the sending user
                 if (array_key_exists($post->userid, $users)) { // we might know him/her already
@@ -4640,8 +4645,25 @@ function forum_user_has_posted($forumid, $did, $userid) {
                  WHERE p.userid = :userid AND d.forum = :forumid";
         return $DB->record_exists_sql($sql, array('forumid'=>$forumid,'userid'=>$userid));
     } else {
-    return $DB->record_exists('forum_posts', array('discussion'=>$did,'userid'=>$userid));
+        return $DB->record_exists('forum_posts', array('discussion'=>$did,'userid'=>$userid));
+    }
 }
+
+/**
+ * Returns creation time of the first user's post in given discussion
+ * @global object $DB
+ * @param int $did Discussion id
+ * @param int $userid User id
+ * @return int|bool post creation time stamp or return false
+ */
+function forum_get_user_posted_time($did, $userid) {
+    global $DB;
+
+    $posttime = $DB->get_field('forum_posts', 'MIN(created)', array('userid'=>$userid, 'discussion'=>$did));
+    if (empty($posttime)) {
+        return false;
+    }
+    return $posttime;
 }
 
 /**
@@ -4893,7 +4915,7 @@ function forum_user_can_see_discussion($forum, $discussion, $context, $user=NULL
  * @return bool
  */
 function forum_user_can_see_post($forum, $discussion, $post, $user=NULL, $cm=NULL) {
-    global $USER, $DB;
+    global $CFG, $USER, $DB;
 
     // retrieve objects (yuk)
     if (is_numeric($forum)) {
@@ -4954,9 +4976,10 @@ function forum_user_can_see_post($forum, $discussion, $post, $user=NULL, $cm=NUL
     if ($forum->type == 'qanda') {
         $firstpost = forum_get_firstpost_from_discussion($discussion->id);
         $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
+        $userfirstpost = forum_get_user_posted_time($discussion->id, $user->id);
 
-        return (forum_user_has_posted($forum->id,$discussion->id,$user->id) ||
-                $firstpost->id == $post->id ||
+        return (($userfirstpost !== false && (time() - $userfirstpost >= $CFG->maxeditingtime)) ||
+                $firstpost->id == $post->id || $post->userid == $user->id || $firstpost->userid == $user->id ||
                 has_capability('mod/forum:viewqandawithoutposting', $modcontext, $user->id, false));
     }
     return true;
index 7817e98..1efe7a8 100644 (file)
@@ -462,32 +462,43 @@ class quiz_attempt extends quiz {
     }
 
     /**
-     * Static function to create a new quiz_attempt object given an attemptid.
-     *
-     * @param integer $attemptid the attempt id.
-     * @return quiz_attempt the new quiz_attempt object
+     * Used by {create()} and {create_from_usage_id()}.
+     * @param array $conditions passed to $DB->get_record('quiz_attempts', $conditions).
      */
-    static public function create($attemptid) {
+    static protected function create_helper($conditions) {
         global $DB;
 
-        if (!$attempt = quiz_load_attempt($attemptid)) {
-            throw new moodle_exception('invalidattemptid', 'quiz');
-        }
-        if (!$quiz = $DB->get_record('quiz', array('id' => $attempt->quiz))) {
-            throw new moodle_exception('invalidquizid', 'quiz');
-        }
-        if (!$course = $DB->get_record('course', array('id' => $quiz->course))) {
-            throw new moodle_exception('invalidcoursemodule');
-        }
-        if (!$cm = get_coursemodule_from_instance('quiz', $quiz->id, $course->id)) {
-            throw new moodle_exception('invalidcoursemodule');
-        }
+        $attempt = $DB->get_record('quiz_attempts', $conditions, '*', MUST_EXIST);
+        $quiz = $DB->get_record('quiz', array('id' => $attempt->quiz), '*', MUST_EXIST);
+        $course = $DB->get_record('course', array('id' => $quiz->course), '*', MUST_EXIST);
+        $cm = get_coursemodule_from_instance('quiz', $quiz->id, $course->id, false, MUST_EXIST);
+
         // Update quiz with override information
         $quiz = quiz_update_effective_access($quiz, $attempt->userid);
 
         return new quiz_attempt($attempt, $quiz, $cm, $course);
     }
 
+    /**
+     * Static function to create a new quiz_attempt object given an attemptid.
+     *
+     * @param int $attemptid the attempt id.
+     * @return quiz_attempt the new quiz_attempt object
+     */
+    static public function create($attemptid) {
+        return self::create_helper(array('id' => $attemptid));
+    }
+
+    /**
+     * Static function to create a new quiz_attempt object given a usage id.
+     *
+     * @param int $usageid the attempt usage id.
+     * @return quiz_attempt the new quiz_attempt object
+     */
+    static public function create_from_unique_id($usageid) {
+        return self::create_helper(array('uniqueid' => $usageid));
+    }
+
     // Functions for loading more data =====================================================
     /**
      * Load the state of a number of questions that have already been loaded.
index 0030c2a..ac8e09b 100644 (file)
@@ -1770,11 +1770,11 @@ function quiz_pluginfile($course, $cm, $context, $filearea, $args, $forcedownloa
  * @return bool false if file not found, does not return if found - justsend the file
  */
 function quiz_question_pluginfile($course, $context, $component,
-        $filearea, $attemptid, $questionid, $args, $forcedownload) {
+        $filearea, $uniqueid, $questionid, $args, $forcedownload) {
     global $USER, $CFG;
     require_once($CFG->dirroot . '/mod/quiz/locallib.php');
 
-    $attemptobj = quiz_attempt::create($attemptid);
+    $attemptobj = quiz_attempt::create_from_unique_id($uniqueid);
     require_login($attemptobj->get_courseid(), false, $attemptobj->get_cm());
     $questionids = array($questionid);
     $attemptobj->load_questions($questionids);
index 240de7b..105d758 100644 (file)
@@ -40,7 +40,7 @@
             redirect($attemptobj->attempt_url(0, $page));
         } else if (!$options->responses) {
             $accessmanager->back_to_view_page($attemptobj->is_preview_user(),
-                    $accessmanager->cannot_review_message($attemptobj->get_attempt_state()));
+                    $accessmanager->cannot_review_message($options));
         }
 
     } else if (!$attemptobj->is_review_allowed()) {
index 0bfc86a..8b77589 100644 (file)
@@ -87,7 +87,8 @@ class question_essay_qtype extends default_questiontype {
         $feedback = '';
         if ($options->feedback && !empty($answers)) {
             foreach ($answers as $answer) {
-                $feedback = quiz_rewrite_question_urls($answer->feedback, 'pluginfile.php', $context->id, 'qtype_essay', 'feedback', array($state->attempt, $state->question), $answer->id);
+                $feedback = quiz_rewrite_question_urls($answer->feedback, 'pluginfile.php',
+                        $context->id, 'question', 'answerfeedback', array($state->attempt, $state->question), $answer->id);
                 $feedback = format_text($feedback, $answer->feedbackformat, $formatoptions, $cmoptions->course);
             }
         }
index 012cc43..ff1b340 100644 (file)
@@ -166,10 +166,6 @@ class embedded_cloze_qtype extends default_questiontype {
         }
 
         $question->category = $authorizedquestion->category;
-        $form->course = $course; // To pass the course object to
-                                 // save_question_options, where it is
-                                 // needed to call type specific
-                                 // save_question methods.
         $form->defaultgrade = $question->defaultgrade;
         $form->questiontext = $question->questiontext;
         $form->questiontextformat = 0;
@@ -599,6 +595,37 @@ class embedded_cloze_qtype extends default_questiontype {
         echo '</div>';
     }
 
+    public function compare_responses($question, $state, $teststate) {
+        global $QTYPES;
+
+        foreach ($question->options->questions as $key => $wrapped) {
+            if (empty($wrapped)) {
+                continue;
+            }
+
+            $stateforquestion = clone($state);
+            if (isset($state->responses[$key])) {
+                $stateforquestion->responses[''] = $state->responses[$key];
+            } else {
+                $stateforquestion->responses[''] = '';
+            }
+
+            $teststateforquestion = clone($teststate);
+            if (isset($teststate->responses[$key])) {
+                $teststateforquestion->responses[''] = $teststate->responses[$key];
+            } else {
+                $teststateforquestion->responses[''] = '';
+            }
+
+            if (!$QTYPES[$wrapped->qtype]->compare_responses($wrapped,
+                    $stateforquestion, $teststateforquestion)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
     function grade_responses(&$question, &$state, $cmoptions) {
         global $QTYPES;
         $teststate = clone($state);
index 12d678d..b8b9704 100644 (file)
@@ -63,9 +63,9 @@
     ?> size="<?php echo $textlength;?>"/>
     <?php if ($state->responses['unit'] != '') echo $feedbackimgunit; 
     if ($options->feedback &&  $question->options->unitgradingtype == 1 && ! $valid_numerical_unit && ! $answerasterisk ){
-        if ( $empty_unit) {
+        if (!empty($empty_unit)) {
             print_string('unitmandatory', 'qtype_numerical'); 
-        }else {
+        } else {
             if(isset($question->options->units) && count($question->options->units) > 0){
                 $found = 0 ;
                 $valid_unit_found = 0 ;
index a373051..8559d19 100644 (file)
@@ -63,8 +63,10 @@ if (!$currentuser &&
     !empty($CFG->forceloginforprofiles) &&
     !has_capability('moodle/user:viewdetails', $context) &&
     !has_coursecontact_role($userid)) {
+
     // Course managers can be browsed at site level. If not forceloginforprofiles, allow access (bug #4366)
     $struser = get_string('user');
+    $PAGE->set_context(get_context_instance(CONTEXT_SYSTEM));
     $PAGE->set_title("$SITE->shortname: $struser");  // Do not leak the name
     $PAGE->set_heading("$SITE->shortname: $struser");
     $PAGE->set_url('/user/profile.php', array('id'=>$userid));
@@ -247,9 +249,10 @@ if (has_capability('moodle/user:viewhiddendetails', $context)) {
     }
 }
 
-if ($user->maildisplay == 1
-   or ($user->maildisplay == 2 && !isguestuser())
-   or has_capability('moodle/course:useremail', $context)) {
+if ($currentuser
+  or $user->maildisplay == 1
+  or has_capability('moodle/course:useremail', $context)
+  or ($user->maildisplay == 2 and enrol_sharing_course($user, $USER))) {
 
     print_row(get_string("email").":", obfuscate_mailto($user->email, ''));
 }