Merge branch 'MDL-31708-moodle23' of git://github.com/StudiUM/moodle into MOODLE_23_S...
authorAparup Banerjee <aparup@moodle.com>
Wed, 31 Oct 2012 02:05:26 +0000 (10:05 +0800)
committerAparup Banerjee <aparup@moodle.com>
Wed, 31 Oct 2012 02:05:26 +0000 (10:05 +0800)
33 files changed:
auth/shibboleth/index.php
auth/shibboleth/lang/en/auth_shibboleth.php
backup/util/dbops/restore_dbops.class.php
blocks/dock.js
blocks/search_forums/block_search_forums.php
course/lib.php
course/yui/modchooser/modchooser.js
course/yui/toolboxes/toolboxes.js
enrol/yui/notification/assets/skins/sam/notification.css
enrol/yui/notification/notification.js
grade/lib.php
grade/report/grader/lib.php
lang/en/form.php
lib/bennu/bennu.class.php
lib/bennu/iCalendar_parameters.php
lib/form/yui/dateselector/dateselector.js
lib/javascript-static.js
lib/outputrenderers.php
lib/tablelib.php
mod/assignment/type/upload/assignment.class.php
mod/book/db/upgrade.php
mod/book/db/upgradelib.php [new file with mode: 0644]
mod/book/version.php
mod/forum/styles.css
mod/quiz/styles.css
question/type/calculated/styles.css
question/type/multichoice/edit_multichoice_form.php
question/type/numerical/styles.css
theme/base/style/core.css
theme/magazine/style/core.css
user/edit.php
user/filters/text.php
version.php

index a1e4a1c..49b510f 100644 (file)
@@ -38,9 +38,9 @@
 
     /// Check if the user has actually submitted login data to us
 
-        if ($shibbolethauth->user_login($frm->username, $frm->password)) {
+        if ($shibbolethauth->user_login($frm->username, $frm->password)
+                && $user = authenticate_user_login($frm->username, $frm->password)) {
 
-            $user = authenticate_user_login($frm->username, $frm->password);
             enrol_check_plugins($user);
             session_set_user($user);
 
@@ -84,7 +84,8 @@
         }
 
         else {
-            // For some weird reason the Shibboleth user couldn't be authenticated
+            // The Shibboleth user couldn't be mapped to a valid Moodle user
+            print_error('shib_invalid_account_error', 'auth_shibboleth');
         }
     }
 
index ca0f251..aace9a1 100644 (file)
@@ -51,6 +51,7 @@ $string['auth_shib_no_organizations_warning'] = 'If you want to use the integrat
 $string['auth_shib_only'] = 'Shibboleth only';
 $string['auth_shib_only_description'] = 'Check this option if a Shibboleth authentication shall be enforced';
 $string['auth_shib_username_description'] = 'Name of the webserver Shibboleth environment variable that shall be used as Moodle username';
+$string['shib_invalid_account_error'] = 'You seem to be Shibboleth authenticated but Moodle has no valid account for your username. Your account may not exist or it may have been suspended.';
 $string['shib_no_attributes_error'] = 'You seem to be Shibboleth authenticated but Moodle didn\'t receive any user attributes. Please check that your Identity Provider releases the necessary attributes ({$a}) to the Service Provider Moodle is running on or inform the webmaster of this server.';
 $string['shib_not_all_attributes_error'] = 'Moodle needs certain Shibboleth attributes which are not present in your case. The attributes are: {$a}<br />Please contact the webmaster of this server or your Identity Provider.';
 $string['shib_not_set_up_error'] = 'Shibboleth authentication doesn\'t seem to be set up correctly because no Shibboleth environment variables are present for this page. Please consult the <a href="README.txt">README</a> for further instructions on how to set up Shibboleth authentication or contact the webmaster of this Moodle installation.';
index fb7beb3..e856ead 100644 (file)
@@ -1505,7 +1505,8 @@ abstract class restore_dbops {
             }
             $currentfullname = $fullname.$suffixfull;
             $currentshortname = substr($shortname, 0, 100 - strlen($suffixshort)).$suffixshort; // < 100cc
-            $coursefull  = $DB->get_record_select('course', 'fullname = ? AND id != ?', array($currentfullname, $courseid));
+            $coursefull  = $DB->get_record_select('course', 'fullname = ? AND id != ?',
+                    array($currentfullname, $courseid), '*', IGNORE_MULTIPLE);
             $courseshort = $DB->get_record_select('course', 'shortname = ? AND id != ?', array($currentshortname, $courseid));
             $counter++;
         } while ($coursefull || $courseshort);
index 3c8a31b..a759913 100644 (file)
@@ -505,7 +505,7 @@ M.core_dock.fixTitleOrientation = function(item, title, text) {
             break;
     }
 
-    if (Y.UA.ie > 7) {
+    if (Y.UA.ie == 8) {
         // IE8 can flip the text via CSS but not handle SVG
         title.setContent(text);
         title.setAttribute('style', 'writing-mode: tb-rl; filter: flipV flipH;display:inline;');
index cf22705..0e780f1 100644 (file)
@@ -27,6 +27,7 @@ class block_search_forums extends block_base {
 
         $this->content->text  = '<div class="searchform">';
         $this->content->text .= '<form action="'.$CFG->wwwroot.'/mod/forum/search.php" style="display:inline"><fieldset class="invisiblefieldset">';
+        $this->content->text .= '<legend class="accesshide">'.$strsearch.'</legend>';
         $this->content->text .= '<input name="id" type="hidden" value="'.$this->page->course->id.'" />';  // course
         $this->content->text .= '<label class="accesshide" for="searchform_search">'.$strsearch.'</label>'.
                                 '<input id="searchform_search" name="search" type="text" size="16" />';
index ef150d0..51b4b0c 100644 (file)
@@ -1548,8 +1548,8 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
                 $linkclasses = '';
                 $textclasses = '';
                 if ($accessiblebutdim) {
-                    $linkclasses .= ' dimmed';
-                    $textclasses .= ' dimmed_text';
+                    $linkclasses .= ' dimmed conditionalhidden';
+                    $textclasses .= ' dimmed_text conditionalhidden';
                     $accesstext = '<span class="accesshide">'.
                         get_string('hiddenfromstudents').': </span>';
                 } else {
@@ -1731,11 +1731,15 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
             // see the activity itself, or for staff)
             if (!$mod->uservisible) {
                 echo '<div class="availabilityinfo">'.$mod->availableinfo.'</div>';
-            } else if ($canviewhidden && !empty($CFG->enableavailability) && $mod->visible) {
+            } else if ($canviewhidden && !empty($CFG->enableavailability)) {
+                $visibilityclass = '';
+                if (!$mod->visible) {
+                    $visibilityclass = 'accesshide';
+                }
                 $ci = new condition_info($mod);
                 $fullinfo = $ci->get_full_information();
                 if($fullinfo) {
-                    echo '<div class="availabilityinfo">'.get_string($mod->showavailability
+                    echo '<div class="availabilityinfo '.$visibilityclass.'">'.get_string($mod->showavailability
                         ? 'userrestriction_visible'
                         : 'userrestriction_hidden','condition',
                         $fullinfo).'</div>';
@@ -1970,7 +1974,7 @@ function get_module_metadata($course, $modnames, $sectionreturn = null) {
                 if ($sm->string_exists('modulename_link', $modname)) {  // Link to further info in Moodle docs
                     $link = get_string('modulename_link', $modname);
                     $linktext = get_string('morehelp');
-                    $module->help .= html_writer::tag('div', $OUTPUT->doc_link($link, $linktext), array('class' => 'helpdoclink'));
+                    $module->help .= html_writer::tag('div', $OUTPUT->doc_link($link, $linktext, true), array('class' => 'helpdoclink'));
                 }
             }
             $module->archetype = plugin_supports('mod', $modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER);
index aea4040..f87a5ec 100644 (file)
@@ -36,36 +36,6 @@ YUI.add('moodle-course-modchooser', function(Y) {
 
             // Catch the page toggle
             Y.all('.block_settings #settingsnav .type_course .modchoosertoggle a').on('click', this.toggle_mod_chooser, this);
-
-            // Ensure that help links are opened in an appropriate popup
-            this.container.all('div.helpdoclink a').on('click', function(e) {
-                var anchor = e.target.ancestor('a', true);
-
-                var args = {
-                    'name'          : 'popup',
-                    'url'           : anchor.getAttribute('href'),
-                    'option'        : ''
-                };
-                var options = [
-                    'height=600',
-                    'width=800',
-                    'top=0',
-                    'left=0',
-                    'menubar=0',
-                    'location=0',
-                    'scrollbars',
-                    'resizable',
-                    'toolbar',
-                    'status',
-                    'directories=0',
-                    'fullscreen=0',
-                    'dependent'
-                ]
-                args.options = options.join(',');
-
-                // Note: openpopup is provided by lib/javascript-static.js
-                openpopup(e, args);
-            });
         },
         /**
          * Update any section areas within the scope of the specified
index 0f70c2c..db7dae8 100644 (file)
@@ -33,7 +33,11 @@ YUI.add('moodle-course-toolboxes', function(Y) {
         SECTIONIDPREFIX : 'section-',
         SECTIONLI : 'li.section',
         SHOW : 'a.editing_show',
-        SHOWHIDE : 'a.editing_showhide'
+        SHOWHIDE : 'a.editing_showhide',
+        CONDITIONALHIDDEN : 'conditionalhidden',
+        AVAILABILITYINFODIV : 'div.availabilityinfo',
+        SHOWCLASS : 'editing_show',
+        ACCESSHIDECLASS : 'accesshide'
     };
 
     /**
@@ -68,18 +72,14 @@ YUI.add('moodle-course-toolboxes', function(Y) {
 
             var status = '';
             var value;
-            if (dimarea.hasClass(toggle_class)) {
+            if (button.hasClass(CSS.SHOWCLASS)) {
                 status = 'hide';
                 value = 1;
             } else {
                 status = 'show';
                 value = 0;
             }
-
-            // Change the UI
-            dimarea.toggleClass(toggle_class);
-            // We need to toggle dimming on the description too
-            element.all(CSS.CONTENTAFTERLINK).toggleClass(CSS.DIMMEDTEXT);
+            // Update button info.
             var newstring = M.util.get_string(status, 'moodle');
             hideicon.setAttrs({
                 'alt' : newstring,
@@ -88,6 +88,19 @@ YUI.add('moodle-course-toolboxes', function(Y) {
             button.set('title', newstring);
             button.set('className', 'editing_'+status);
 
+            // If activity is conditionally hidden, then don't toggle.
+            if (!dimarea.hasClass(CSS.CONDITIONALHIDDEN)) {
+                // Change the UI.
+                dimarea.toggleClass(toggle_class);
+                // We need to toggle dimming on the description too.
+                element.all(CSS.CONTENTAFTERLINK).toggleClass(CSS.DIMMEDTEXT);
+            }
+            // Toggle availablity info for conditional activities.
+            var availabilityinfo = element.one(CSS.AVAILABILITYINFODIV);
+
+            if (availabilityinfo) {
+                availabilityinfo.toggleClass(CSS.ACCESSHIDECLASS);
+            }
             return value;
         },
         /**
index f49a799..66cddda 100644 (file)
@@ -6,7 +6,7 @@
 .moodle-dialogue-base .moodle-dialogue-hd {font-size:110%;color:inherit;font-weight:bold;text-align:left;padding:5px 6px;margin:0;border-bottom:1px solid #ccc;background-color:#f6f6f6;}
 .moodle-dialogue-base .closebutton {background-image:url(sprite.png);width:25px;height:15px;background-repeat:no-repeat;float:right;vertical-align:middle;display:inline-block;cursor:pointer;}
 .moodle-dialogue-base .moodle-dialogue-bd {padding:5px; overflow: auto;}
-.moodle-dialogue-base .moodle-dialogue-fd {}
+.moodle-dialogue-base .moodle-dialogue-ft {}
 
 .moodle-dialogue-confirm .confirmation-dialogue {text-align:center;}
 .moodle-dialogue-confirm .confirmation-message {margin:0.5em 1em;}
index 8b91443..2ed9af0 100644 (file)
@@ -21,7 +21,7 @@ var DIALOGUE_NAME = 'Moodle dialogue',
         HEADER : 'moodle-dialogue-hd',
         BODY : 'moodle-dialogue-bd',
         CONTENT : 'moodle-dialogue-content',
-        FOOTER : 'moodle-dialogue-fd',
+        FOOTER : 'moodle-dialogue-ft',
         HIDDEN : 'hidden',
         LIGHTBOX : 'moodle-dialogue-lightbox'
     };
@@ -35,7 +35,7 @@ var DIALOGUE = function(config) {
             .append(C('<div id="'+id+'" class="'+CSS.WRAP+'"></div>')
                 .append(C('<div class="'+CSS.HEADER+' yui3-widget-hd"></div>'))
                 .append(C('<div class="'+CSS.BODY+' yui3-widget-bd"></div>'))
-                .append(C('<div class="'+CSS.CONTENT+' yui3-widget-ft"></div>')));
+                .append(C('<div class="'+CSS.FOOTER+' yui3-widget-ft"></div>')));
     Y.one(document.body).append(config.notificationBase);
     config.srcNode =    '#'+id;
     config.width =      config.width || '400px';
index d7d3b5b..a1e634b 100644 (file)
@@ -1503,7 +1503,7 @@ class grade_structure {
 
             $url->param('action', 'show');
 
-            $hideicon = $OUTPUT->action_icon($url, new pix_icon('t/'.$type, $tooltip, 'moodle', array('alt'=>$strshow, 'class'=>'iconsmall')));
+            $hideicon = $OUTPUT->action_icon($url, new pix_icon('t/'.$type, $tooltip, 'moodle', array('alt'=>$strshow, 'class'=>'smallicon')));
 
         } else {
             $url->param('action', 'hide');
index ea8f076..3dbac53 100644 (file)
@@ -225,7 +225,7 @@ class grade_report_grader extends grade_report {
                 $changedgrades = true;
 
             } else if ($datatype === 'feedback') {
-                if ($oldvalue->feedback === $postedvalue) {
+                if (($oldvalue->feedback === $postedvalue) or ($oldvalue->feedback === NULL and empty($postedvalue))) {
                     continue;
                 }
             }
index d55667d..d926cd2 100644 (file)
@@ -25,6 +25,7 @@
 
 $string['addfields'] = 'Add {$a} fields to form';
 $string['advancedelement'] = 'Advanced element';
+$string['close'] = 'Close';
 $string['day'] = 'Day';
 $string['display'] = 'Display';
 $string['err_alphanumeric'] = 'You must enter only letters or numbers here.';
index 57d643f..b278c14 100644 (file)
  */
 
 class Bennu {
-    function timestamp_to_datetime($t = NULL) {
+    static function timestamp_to_datetime($t = NULL) {
         if($t === NULL) {
             $t = time();
         }
         return gmstrftime('%Y%m%dT%H%M%SZ', $t);
     }
 
-    function generate_guid() {
+    static function generate_guid() {
         // Implemented as per the Network Working Group draft on UUIDs and GUIDs
     
         // These two octets get special treatment
index 6614b39..d264083 100644 (file)
@@ -14,7 +14,7 @@
  */
 
 class iCalendar_parameter {
-    function multiple_values_allowed($parameter) {
+    static function multiple_values_allowed($parameter) {
         switch($parameter) {
             case 'DELEGATED-FROM':
             case 'DELEGATED-TO':
@@ -25,7 +25,7 @@ class iCalendar_parameter {
         }
     }
 
-    function default_value($parameter) {
+    static function default_value($parameter) {
         switch($parameter) {
             case 'CUTYPE':   return 'INDIVIDUAL';
             case 'FBTYPE':   return 'BUSY';
@@ -38,7 +38,7 @@ class iCalendar_parameter {
         }
     }
 
-    function is_valid_value(&$parent_property, $parameter, $value) {
+    static function is_valid_value(&$parent_property, $parameter, $value) {
         switch($parameter) {
             // These must all be a URI
             case 'ALTREP':
@@ -191,7 +191,7 @@ class iCalendar_parameter {
         }
     }
 
-    function do_value_formatting($parameter, $value) {
+    static function do_value_formatting($parameter, $value) {
         switch($parameter) {
             // Parameters of type CAL-ADDRESS or URI MUST be double-quoted
             case 'ALTREP':
@@ -232,7 +232,7 @@ class iCalendar_parameter {
         }
     }
 
-    function undo_value_formatting($parameter, $value) {
+    static function undo_value_formatting($parameter, $value) {
     }
 
 }
index 1109b22..9414db0 100644 (file)
@@ -220,7 +220,7 @@ YUI.add('moodle-form-dateselector', function(Y) {
                     config.september,
                     config.october,
                     config.november,
-                    config.december ],
+                    config.december ]
             });
             this.calendar.changePageEvent.subscribe(function(){
                 this.fix_position();
index 4189c37..0230e60 100644 (file)
@@ -1374,6 +1374,42 @@ function hide_item(itemid) {
     }
 }
 
+M.util.help_popups = {
+    setup : function(Y) {
+        Y.one('body').delegate('click', this.open_popup, 'a.helplinkpopup', this);
+    },
+    open_popup : function(e) {
+        // Prevent the default page action
+        e.preventDefault();
+
+        // Grab the anchor that was clicked
+        var anchor = e.target.ancestor('a', true);
+        var args = {
+            'name'          : 'popup',
+            'url'           : anchor.getAttribute('href'),
+            'options'       : ''
+        };
+        var options = [
+            'height=600',
+            'width=800',
+            'top=0',
+            'left=0',
+            'menubar=0',
+            'location=0',
+            'scrollbars',
+            'resizable',
+            'toolbar',
+            'status',
+            'directories=0',
+            'fullscreen=0',
+            'dependent'
+        ]
+        args.options = options.join(',');
+
+        openpopup(e, args);
+    }
+}
+
 M.util.help_icon = {
     Y : null,
     instance : null,
@@ -1388,16 +1424,17 @@ M.util.help_icon = {
         event.preventDefault();
         if (M.util.help_icon.instance === null) {
             var Y = M.util.help_icon.Y;
-            Y.use('overlay', 'io-base', 'event-mouseenter', 'node', 'event-key', function(Y) {
+            Y.use('overlay', 'io-base', 'event-mouseenter', 'node', 'event-key', 'escape', function(Y) {
                 var help_content_overlay = {
                     helplink : null,
                     overlay : null,
                     init : function() {
 
-                        var closebtn = Y.Node.create('<a id="closehelpbox" href="#"><img  src="'+M.util.image_url('t/delete', 'moodle')+'" /></a>');
+                        var strclose = Y.Escape.html(M.str.form.close);
+                        var footerbtn = Y.Node.create('<button class="closebtn">'+strclose+'</button>');
                         // Create an overlay from markup
                         this.overlay = new Y.Overlay({
-                            headerContent: closebtn,
+                            footerContent: footerbtn,
                             bodyContent: '',
                             id: 'helppopupbox',
                             width:'400px',
@@ -1406,7 +1443,7 @@ M.util.help_icon = {
                         });
                         this.overlay.render(Y.one(document.body));
 
-                        closebtn.on('click', this.overlay.hide, this.overlay);
+                        footerbtn.on('click', this.overlay.hide, this.overlay);
 
                         var boundingBox = this.overlay.get("boundingBox");
 
@@ -1422,9 +1459,6 @@ M.util.help_icon = {
                                 this.overlay.hide();
                             }
                         }, this);
-
-                        Y.on("key", this.close, closebtn , "down:13", this);
-                        closebtn.on('click', this.close, this);
                     },
 
                     close : function(e) {
@@ -1434,9 +1468,16 @@ M.util.help_icon = {
                     },
 
                     display : function(event, args) {
+                        if (Y.one('html').get('dir') == 'rtl') {
+                            var overlayPosition = [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.LC];
+                        } else {
+                            var overlayPosition = [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.RC];
+                        }
+
                         this.helplink = args.node;
+
                         this.overlay.set('bodyContent', Y.Node.create('<img src="'+M.cfg.loadingicon+'" class="spinner" />'));
-                        this.overlay.set("align", {node:args.node, points:[Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.RC]});
+                        this.overlay.set("align", {node:args.node, points: overlayPosition});
 
                         var fullurl = args.url;
                         if (!args.url.match(/https?:\/\//)) {
index dd03dc8..85e2e7a 100644 (file)
@@ -372,6 +372,9 @@ class core_renderer extends renderer_base {
         // flow player embedding support
         $this->page->requires->js_function_call('M.util.load_flowplayer');
 
+        // Set up help link popups for all links with the helplinkpopup class
+        $this->page->requires->js_init_call('M.util.help_popups.setup');
+
         $this->page->requires->js_function_call('setTimeout', array('fix_column_widths()', 20));
 
         $focus = $this->page->focuscontrol;
@@ -1495,9 +1498,10 @@ class core_renderer extends renderer_base {
      *
      * @param string $path The page link after doc root and language, no leading slash.
      * @param string $text The text to be displayed for the link
+     * @param boolean $forcepopup Whether to force a popup regardless of the value of $CFG->doctonewwindow
      * @return string
      */
-    public function doc_link($path, $text = '') {
+    public function doc_link($path, $text = '', $forcepopup = false) {
         global $CFG;
 
         $icon = $this->pix_icon('docs', $text, 'moodle', array('class'=>'iconhelp'));
@@ -1505,8 +1509,8 @@ class core_renderer extends renderer_base {
         $url = new moodle_url(get_docs_url($path));
 
         $attributes = array('href'=>$url);
-        if (!empty($CFG->doctonewwindow)) {
-            $attributes['id'] = $this->add_action_handler(new popup_action('click', $url));
+        if (!empty($CFG->doctonewwindow) || $forcepopup) {
+            $attributes['class'] = 'helplinkpopup';
         }
 
         return html_writer::tag('a', $icon.$text, $attributes);
@@ -1733,6 +1737,7 @@ class core_renderer extends renderer_base {
         $output = html_writer::tag('a', $output, $attributes);
 
         $this->page->requires->js_init_call('M.util.help_icon.add', array(array('id'=>$id, 'url'=>$url->out(false))));
+        $this->page->requires->string_for_js('close', 'form');
 
         // and finally span
         return html_writer::tag('span', $output, array('class' => 'helplink'));
@@ -1798,6 +1803,7 @@ class core_renderer extends renderer_base {
         $output = html_writer::tag('a', $output, $attributes);
 
         $this->page->requires->js_init_call('M.util.help_icon.add', array(array('id'=>$id, 'url'=>$url->out(false))));
+        $this->page->requires->string_for_js('close', 'form');
 
         // and finally span
         return html_writer::tag('span', $output, array('class' => 'helplink'));
index 6de22af..2a08616 100644 (file)
@@ -727,16 +727,19 @@ class flexible_table {
     function col_fullname($row) {
         global $COURSE, $CFG;
 
-        if (!$this->download) {
-            $profileurl = new moodle_url('/user/profile.php', array('id' => $row->{$this->useridfield}));
-            if ($COURSE->id != SITEID) {
-                $profileurl->param('course', $COURSE->id);
-            }
-            return html_writer::link($profileurl, fullname($row));
+        $name = fullname($row);
+        if ($this->download) {
+            return $name;
+        }
 
+        $userid = $row->{$this->useridfield};
+        if ($COURSE->id == SITEID) {
+            $profileurl = new moodle_url('/user/profile.php', array('id' => $userid));
         } else {
-            return fullname($row);
+            $profileurl = new moodle_url('/user/view.php',
+                    array('id' => $userid, 'course' => $COURSE->id));
         }
+        return html_writer::link($profileurl, $name);
     }
 
     /**
index 91c5f5f..8ca17bd 100644 (file)
@@ -1164,9 +1164,9 @@ class assignment_upload extends assignment_base {
         }
         $filename = str_replace(' ', '_', clean_filename($this->course->shortname.'-'.$this->assignment->name.'-'.$groupname.$this->assignment->id.".zip")); //name of new zip file.
         foreach ($submissions as $submission) {
-            // If assignment is open and submission is not finalized then don't add it to zip.
+            // If assignment is open and submission is not finalized and marking button enabled then don't add it to zip.
             $submissionstatus = $this->is_finalized($submission);
-            if ($this->isopen() && empty($submissionstatus)) {
+            if ($this->isopen() && empty($submissionstatus) && !empty($this->assignment->var4)) {
                 continue;
             }
             $a_userid = $submission->userid; //get userid
index 3fb1085..c4709f0 100644 (file)
@@ -40,6 +40,152 @@ function xmldb_book_upgrade($oldversion) {
     // Moodle v2.3.0 release upgrade line
     // Put any upgrade step following this
 
+    // Note: The next steps (up to 2012061710 included, are a "replay" of old upgrade steps,
+    // because some sites updated to Moodle 2.3 didn't have the latest contrib mod_book
+    // installed, so some required changes were missing.
+    //
+    // All the steps are run conditionally so sites upgraded from latest contrib mod_book or
+    // new (2.3 and upwards) sites won't get affected.
+    //
+    // See MDL-35297 and commit msg for more information.
+
+    if ($oldversion < 2012061703) {
+        // Rename field summary on table book to intro
+        $table = new xmldb_table('book');
+        $field = new xmldb_field('summary', XMLDB_TYPE_TEXT, null, null, null, null, null, 'name');
+
+        // Launch rename field summary
+        if ($dbman->field_exists($table, $field)) {
+            $dbman->rename_field($table, $field, 'intro');
+        }
+
+        // book savepoint reached
+        upgrade_mod_savepoint(true, 2012061703, 'book');
+    }
+
+    if ($oldversion < 2012061704) {
+        // Define field introformat to be added to book
+        $table = new xmldb_table('book');
+        $field = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0', 'intro');
+
+        // Launch add field introformat
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+            // Conditionally migrate to html format in intro
+            // Si está activo el htmleditor!!!!!
+            if ($CFG->texteditors !== 'textarea') {
+                $rs = $DB->get_recordset('book', array('introformat'=>FORMAT_MOODLE), '', 'id,intro,introformat');
+                foreach ($rs as $b) {
+                    $b->intro       = text_to_html($b->intro, false, false, true);
+                    $b->introformat = FORMAT_HTML;
+                    $DB->update_record('book', $b);
+                    upgrade_set_timeout();
+                }
+                unset($b);
+                $rs->close();
+            }
+        }
+
+        // book savepoint reached
+        upgrade_mod_savepoint(true, 2012061704, 'book');
+    }
+
+    if ($oldversion < 2012061705) {
+        // Define field introformat to be added to book
+        $table = new xmldb_table('book_chapters');
+        $field = new xmldb_field('contentformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0', 'content');
+
+        // Launch add field introformat
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+
+            $DB->set_field('book_chapters', 'contentformat', FORMAT_HTML, array());
+        }
+
+        // book savepoint reached
+        upgrade_mod_savepoint(true, 2012061705, 'book');
+    }
+
+    if ($oldversion < 2012061706) {
+        require_once("$CFG->dirroot/mod/book/db/upgradelib.php");
+
+        $sqlfrom = "FROM {book} b
+                    JOIN {modules} m ON m.name = 'book'
+                    JOIN {course_modules} cm ON (cm.module = m.id AND cm.instance = b.id)";
+
+        $count = $DB->count_records_sql("SELECT COUNT('x') $sqlfrom");
+
+        if ($rs = $DB->get_recordset_sql("SELECT b.id, b.course, cm.id AS cmid $sqlfrom ORDER BY b.course, b.id")) {
+
+            $pbar = new progress_bar('migratebookfiles', 500, true);
+
+            $i = 0;
+            foreach ($rs as $book) {
+                $i++;
+                upgrade_set_timeout(360); // set up timeout, may also abort execution
+                $pbar->update($i, $count, "Migrating book files - $i/$count.");
+
+                $context = context_module::instance($book->cmid);
+
+                mod_book_migrate_moddata_dir_to_legacy($book, $context, '/');
+
+                // remove dirs if empty
+                @rmdir("$CFG->dataroot/$book->course/$CFG->moddata/book/$book->id/");
+                @rmdir("$CFG->dataroot/$book->course/$CFG->moddata/book/");
+                @rmdir("$CFG->dataroot/$book->course/$CFG->moddata/");
+                @rmdir("$CFG->dataroot/$book->course/");
+            }
+            $rs->close();
+        }
+
+        // book savepoint reached
+        upgrade_mod_savepoint(true, 2012061706, 'book');
+    }
+
+    if ($oldversion < 2012061707) {
+        // Define field disableprinting to be dropped from book
+        $table = new xmldb_table('book');
+        $field = new xmldb_field('disableprinting');
+
+        // Conditionally launch drop field disableprinting
+        if ($dbman->field_exists($table, $field)) {
+            $dbman->drop_field($table, $field);
+        }
+
+        // book savepoint reached
+        upgrade_mod_savepoint(true, 2012061707, 'book');
+    }
+
+    if ($oldversion < 2012061708) {
+        unset_config('book_tocwidth');
+
+        // book savepoint reached
+        upgrade_mod_savepoint(true, 2012061708, 'book');
+    }
+
+    if ($oldversion < 2012061709) {
+        require_once("$CFG->dirroot/mod/book/db/upgradelib.php");
+
+        mod_book_migrate_all_areas();
+
+        upgrade_mod_savepoint(true, 2012061709, 'book');
+    }
+
+    if ($oldversion < 2012061710) {
+
+        // Define field revision to be added to book
+        $table = new xmldb_table('book');
+        $field = new xmldb_field('revision', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'customtitles');
+
+        // Conditionally launch add field revision
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+
+        // book savepoint reached
+        upgrade_mod_savepoint(true, 2012061710, 'book');
+    }
+    // End of MDL-35297 "replayed" steps.
 
     return true;
 }
diff --git a/mod/book/db/upgradelib.php b/mod/book/db/upgradelib.php
new file mode 100644 (file)
index 0000000..5411930
--- /dev/null
@@ -0,0 +1,168 @@
+<?php
+// This file is part of Book module for 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/>.
+
+/**
+ * Book module upgrade related helper functions
+ *
+ * @package    mod_book
+ * @copyright  2010 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Migrate book files stored in moddata folders.
+ *
+ * Please note it was a big mistake to store the files there in the first place!
+ *
+ * @param stdClass $book
+ * @param stdClass $context
+ * @param string $path
+ * @return void
+ */
+function mod_book_migrate_moddata_dir_to_legacy($book, $context, $path) {
+    global $OUTPUT, $CFG;
+
+    $base = "$CFG->dataroot/$book->course/$CFG->moddata/book/$book->id";
+    $fulldir = $base.$path;
+
+    if (!is_dir($fulldir)) {
+        // does not exist
+        return;
+    }
+
+    $fs      = get_file_storage();
+    $items   = new DirectoryIterator($fulldir);
+
+    foreach ($items as $item) {
+        if ($item->isDot()) {
+            unset($item); // release file handle
+            continue;
+        }
+
+        if ($item->isLink()) {
+            // do not follow symlinks - they were never supported in moddata, sorry
+            unset($item); // release file handle
+            continue;
+        }
+
+        if ($item->isFile()) {
+            if (!$item->isReadable()) {
+                echo $OUTPUT->notification(" File not readable, skipping: ".$fulldir.$item->getFilename());
+                unset($item); // release file handle
+                continue;
+            }
+
+            $filepath = clean_param("/$CFG->moddata/book/$book->id".$path, PARAM_PATH);
+            $filename = clean_param($item->getFilename(), PARAM_FILE);
+
+            if ($filename === '') {
+                // unsupported chars, sorry
+                unset($item); // release file handle
+                continue;
+            }
+
+            if (textlib::strlen($filepath) > 255) {
+                echo $OUTPUT->notification(" File path longer than 255 chars, skipping: ".$fulldir.$item->getFilename());
+                unset($item); // release file handle
+                continue;
+            }
+
+            if (!$fs->file_exists($context->id, 'course', 'legacy', '0', $filepath, $filename)) {
+                $file_record = array('contextid'=>$context->id, 'component'=>'course', 'filearea'=>'legacy', 'itemid'=>0, 'filepath'=>$filepath, 'filename'=>$filename,
+                                     'timecreated'=>$item->getCTime(), 'timemodified'=>$item->getMTime());
+                $fs->create_file_from_pathname($file_record, $fulldir.$item->getFilename());
+            }
+            $oldpathname = $fulldir.$item->getFilename();
+            unset($item); // release file handle
+            @unlink($oldpathname);
+
+        } else {
+            // migrate recursively all subdirectories
+            $oldpathname = $base.$item->getFilename().'/';
+            $subpath     = $path.$item->getFilename().'/';
+            unset($item);  // release file handle
+            mod_book_migrate_moddata_dir_to_legacy($book, $context, $subpath);
+            @rmdir($oldpathname); // deletes dir if empty
+        }
+    }
+    unset($items); // release file handles
+}
+
+/**
+ * Migrate legacy files in intro and chapters
+ * @return void
+ */
+function mod_book_migrate_all_areas() {
+    global $DB;
+
+    $rsbooks = $DB->get_recordset('book');
+    foreach($rsbooks as $book) {
+        upgrade_set_timeout(360); // set up timeout, may also abort execution
+        $cm = get_coursemodule_from_instance('book', $book->id);
+        $context = context_module::instance($cm->id);
+        mod_book_migrate_area($book, 'intro', 'book', $book->course, $context, 'mod_book', 'intro', 0);
+
+        $rschapters = $DB->get_recordset('book_chapters', array('bookid'=>$book->id));
+        foreach ($rschapters as $chapter) {
+            mod_book_migrate_area($chapter, 'content', 'book_chapters', $book->course, $context, 'mod_book', 'chapter', $chapter->id);
+        }
+        $rschapters->close();
+    }
+    $rsbooks->close();
+}
+
+/**
+ * Migrate one area, this should be probably part of moodle core...
+ *
+ * @param stdClass $record object to migrate files (book, chapter)
+ * @param string $field field in the record we are going to migrate
+ * @param string $table DB table containing the information to migrate
+ * @param int $courseid id of the course the book module belongs to
+ * @param context_module $context context of the book module
+ * @param string $component component to be used for the migrated files
+ * @param string $filearea filearea to be used for the migrated files
+ * @param int $itemid id to be used for the migrated files
+ * @return void
+ */
+function mod_book_migrate_area($record, $field, $table, $courseid, $context, $component, $filearea, $itemid) {
+    global $CFG, $DB;
+
+    $fs = get_file_storage();
+
+    foreach(array(get_site()->id, $courseid) as $cid) {
+        $matches = null;
+        $ooldcontext = context_course::instance($cid);
+        if (preg_match_all("|$CFG->wwwroot/file.php(\?file=)?/$cid(/[^\s'\"&\?#]+)|", $record->$field, $matches)) {
+            $file_record = array('contextid'=>$context->id, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid);
+            foreach ($matches[2] as $i=>$filepath) {
+                if (!$file = $fs->get_file_by_hash(sha1("/$ooldcontext->id/course/legacy/0".$filepath))) {
+                    continue;
+                }
+                try {
+                    if (!$newfile = $fs->get_file_by_hash(sha1("/$context->id/$component/$filearea/$itemid".$filepath))) {
+                        $fs->create_file_from_storedfile($file_record, $file);
+                    }
+                    $record->$field = str_replace($matches[0][$i], '@@PLUGINFILE@@'.$filepath, $record->$field);
+                } catch (Exception $ex) {
+                    // ignore problems
+                }
+                $DB->set_field($table, $field, $record->$field, array('id'=>$record->id));
+            }
+        }
+    }
+}
\ No newline at end of file
index e187cb3..f37c00d 100644 (file)
@@ -25,6 +25,6 @@
 defined('MOODLE_INTERNAL') || die;
 
 $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics)
-$module->version   = 2012061702; // The current module version (Date: YYYYMMDDXX)
+$module->version   = 2012061710; // The current module version (Date: YYYYMMDDXX)
 $module->requires  = 2012061700; // Requires this Moodle version
 $module->cron      = 0;          // Period for cron to check this module (secs)
index fe824c4..0e544df 100644 (file)
 
 /** Unknown Styles ??? */
 #email .unsubscribelink {margin-top:20px;}
+
+
+/* Forumpost unread
+-------------------------*/
+#page-mod-forum-view .unread,
+.forumpost.unread .row.header,
+.path-course-view .unread,
+span.unread {
+    background-color: #FFD;
+}
+.forumpost.unread .row.header {
+    border-bottom: 1px solid #DDD;
+}
\ No newline at end of file
index 322ccdd..6efbdbc 100644 (file)
@@ -401,7 +401,7 @@ bank window's title is prominent enough*/
 #page-mod-quiz-edit.dir-rtl div.question {clear: right;}
 #page-mod-quiz-edit.dir-rtl div.question div.qnum {float: right;}
 #page-mod-quiz-edit.dir-rtl div.editq div.question div.content {float: right;height: 40px;}
-#page-mod-quiz-edit.dir-rtl div.question div.content div.points {left: 5px;right:auto;}
+#page-mod-quiz-edit.dir-rtl div.question div.content div.points {left: 50px;right:auto;}
 #page-mod-quiz-edit.dir-rtl div.question div.content div.questioncontrols {float: left;left: 0.3em; right:auto;}
 #page-mod-quiz-edit.dir-rtl .editq div.question div.content .singlequestion .questioneditbutton .questionname,
 #page-mod-quiz-edit.dir-rtl .editq div.question div.content .singlequestion .questioneditbutton .questiontext {float: right; padding-right: 0.3em;}
@@ -414,4 +414,6 @@ bank window's title is prominent enough*/
 #page-mod-quiz-edit.dir-rtl .quizpagedelete {left: 0.2em;right:auto;}
 #page-mod-quiz-edit.dir-rtl div.quizcontents {clear: right;float: right;}
 #page-mod-quiz-edit.dir-rtl .questionbankwindow.block {float: left;}
-#page-question-edit.dir-rtl td.creatorname, #page-question-edit.dir-rtl td.modifiername {text-align: center;}
\ No newline at end of file
+#page-question-edit.dir-rtl td.creatorname, #page-question-edit.dir-rtl td.modifiername {text-align: center;}
+.path-question-type.dir-rtl input[name="defaultmark"],
+#page-mod-quiz-edit.dir-rtl div.points input {direction: ltr;text-align: left;}
index 132b629..d8f5dbf 100644 (file)
@@ -6,3 +6,17 @@
 .que.calculated .answer input[type="text"] {
     width: 30%;
 }
+
+/* Numeric INPUT text boxes should be left aligned in RTL mode
+*/
+#page-question-type-calculated.dir-rtl input[name^="answer"],
+#page-question-type-calculated.dir-rtl input[name^="unit"],
+#page-question-type-calculated.dir-rtl input[name^="multiplier"],
+#page-question-type-calculated.dir-rtl input[name^="calcmax"],
+#page-question-type-calculated.dir-rtl input[name^="calcmin"],
+#page-question-type-calculated.dir-rtl input[name^="number"],
+#page-question-type-calculated.dir-rtl input[name^="tolerance"]
+{
+    direction: ltr;
+    text-align: left;
+}
index e94c202..031605e 100644 (file)
@@ -110,10 +110,10 @@ class qtype_multichoice_edit_form extends question_edit_form {
             //check no of choices
             $trimmedanswer = trim($answer['text']);
             $fraction = (float) $data['fraction'][$key];
-            if (empty($trimmedanswer) && empty($fraction)) {
+            if ($trimmedanswer === '' && empty($fraction)) {
                 continue;
             }
-            if (empty($trimmedanswer)) {
+            if ($trimmedanswer === '') {
                 $errors['fraction['.$key.']'] = get_string('errgradesetanswerblank', 'qtype_multichoice');
             }
 
index 784c855..50958df 100644 (file)
@@ -6,3 +6,15 @@
 .que.numerical .answer input[type="text"] {
     width: 30%;
 }
+
+/* Numeric INPUT text boxes should be left aligned in RTL mode
+*/
+#page-question-type-numerical.dir-rtl input[name="unitpenalty"],
+#page-question-type-numerical.dir-rtl input[name^="answer"],
+#page-question-type-numerical.dir-rtl input[name^="tolerance"],
+#page-question-type-numerical.dir-rtl input[name^="multiplier"],
+#page-question-type-numerical.dir-rtl input[name^="unit"]
+{
+    direction: ltr;
+    text-align: left;
+}
index 4a5151b..8748930 100644 (file)
@@ -477,8 +477,11 @@ body.tag .managelink {padding: 5px;}
 #helppopupbox {background-color: #eee; border: 1px solid #848484;z-index: 10000 !important;}
 #helppopupbox .yui3-widget-hd {float:right;margin:3px 3px 0 0;}
 #helppopupbox .yui3-widget-bd {margin:0 1em 1em 1em;border-top:1px solid #eee;}
+#helppopupbox .yui3-widget-ft {text-align: center;}
+#helppopupbox .yui3-widget-ft .closebtn {margin:0 1em 1em 1em;}
 #helppopupbox .helpheading {font-size: 1em;}
 #helppopupbox .spinner {margin:1em;}
+.dir-rtl #helppopupbox .yui3-widget-hd {float:left;margin:3px 0 0 3px;}
 
 /**
  * Custom menu
index a617287..242e021 100644 (file)
@@ -1040,7 +1040,7 @@ table.glossarypost td.entry h3 {
 
 div#intro {
     border: none;
-    text-align: center;
+    text-align: left;
     font-size: 14px;
     color: #333333;
 }
index aa88131..0ca7509 100644 (file)
@@ -293,6 +293,7 @@ $PAGE->set_title("$course->shortname: $streditmyprofile");
 $PAGE->set_heading($course->fullname);
 
 echo $OUTPUT->header();
+echo $OUTPUT->heading($userfullname);
 
 if ($email_changed) {
     echo $email_changed_html;
index 2f54d4e..8be8f1f 100644 (file)
@@ -62,7 +62,12 @@ class user_filter_text extends user_filter_type {
                 // no data - no change except for empty filter
                 return false;
             }
-            return array('operator'=>(int)$formdata->$operator, 'value'=>$formdata->$field);
+            // If field value is set then use it, else it's null.
+            $fieldvalue = null;
+            if (isset($formdata->$field)) {
+                $fieldvalue = $formdata->$field;
+            }
+            return array('operator' => (int)$formdata->$operator, 'value' =>  $fieldvalue);
         }
 
         return false;
index b25cd6c..6ccbfde 100644 (file)
@@ -34,7 +34,7 @@ $version  = 2012062502.09;              // YYYYMMDD      = weekly release date o
                                         //         RR    = release increments - 00 in DEV branches
                                         //           .XX = incremental changes
 
-$release  = '2.3.3+ (Build: 20121018)'; // Human-friendly version name
+$release  = '2.3.2+ (Build: 20121018)'; // Human-friendly version name
 
 $branch   = '23';                       // this version's branch
 $maturity = MATURITY_STABLE;            // this version's maturity level