Merge branch 'MDL-42704-master' of git://github.com/jamiepratt/moodle
authorDan Poltawski <dan@moodle.com>
Fri, 8 Nov 2013 03:11:28 +0000 (11:11 +0800)
committerDan Poltawski <dan@moodle.com>
Fri, 8 Nov 2013 03:11:28 +0000 (11:11 +0800)
112 files changed:
admin/settings/development.php
admin/tool/behat/lang/en/tool_behat.php
admin/tool/langimport/lang/en/tool_langimport.php
backup/util/ui/tests/behat/duplicate_activities.feature
blocks/tests/behat/behat_blocks.php
blocks/tests/behat/configure_block_throughout_site.feature
blocks/tests/behat/manage_blocks.feature
blocks/tests/behat/return_block_original_state.feature
course/classes/management_renderer.php
course/lib.php
course/management.php
course/renderer.php
course/tests/behat/activities_visibility_icons.feature
course/yui/dragdrop/dragdrop.js
course/yui/toolboxes/toolboxes.js
lang/en/admin.php
lang/en/backup.php
lang/en/badges.php
lang/en/form.php
lang/en/question.php
lib/boxlib.php
lib/classes/collator.php
lib/classes/plugin_manager.php
lib/db/upgrade.php
lib/ddl/tests/ddl_test.php
lib/dml/mssql_native_moodle_database.php
lib/dml/oci_native_moodle_database.php
lib/editor/tinymce/db/upgrade.php
lib/editor/tinymce/settings.php
lib/editor/tinymce/styles.css
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/button_bg.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/ui.css
lib/editor/tinymce/version.php
lib/filestorage/mbz_packer.php
lib/filestorage/tests/mbz_packer_test.php
lib/filestorage/tests/tgz_packer_test.php
lib/filestorage/tgz_packer.php
lib/flickrlib.php
lib/oauthlib.php
lib/outputrenderers.php
lib/testing/generator/repository_generator.php
lib/upgrade.txt
lib/yui/build/moodle-core-actionmenu/moodle-core-actionmenu-debug.js
lib/yui/build/moodle-core-actionmenu/moodle-core-actionmenu-min.js
lib/yui/build/moodle-core-actionmenu/moodle-core-actionmenu.js
lib/yui/dragdrop/dragdrop.js
lib/yui/src/actionmenu/js/actionmenu.js
mod/assign/feedback/editpdf/lang/en/assignfeedback_editpdf.php
mod/assign/feedback/editpdf/settings.php
mod/assign/feedback/editpdf/styles.css
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-debug.js
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-min.js
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor.js
mod/assign/feedback/editpdf/yui/src/editor/js/commentsearch.js
mod/assign/feedback/editpdf/yui/src/editor/js/dropdown.js
mod/assign/lang/en/assign.php
mod/choice/lang/en/choice.php
mod/quiz/addrandom.php
mod/quiz/comment.php
mod/quiz/index.php
mod/quiz/lang/en/quiz.php
mod/quiz/overridedelete.php
mod/quiz/overrideedit.php
mod/quiz/overrides.php
mod/quiz/renderer.php
mod/quiz/report/default.php
mod/quiz/report/grading/report.php
mod/quiz/report/overview/report.php
mod/quiz/report/statistics/report.php
mod/quiz/report/upgrade.txt
mod/quiz/reviewquestion.php
mod/quiz/startattempt.php
mod/quiz/styles.css
mod/quiz/upgrade.txt
mod/resource/lang/en/resource.php
mod/survey/lang/en/survey.php
mod/url/lang/en/url.php
mod/workshop/allocation/random/lang/en/workshopallocation_random.php
portfolio/boxnet/db/upgrade.php [new file with mode: 0644]
portfolio/boxnet/db/upgradelib.php [new file with mode: 0644]
portfolio/boxnet/lang/en/portfolio_boxnet.php
portfolio/boxnet/lib.php
portfolio/boxnet/version.php
portfolio/flickr/lib.php
question/engine/renderer.php
question/engine/upgrade.txt
question/type/description/tests/walkthrough_test.php
question/type/numerical/lang/en/qtype_numerical.php
question/type/random/lang/en/qtype_random.php
question/type/truefalse/tests/walkthrough_test.php
repository/boxnet/cli/migrationv1.php [new file with mode: 0644]
repository/boxnet/db/upgrade.php [new file with mode: 0644]
repository/boxnet/db/upgradelib.php [new file with mode: 0644]
repository/boxnet/lang/en/repository_boxnet.php
repository/boxnet/lib.php
repository/boxnet/locallib.php [new file with mode: 0644]
repository/boxnet/migrationv1.php [new file with mode: 0644]
repository/boxnet/tests/generator/lib.php
repository/boxnet/version.php
repository/recent/lang/en/repository_recent.php
theme/anomaly/renderers.php
theme/base/style/core.css
theme/base/style/course.css
theme/base/style/dock.css
theme/base/style/filemanager.css
theme/base/style/question.css
theme/bootstrapbase/less/moodle/core.less
theme/bootstrapbase/less/moodle/course.less
theme/bootstrapbase/less/moodle/filemanager.less
theme/bootstrapbase/less/moodle/question.less
theme/bootstrapbase/style/moodle.css
version.php

index b99d519..a1ad6e0 100644 (file)
@@ -27,6 +27,9 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
     $temp->add(new admin_setting_configcheckbox('enabletgzbackups',
             new lang_string('enabletgzbackups', 'admin'),
             new lang_string('enabletgzbackups_desc', 'admin'), 0));
+    $temp->add(new admin_setting_php_extension_enabled('zlibenabled',
+            get_string('zlibenabled', 'admin'),
+            get_string('enabletgzbackups_nozlib', 'admin'), 'zlib'));
 
     $ADMIN->add('experimental', $temp);
 
index a67581d..d8b2b51 100644 (file)
@@ -38,7 +38,7 @@ $string['stepsdefinitionscontains'] = 'Contains';
 $string['stepsdefinitionsfilters'] = 'Steps definitions';
 $string['stepsdefinitionstype'] = 'Type';
 $string['theninfo'] = 'Then. Checkings to ensure the outcomes are the expected ones';
-$string['unknownexceptioninfo'] = 'There was a problem with Selenium or the browser, try to upgrade Selenium to the latest version. Error: ';
+$string['unknownexceptioninfo'] = 'There was a problem with Selenium or your browser. Please ensure you are using the latest version of Selenium. Error:';
 $string['viewsteps'] = 'Filter';
 $string['wheninfo'] = 'When. Actions that provokes an event';
 $string['wrongbehatsetup'] = 'Something is wrong with behat setup, ensure:<ul>
index 87dee88..d31ec68 100644 (file)
@@ -38,7 +38,7 @@ $string['nolangupdateneeded'] = 'All your language packs are up to date, no upda
 $string['pluginname'] = 'Language packs';
 $string['purgestringcaches'] = 'Purge string caches';
 $string['remotelangnotavailable'] = 'Because Moodle cannot connect to download.moodle.org, it is not possible for language packs to be installed automatically. Please download the appropriate ZIP file(s) from <a href="http://download.moodle.org/langpack/">download.moodle.org/langpack</a>, copy them to your {$a} directory and unzip them manually.';
-$string['uninstall'] = 'Uninstall selected language pack(s)';
+$string['uninstall'] = 'Uninstall selected language pack';
 $string['uninstallconfirm'] = 'You are about to completely uninstall language pack {$a}, are you sure?';
 $string['updatelangs'] = 'Update all installed language packs';
 
index 8fe100c..9675a62 100644 (file)
@@ -23,6 +23,7 @@ Feature: Duplicate activities
       | Description | Test database description |
     And I open "Test database name" actions menu
     When I click on "Duplicate" "link" in the "Test database name" activity
+    And I open "Test database name" actions menu
     And I click on "Edit settings" "link" in the "Test database name" activity
     And I fill the moodle form with:
       | Name | Original database name |
index 42fe9a1..36d8be2 100644 (file)
@@ -58,4 +58,43 @@ class behat_blocks extends behat_base {
         return $steps;
     }
 
+    /**
+     * Opens a block's actions menu if it is not already opened.
+     *
+     * @Given /^I open the "(?P<block_name_string>(?:[^"]|\\")*)" blocks action menu$/
+     * @throws DriverException The step is not available when Javascript is disabled
+     * @param string $blockname
+     * @return Given
+     */
+    public function i_open_the_blocks_action_menu($blockname) {
+
+        if (!$this->running_javascript()) {
+            throw new DriverException('Blocks action menu not available when Javascript is disabled');
+        }
+
+        // If it is already opened we do nothing.
+        $blocknode = $this->get_block_node($blockname);
+        $classes = array_flip(explode(' ', $blocknode->getAttribute('class')));
+        if (!empty($classes['action-menu-shown'])) {
+            return;
+        }
+
+        return new Given('I click on "a[role=\'menuitem\']" "css_element" in the "' . $this->escape($blockname) . '" "block"');
+    }
+
+    /**
+     * Returns the DOM node of the block from <div>.
+     *
+     * @throws ElementNotFoundException Thrown by behat_base::find
+     * @param string $blockname The block name
+     * @return NodeElement
+     */
+    protected function get_block_node($blockname) {
+
+        $blockname = $this->getSession()->getSelectorsHandler()->xpathLiteral($blockname);
+        $xpath = "//div[contains(concat(' ', normalize-space(@class), ' '), ' block ')][contains(., $blockname)]";
+
+        return $this->find('xpath', $xpath);
+    }
+
 }
index af2bc33..bc1c316 100644 (file)
@@ -18,7 +18,7 @@ Feature: Add and configure blocks throughout the site
     And I log in as "manager1"
     And I follow "Turn editing on"
     And I add the "Comments" block
-    And I click on "Actions" "link" in the "Comments" "block"
+    And I open the "Comments" blocks action menu
     And I follow "Configure Comments block"
     And I fill the moodle form with:
       | Page contexts | Display throughout the entire site |
@@ -27,7 +27,7 @@ Feature: Add and configure blocks throughout the site
     Then I should see "Comments" in the "Comments" "block"
     And I should see "Save comment" in the "Comments" "block"
     And I am on homepage
-    And I click on "Actions" "link" in the "Comments" "block"
+    And I open the "Comments" blocks action menu
     And I follow "Configure Comments block"
     And I fill the moodle form with:
       | Default weight | -10 (first) |
index 2c3cb7f..dea4dcc 100644 (file)
@@ -42,6 +42,7 @@ Feature: Block appearances
     And I follow "Course 1"
     And I follow "Turn editing on"
     And I add the "Comments" block
+    And I open the "Comments" blocks action menu
     And I follow "Configure Comments block"
     And I fill the moodle form with:
       | Display on page types | Any page |
@@ -52,6 +53,7 @@ Feature: Block appearances
     When I follow "Test survey name"
     Then I should see "Comments" in the "Comments" "block"
     And I follow "Course 1"
+    And I open the "Comments" blocks action menu
     And I follow "Configure Comments block"
     And I fill the moodle form with:
       | Display on page types | Any course page |
@@ -63,6 +65,7 @@ Feature: Block appearances
   @javascript
   Scenario: Block settings can be modified so that a block can be hidden or moved
     When I follow "Test book name"
+    And I open the "Comments" blocks action menu
     And I follow "Configure Comments block"
     And I fill the moodle form with:
       | Visible | No |
@@ -72,6 +75,7 @@ Feature: Block appearances
     Then I should not see "Comments"
     And I expand "Course administration" node
     And I follow "Turn editing on"
+    And I open the "Comments" blocks action menu
     And I follow "Configure Comments block"
     And I fill the moodle form with:
       | Visible | Yes |
index 8605ccc..af9bce2 100644 (file)
@@ -15,7 +15,7 @@ Feature: The context of a block can always be returned to it's original state.
     And I add the "Tags" block
     Then I should see "Tags" in the "Tags" "block"
     And I click on "Participants" "link" in the "//li[p/span[contains(normalize-space(string(.)), 'Current course')]]" "xpath_element"
-    And I click on "Actions" "link" in the "Tags" "block"
+    And I open the "Tags" blocks action menu
     And I follow "Configure Tags block"
     And I fill the moodle form with:
       | Display on page types | Any page |
@@ -25,7 +25,7 @@ Feature: The context of a block can always be returned to it's original state.
       | Assignment name | Assignment1 |
       | Description | Description |
     And I follow "Assignment1"
-    And I click on "Actions" "link" in the "Tags" "block"
+    And I open the "Tags" blocks action menu
     And I follow "Configure Tags block"
     And I fill the moodle form with:
       | Display on page types | Any assignment module page |
@@ -41,7 +41,7 @@ Feature: The context of a block can always be returned to it's original state.
       | Description | Description |
     And I follow "Assignment2"
     And I should see "Tags" in the "Tags" "block"
-    And I click on "Actions" "link" in the "Tags" "block"
+    And I open the "Tags" blocks action menu
     And I follow "Configure Tags block"
     And I fill the moodle form with:
       | Display on page types | Any page |
index 87609ea..5904198 100644 (file)
@@ -559,7 +559,7 @@ class core_course_management_renderer extends plugin_renderer_base {
 
         if ($category->can_resort_courses()) {
             // In order for dnd to be available the user must be able to resort the category children..
-            $html .= html_writer::div($this->output->pix_icon('i/dragdrop', get_string('dndcourse')), 'float-left drag-handle');
+            $html .= html_writer::div($this->output->pix_icon('i/move_2d', get_string('dndcourse')), 'float-left drag-handle');
         }
 
         $html .= html_writer::start_div('ba-checkbox float-left');
index cbca4ca..189581d 100644 (file)
@@ -1995,7 +1995,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
             new moodle_url($baseurl, array('id' => $mod->id, 'indent' => '1')),
             new pix_icon($rightarrow, $str->moveright, 'moodle', array('class' => 'iconsmall', 'title' => '')),
             $str->moveright,
-            array('class' => 'editing_moveright ' . $enabledclass, 'data-action' => 'moveright')
+            array('class' => 'editing_moveright ' . $enabledclass, 'data-action' => 'moveright', 'data-keepopen' => true)
         );
 
         if ($indent <= $indentlimits->min) {
@@ -2007,7 +2007,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
             new moodle_url($baseurl, array('id' => $mod->id, 'indent' => '-1')),
             new pix_icon($leftarrow, $str->moveleft, 'moodle', array('class' => 'iconsmall', 'title' => '')),
             $str->moveleft,
-            array('class' => 'editing_moveleft ' . $enabledclass, 'data-action' => 'moveleft')
+            array('class' => 'editing_moveleft ' . $enabledclass, 'data-action' => 'moveleft', 'data-keepopen' => true)
         );
 
     }
index a428454..21aa0f8 100644 (file)
@@ -102,13 +102,13 @@ if ($modulelist !== '') {
 }
 
 $strmanagement = new lang_string('coursecatmanagement');
-$title = format_string($SITE->fullname, true, array('context' => $systemcontext));
+$pageheading = format_string($SITE->fullname, true, array('context' => $systemcontext));
 
 $PAGE->set_context($context);
 $PAGE->set_url($url);
 $PAGE->set_pagelayout('admin');
-$PAGE->set_title($title);
-$PAGE->set_heading($strmanagement);
+$PAGE->set_title($strmanagement);
+$PAGE->set_heading($pageheading);
 
 // This is a system level page that operates on other contexts.
 require_login();
index d5a93f6..1001212 100644 (file)
@@ -859,7 +859,8 @@ class core_course_renderer extends plugin_renderer_base {
             }
         } else {
             // No link, so display only content.
-            $output = html_writer::tag('div', $accesstext . $content, array('class' => $textclasses));
+            $output = html_writer::tag('div', $accesstext . $content,
+                    array('class' => 'contentwithoutlink ' . $textclasses));
         }
         return $output;
     }
@@ -982,22 +983,33 @@ class core_course_renderer extends plugin_renderer_base {
             $output .= course_get_cm_move($mod, $sectionreturn);
         }
 
-        $output .= html_writer::start_tag('div', array('class' => $indentclasses));
+        $output .= html_writer::start_tag('div', array('class' => 'mod-indent-outer'));
 
-        // Start the div for the activity title, excluding the edit icons.
-        $output .= html_writer::start_tag('div', array('class' => 'activityinstance'));
+        // This div is used to indent the content.
+        $output .= html_writer::div('', $indentclasses);
+
+        // Start a wrapper for the actual content to keep the indentation consistent
+        $output .= html_writer::start_tag('div');
 
         // Display the link to the module (or do nothing if module has no url)
-        $output .= $this->course_section_cm_name($mod, $displayoptions);
-        if ($this->page->user_is_editing()) {
-            $output .= ' ' . course_get_cm_rename_action($mod, $sectionreturn);
-        }
+        $cmname = $this->course_section_cm_name($mod, $displayoptions);
+
+        if (!empty($cmname)) {
+            // Start the div for the activity title, excluding the edit icons.
+            $output .= html_writer::start_tag('div', array('class' => 'activityinstance'));
+            $output .= $cmname;
+
 
-        // Module can put text after the link (e.g. forum unread)
-        $output .= $mod->get_after_link();
+            if ($this->page->user_is_editing()) {
+                $output .= ' ' . course_get_cm_rename_action($mod, $sectionreturn);
+            }
+
+            // Module can put text after the link (e.g. forum unread)
+            $output .= $mod->get_after_link();
 
-        // Closing the tag which contains everything but edit icons. Content part of the module should not be part of this.
-        $output .= html_writer::end_tag('div'); // .activityinstance
+            // Closing the tag which contains everything but edit icons. Content part of the module should not be part of this.
+            $output .= html_writer::end_tag('div'); // .activityinstance
+        }
 
         // If there is content but NO link (eg label), then display the
         // content here (BEFORE any icons). In this case cons must be
@@ -1033,7 +1045,10 @@ class core_course_renderer extends plugin_renderer_base {
         // show availability info (if module is not available)
         $output .= $this->course_section_cm_availability($mod, $displayoptions);
 
-        $output .= html_writer::end_tag('span'); // $indentclasses
+        $output .= html_writer::end_tag('div'); // $indentclasses
+
+        // End of indentation div.
+        $output .= html_writer::end_tag('div');
 
         $output .= html_writer::end_tag('div');
         return $output;
index fdcdb61..9006567 100644 (file)
@@ -27,8 +27,10 @@ Feature: Toggle activities visibility from the course page
     When I open "Test forum name" actions menu
     And I click on "Hide" "link" in the "Test forum name" activity
     Then "Test forum name" activity should be hidden
+    And I open "Test forum name" actions menu
     And I click on "Show" "link" in the "Test forum name" activity
     And "Test forum name" activity should be visible
+    And I open "Test forum name" actions menu
     And I click on "Hide" "link" in the "Test forum name" activity
     And "Test forum name" activity should be hidden
     And I reload the page
index e165d86..7d8a9dd 100644 (file)
@@ -1,9 +1,9 @@
 YUI.add('moodle-course-dragdrop', function(Y) {
 
     var CSS = {
+        ACTIONAREA: '.actions',
         ACTIVITY : 'activity',
         ACTIVITYINSTANCE : 'activityinstance',
-        COMMANDSPAN : '.commands',
         CONTENT : 'content',
         COURSECONTENT : 'course-content',
         EDITINGMOVE : 'editing_move',
@@ -375,8 +375,8 @@ YUI.add('moodle-course-dragdrop', function(Y) {
             var dropnode = e.drop.get('node');
 
             // Add spinner if it not there
-            var activityinstance = dragnode.one('.' + CSS.ACTIVITYINSTANCE);
-            var spinner = M.util.add_spinner(Y, activityinstance);
+            var actionarea = dragnode.one(CSS.ACTIONAREA);
+            var spinner = M.util.add_spinner(Y, actionarea);
 
             var params = {};
 
index de021b3..c4f004b 100644 (file)
@@ -9,6 +9,7 @@ YUI.add('moodle-course-toolboxes', function(Y) {
     var CSS = {
         ACTIVITYINSTANCE : 'activityinstance',
         AVAILABILITYINFODIV : 'div.availabilityinfo',
+        CONTENTWITHOUTLINK : 'contentwithoutlink',
         CONDITIONALHIDDEN : 'conditionalhidden',
         DIMCLASS : 'dimmed',
         DIMMEDTEXT : 'dimmed_text',
@@ -25,6 +26,7 @@ YUI.add('moodle-course-toolboxes', function(Y) {
     },
     // The CSS selectors we use.
     SELECTOR = {
+        ACTIONAREA: '.actions',
         ACTIONLINKTEXT : '.actionlinktext',
         ACTIVITYACTION : 'a.cm-edit-action[data-action], a.editing_title',
         ACTIVITYFORM : '.' + CSS.ACTIVITYINSTANCE + ' form',
@@ -35,11 +37,13 @@ YUI.add('moodle-course-toolboxes', function(Y) {
         ACTIVITYTITLE : 'input[name=title]',
         COMMANDSPAN : '.commands',
         CONTENTAFTERLINK : 'div.contentafterlink',
+        CONTENTWITHOUTLINK : 'div.contentwithoutlink',
         EDITTITLE: 'a.editing_title',
         HIDE : 'a.editing_hide',
         HIGHLIGHT : 'a.editing_highlight',
         INSTANCENAME : 'span.instancename',
         MODINDENTDIV : '.mod-indent',
+        MODINDENTOUTER : '.mod-indent-outer',
         PAGECONTENT : 'div#page-content',
         SECTIONLI : 'li.section',
         SHOW : 'a.'+CSS.SHOW,
@@ -291,13 +295,8 @@ YUI.add('moodle-course-toolboxes', function(Y) {
             }
         },
         add_spinner: function(activity) {
-            var instance = activity.one(SELECTOR.ACTIVITYINSTANCE);
-
-            if (instance) {
-                return M.util.add_spinner(Y, instance);
-            } else {
-                return M.util.add_spinner(Y, activity);
-            }
+            var actionarea = activity.one(SELECTOR.ACTIONAREA);
+            return M.util.add_spinner(Y, actionarea);
         },
 
         /**
@@ -506,7 +505,7 @@ YUI.add('moodle-course-toolboxes', function(Y) {
          */
         handle_resource_dim : function(button, activity, action) {
             var toggleclass = CSS.DIMCLASS,
-                dimarea = activity.one('a'),
+                dimarea = activity.one('a, .contentwithoutlink'),
                 availabilityinfo = activity.one(CSS.AVAILABILITYINFODIV),
                 nextaction = (action === 'hide') ? 'show' : 'hide',
                 buttontext = button.one('span'),
@@ -524,11 +523,12 @@ YUI.add('moodle-course-toolboxes', function(Y) {
                 buttontext.set('text', newstring);
             }
 
-            // If activity is conditionally hidden, then don't toggle.
-            if (Y.Moodle.core_course.util.cm.getName(activity) === null) {
+            if (activity.one(SELECTOR.CONTENTWITHOUTLINK)) {
+                dimarea = activity.one(SELECTOR.CONTENTWITHOUTLINK);
                 toggleclass = CSS.DIMMEDTEXT;
-                dimarea = activity.all(SELECTOR.MODINDENTDIV + ' > div').item(1);
             }
+
+            // If activity is conditionally hidden, then don't toggle.
             if (!dimarea.hasClass(CSS.CONDITIONALHIDDEN)) {
                 // Change the UI.
                 dimarea.toggleClass(toggleclass);
@@ -618,6 +618,7 @@ YUI.add('moodle-course-toolboxes', function(Y) {
             // Get the element we're working on
             var activityid = Y.Moodle.core_course.util.cm.getId(activity),
                 instancename  = activity.one(SELECTOR.INSTANCENAME),
+                instance = activity.one(SELECTOR.ACTIVITYINSTANCE),
                 currenttitle = instancename.get('firstChild'),
                 oldtitle = currenttitle.get('data'),
                 titletext = oldtitle,
@@ -657,18 +658,14 @@ YUI.add('moodle-course-toolboxes', function(Y) {
                 editform.appendChild(activity.one(SELECTOR.ACTIVITYICON).cloneNode());
                 editform.appendChild(editor);
                 editform.setData('anchor', anchor);
+                instance.insert(editinstructions, 'before');
                 anchor.replace(editform);
-                activity.one('div').appendChild(editinstructions);
 
                 // Force the editing instruction to match the mod-indent position.
                 var padside = 'left';
                 if (right_to_left()) {
                     padside = 'right';
                 }
-                var mi = activity.one('.mod-indent'),
-                    instructionpad = parseInt(mi.getStyle('padding-' + padside), 10) +
-                            parseInt(mi.getStyle('margin-' + padside), 10);
-                editinstructions.setStyle('margin-' + padside, instructionpad + 'px');
 
                 // We hide various components whilst editing:
                 activity.addClass(CSS.EDITINGTITLE);
index 1d06ba4..14d1fcc 100644 (file)
@@ -168,15 +168,12 @@ $string['configcronremotepassword'] = 'This means that the cron.php script canno
 $string['configcurlcache'] = 'Time-to-live for cURL cache, in seconds.';
 $string['configcustommenuitems'] = 'You can configure a custom menu here to be shown by themes. Each line consists of some menu text, a link URL (optional), a tooltip title (optional) and a language code or comma-separated list of codes (optional, for displaying the line to users of the specified language only), separated by pipe characters. You can specify a structure using hyphens. For example:
 <pre>
-Moodle community|http://moodle.org
--Moodle free support|http://moodle.org/support
--Moodle development|http://moodle.org/development
---Moodle Tracker|http://tracker.moodle.org
---Moodle Docs|http://docs.moodle.org|Moodle Docs in German
+Moodle community|https://moodle.org
+-Moodle free support|https://moodle.org/support
+-Moodle development|https://moodle.org/development
+--Moodle Docs|http://docs.moodle.org|Moodle Docs
 --German Moodle Docs|http://docs.moodle.org/de|Documentation in German|de
--Moodle News|http://moodle.org/news Moodle company
--Moodle commercial hosting|http://moodle.com/hosting
--Moodle commercial support|http://moodle.com/support
+Moodle.com|http://moodle.com/
 </pre>';
 $string['configdbsessions'] = 'If enabled, this setting will use the database to store information about current sessions.  This is especially useful for large/busy sites or sites built on cluster of servers.  For most sites this should probably be left disabled so that the server disk is used instead.  Note that changing this setting now will log out all current users (including you). If you are using MySQL please make sure that \'max_allowed_packet\' in my.cnf (or my.ini) is at least 4M.';
 $string['configdebug'] = 'If you turn this on, then PHP\'s error_reporting will be increased so that more warnings are printed.  This is only useful for developers.';
@@ -491,6 +488,7 @@ $string['enablesafebrowserintegration'] = 'Enable Safe Exam Browser integration'
 $string['enablestats'] = 'Enable statistics';
 $string['enabletgzbackups'] = 'Enable new backup format';
 $string['enabletgzbackups_desc'] = 'If enabled, future backups will be created in a new compression format for .mbz files (internally stored as a .tar.gz file). This removes the 4GB backup size restriction and may improve performance. Restore supports both formats and the difference should be transparent to users.';
+$string['enabletgzbackups_nozlib'] = 'PHP extension &lsquo;zlib&rsquo; is not available. The new backup format relies on this extension and will be disabled until zlib is installed and enabled.';
 $string['enabletrusttext'] = 'Enable trusted content';
 $string['enablewebservices'] = 'Enable web services';
 $string['enablewsdocumentation'] = 'Web services documentation';
@@ -537,7 +535,7 @@ $string['forcelogin'] = 'Force users to log in';
 $string['forceloginforprofileimage'] = 'Force users to log in to view user pictures';
 $string['forceloginforprofileimage_help'] = 'If enabled, users must login in order to view user profile pictures and the default user picture will be used in all notification emails.';
 $string['forceloginforprofiles'] = 'Force users to log in for profiles';
-$string['forcetimezone'] = 'Force default timezone';
+$string['forcetimezone'] = 'Force timezone';
 $string['formatuninstallwithcourses'] = 'There are {$a->count} courses using {$a->format}. Their format will be changed to {$a->defaultformat} (default format for this site). Some format-specific data may be lost. Are you sure you want to proceed?';
 $string['frontpage'] = 'Front page';
 $string['frontpagebackup'] = 'Front page backup';
@@ -731,7 +729,7 @@ $string['mobile'] = 'Mobile';
 $string['mobilecssurl'] = 'CSS';
 $string['modchooserdefault'] = 'Activity chooser default';
 $string['modeditdefaults'] = 'Default values for activity settings';
-$string['modeditingmenu'] = 'Activitiy editing menus';
+$string['modeditingmenu'] = 'Activity editing menus';
 $string['modeditingmenu_desc'] = 'If enabled many of the activity editing icons shown when viewing a course with editing on will be displayed within a drop-down menu. This reduces the content on screen when editing a course by hiding the icons until they are needed.';
 $string['modsettings'] = 'Manage activities';
 $string['modulesecurity'] = 'Module security';
@@ -1130,6 +1128,7 @@ $string['webproxyinfo'] = 'Fill in following options if your Moodle server can n
 $string['xmlrpcrecommended'] = 'The xmlrpc extension is needed for hub communication, and useful for web services and Moodle networking';
 $string['yuicomboloading'] = 'YUI combo loading';
 $string['ziprequired'] = 'The Zip PHP extension is now required by Moodle, info-ZIP binaries or PclZip library are not used anymore.';
+$string['zlibenabled'] = 'zlib enabled';
 
 
 $string['caching'] = 'Caching';
index 18a34ff..fbc4bc3 100644 (file)
@@ -117,6 +117,7 @@ $string['errorminbackup20version'] = 'This backup file has been created with one
 $string['errorrestorefrontpage'] = 'Restoring over front page is not allowed.';
 $string['errorinvalidformat'] = 'Unknown backup format';
 $string['errorinvalidformatinfo'] = 'The selected file is not a valid Moodle backup file and can\'t be restored.';
+$string['errortgznozlib'] = 'The selected file is in the new backup format and cannot be restored because the zlib PHP extension is not available on this system.';
 $string['executionsuccess'] = 'The backup file was successfully created.';
 $string['filename'] = 'Filename';
 $string['filealiasesrestorefailures'] = 'Aliases restore failures';
index 3065685..23ceb4e 100644 (file)
@@ -367,16 +367,16 @@ Once a badge has been issued to at least one user, it automatically becomes **LO
 We want to make sure that all users complete the same requirements to earn a badge. Currently, it is not possible to revoke badges. If we allowed badges requirements to be modified all the time, we would most likely end up with users having the same badge for meeting completely different requirements.';
 $string['subject'] = 'Message subject';
 $string['variablesubstitution'] = 'Variable substitution in messages.';
-$string['variablesubstitution_help'] = 'In a badge message, certain variables can be inserted into the subject and/or body of a message so that they will be replaced with real values when the message is sent. The variables should be inserted into the the text exactly as they are shown below. The following variables can be used:
+$string['variablesubstitution_help'] = 'In a badge message, certain variables can be inserted into the subject and/or body of a message so that they will be replaced with real values when the message is sent. The variables should be inserted into the text exactly as they are shown below. The following variables can be used:
 
 %badgename%
-:   This will be replaced by the badge\'s full name.
+: This will be replaced by the badge\'s full name.
 
 %username%
-:   This will be replaced by the recipient\'s full name.
+: This will be replaced by the recipient\'s full name.
 
 %badgelink%
-:   This will be replaced by the public URL with information about the issued badge.';
+: This will be replaced by the public URL with information about the issued badge.';
 $string['viewbadge'] = 'View issued badge';
 $string['visible'] = 'Visible';
 $string['warnexpired'] = ' (This badge has expired!)';
index b259c16..feb6833 100644 (file)
@@ -23,7 +23,7 @@
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-$string['addfields'] = 'Add {$a} fields to form';
+$string['addfields'] = 'Add {$a} field(s) to form';
 $string['advancedelement'] = 'Advanced element';
 $string['close'] = 'Close';
 $string['day'] = 'Day';
index 60f2cd8..27b569d 100644 (file)
@@ -339,7 +339,7 @@ Alternatively, you may wish for students to submit each question as they go alon
 Those are probably the two most commonly used modes of behaviour. ';
 $string['importfromcoursefiles'] = '... or choose a course file to import.';
 $string['importfromupload'] = 'Select a file to upload ...';
-$string['includesubcategories'] = 'Also show questions from sub-categories';
+$string['includesubcategories'] = 'Also show questions from subcategories';
 $string['incorrect'] = 'Incorrect';
 $string['incorrectfeedback'] = 'For any incorrect response';
 $string['incorrectfeedbackdefault'] = 'Your answer is incorrect.';
@@ -367,7 +367,7 @@ $string['partiallycorrect'] = 'Partially correct';
 $string['partiallycorrectfeedback'] = 'For any partially correct response';
 $string['partiallycorrectfeedbackdefault'] = 'Your answer is partially correct.';
 $string['penaltyforeachincorrecttry'] = 'Penalty for each incorrect try';
-$string['penaltyforeachincorrecttry_help'] = 'When you run your questions using the \'Interactive with multiple tries\' or \'Adaptive mode\' behaviour, so that the the student will have several tries to get the question right, then this option controls how much they are penalised for each incorrect try.
+$string['penaltyforeachincorrecttry_help'] = 'When questions are run using the \'Interactive with multiple tries\' or \'Adaptive mode\' behaviour, so that the student will have several tries to get the question right, then this option controls how much they are penalised for each incorrect try.
 
 The penalty is a proportion of the total question grade, so if the question is worth three marks, and the penalty is 0.3333333, then the student will score 3 if they get the question right first time, 2 if they get it right second try, and 1 of they get it right on the third try.';
 $string['previewquestion'] = 'Preview question: {$a}';
index 974124f..79e62c1 100644 (file)
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * Box REST Client Library for PHP5 Developers
+ * Box.net client.
  *
- *
- * @package moodlecore
+ * @package core
  * @author James Levy <james@box.net>
  * @link http://enabled.box.net
  * @access public
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+defined('MOODLE_INTERNAL') || die();
+require_once($CFG->libdir . '/oauthlib.php');
+
+/**
+ * Box.net client class.
+ *
+ * @package    core
+ * @copyright  2013 Frédéric Massart
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class boxnet_client extends oauth2_client {
+
+    /** @const API URL */
+    const API = 'https://api.box.com/2.0';
+
+    /** @const UPLOAD_API URL */
+    const UPLOAD_API = 'https://upload.box.com/api/2.0';
+
+    /**
+     * Return authorize URL.
+     *
+     * @return string
+     */
+    protected function auth_url() {
+        return 'https://www.box.com/api/oauth2/authorize';
+    }
+
+    /**
+     * Create a folder.
+     *
+     * @param string $foldername The folder name.
+     * @param int $parentid The ID of the parent folder.
+     * @return array Information about the new folder.
+     */
+    public function create_folder($foldername, $parentid = 0) {
+        $params = array('name' => $foldername, 'parent' => array('id' => (string) $parentid));
+        $this->reset_state();
+        $result = $this->post($this->make_url("/folders"), json_encode($params));
+        $result = json_decode($result);
+        return $result;
+    }
+
+    /**
+     * Download the file.
+     *
+     * @param int $fileid File ID.
+     * @param string $path Path to download the file to.
+     * @return bool Success or not.
+     */
+    public function download_file($fileid, $path) {
+        $this->reset_state();
+        $result = $this->download_one($this->make_url("/files/$fileid/content"), array(),
+            array('filepath' => $path, 'CURLOPT_FOLLOWLOCATION' => true));
+        return ($result === true && $this->info['http_code'] === 200);
+    }
+
+    /**
+     * Get info of a file.
+     *
+     * @param int $fileid File ID.
+     * @return object
+     */
+    public function get_file_info($fileid) {
+        $this->reset_state();
+        $result = $this->request($this->make_url("/files/$fileid"));
+        return json_decode($result);
+    }
+
+    /**
+     * Get a folder content.
+     *
+     * @param int $folderid Folder ID.
+     * @return object
+     */
+    public function get_folder_items($folderid = 0) {
+        $this->reset_state();
+        $result = $this->request($this->make_url("/folders/$folderid/items",
+            array('fields' => 'id,name,type,modified_at,size,owned_by')));
+        return json_decode($result);
+    }
+
+    /**
+     * Log out.
+     *
+     * @return void
+     */
+    public function log_out() {
+        if ($accesstoken = $this->get_accesstoken()) {
+            $params = array(
+                'client_id' => $this->get_clientid(),
+                'client_secret' => $this->get_clientsecret(),
+                'token' => $accesstoken->token
+            );
+            $this->reset_state();
+            $this->post($this->revoke_url(), $params);
+        }
+        parent::log_out();
+    }
+
+    /**
+     * Build a request URL.
+     *
+     * @param string $uri The URI to request.
+     * @param array $params Query string parameters.
+     * @param bool $uploadapi Whether this works with the upload API or not.
+     * @return string
+     */
+    protected function make_url($uri, $params = array(), $uploadapi = false) {
+        $api = $uploadapi ? self::UPLOAD_API : self::API;
+        $url = new moodle_url($api . '/' . ltrim($uri, '/'), $params);
+        return $url->out(false);
+    }
+
+    /**
+     * Rename a file.
+     *
+     * @param int $fileid The file ID.
+     * @param string $newname The new file name.
+     * @return object Box.net file object.
+     */
+    public function rename_file($fileid, $newname) {
+        // This requires a PUT request with data within it. We cannot use
+        // the standard PUT request 'CURLOPT_PUT' because it expects a file.
+        $data = array('name' => $newname);
+        $options = array(
+            'CURLOPT_CUSTOMREQUEST' => 'PUT',
+            'CURLOPT_POSTFIELDS' => json_encode($data)
+        );
+        $url = $this->make_url("/files/$fileid");
+        $this->reset_state();
+        $result = $this->request($url, $options);
+        $result = json_decode($result);
+        return $result;
+    }
+
+    /**
+     * Resets curl for multiple requests.
+     *
+     * @return void
+     */
+    public function reset_state() {
+        $this->cleanopt();
+        $this->resetHeader();
+    }
+
+    /**
+     * Return the revoke URL.
+     *
+     * @return string
+     */
+    protected function revoke_url() {
+        return 'https://www.box.com/api/oauth2/revoke';
+    }
+
+    /**
+     * Share a file and return the link to it.
+     *
+     * @param string $fileid The file ID.
+     * @param bool $businesscheck Whether or not to check if the user can share files, has a business account.
+     * @return object
+     */
+    public function share_file($fileid, $businesscheck = true) {
+        // Sharing the file, this requires a PUT request with data within it. We cannot use
+        // the standard PUT request 'CURLOPT_PUT' because it expects a file.
+        $data = array('shared_link' => array('access' => 'open', 'permissions' =>
+            array('can_download' => true, 'can_preview' => true)));
+        $options = array(
+            'CURLOPT_CUSTOMREQUEST' => 'PUT',
+            'CURLOPT_POSTFIELDS' => json_encode($data)
+        );
+        $this->reset_state();
+        $result = $this->request($this->make_url("/files/$fileid"), $options);
+        $result = json_decode($result);
+
+        if ($businesscheck) {
+            // Checks that the user has the right to share the file. If not, throw an exception.
+            $this->reset_state();
+            $this->head($result->shared_link->download_url);
+            $info = $this->get_info();
+            if ($info['http_code'] == 403) {
+                throw new moodle_exception('No permission to share the file');
+            }
+        }
+
+        return $result->shared_link;
+    }
+
+    /**
+     * Search.
+     *
+     * @return object
+     */
+    public function search($query) {
+        $this->reset_state();
+        $result = $this->request($this->make_url('/search', array('query' => $query, 'limit' => 50, 'offset' => 0)));
+        return json_decode($result);
+    }
+
+    /**
+     * Return token URL.
+     *
+     * @return string
+     */
+    protected function token_url() {
+        return 'https://www.box.com/api/oauth2/token';
+    }
+
+    /**
+     * Upload a file.
+     *
+     * Please note that the file is named on Box.net using the path we are providing, and so
+     * the file has the name of the stored_file hash.
+     *
+     * @param stored_file $storedfile A stored_file.
+     * @param integer $parentid The ID of the parent folder.
+     * @return object Box.net file object.
+     */
+    public function upload_file(stored_file $storedfile, $parentid = 0) {
+        $url = $this->make_url('/files/content', array(), true);
+        $options = array(
+            'filename' => $storedfile,
+            'parent_id' => $parentid
+        );
+        $this->reset_state();
+        $result = $this->post($url, $options);
+        $result = json_decode($result);
+        return $result;
+    }
+
+}
+
 /**
- * @package moodlecore
+ * Box REST Client Library for PHP5 Developers.
+ *
+ * Deprecation note: As of the 14th of December 2013 Box.net APIv1, used by this class,
+ * is reaching its end of life. Please use boxnet_client() instead.
+ *
+ * @package core
+ * @author James Levy <james@box.net>
+ * @link http://enabled.box.net
+ * @access public
+ * @version 1.0
  * @copyright copyright Box.net 2007
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @deprecated since 2.6, 2.5.3, 2.4.7
  */
 class boxclient {
     /** @var string */
index fa1931c..7f5f216 100644 (file)
@@ -83,19 +83,26 @@ class core_collator {
                     if ($errorcode !== 0) {
                         // Get the actual locale being used, e.g. en, he, zh
                         $localeinuse = $collator->getLocale(Locale::ACTUAL_LOCALE);
-                        // Check for the common fallback warning error codes. If this occurred
-                        // there is normally little to worry about:
-                        // - U_USING_DEFAULT_WARNING (127)  - default fallback locale used (pt => UCA)
-                        // - U_USING_FALLBACK_WARNING (128) - fallback locale used (de_CH => de)
-                        // (UCA: Unicode Collation Algorithm http://unicode.org/reports/tr10/)
+                        // Check for the common fallback warning error codes. If any of the two
+                        // following errors occurred, there is normally little to worry about:
+                        // * U_USING_FALLBACK_WARNING (-128) indicates that a fall back locale was
+                        //   used. For example, 'de_CH' was requested, but nothing was found
+                        //   there, so 'de' was used.
+                        // * U_USING_DEFAULT_WARNING (-127) indicates that the default locale
+                        //   data was used; neither the requested locale nor any of its fall
+                        //   back locales could be found. For example, 'pt' was requested, but
+                        //   UCA was used (Unicode Collation Algorithm http://unicode.org/reports/tr10/).
+                        // See http://www.icu-project.org/apiref/icu4c/classicu_1_1ResourceBundle.html
                         if ($errorcode === -127 || $errorcode === -128) {
                             // Check if the locale in use is UCA default one ('root') or
                             // if it is anything like the locale we asked for
                             if ($localeinuse !== 'root' && strpos($locale, $localeinuse) !== 0) {
                                 // The locale we asked for is completely different to the locale
                                 // we have received, let the user know via debugging
-                                debugging('Invalid locale: "' . $locale . '", with warning (not fatal) "' . $errormessage .
-                                '", falling back to "' . $collator->getLocale(Locale::VALID_LOCALE) . '"');
+                                debugging('Locale warning (not fatal) '.$errormessage.': '.
+                                    'Requested locale "'.$locale.'" not found, locale "'.$localeinuse.'" used instead. '.
+                                    'The most specific locale supported by ICU relatively to the requested locale is "'.
+                                    $collator->getLocale(Locale::VALID_LOCALE).'".');
                             } else {
                                 // Nothing to do here, this is expected!
                                 // The Moodle locale setting isn't what the collator expected but
@@ -105,8 +112,10 @@ class core_collator {
                         } else {
                             // We've received some other sort of non fatal warning - let the
                             // user know about it via debugging.
-                            debugging('Problem with locale: "' . $locale . '", with message "' . $errormessage .
-                            '", falling back to "' . $collator->getLocale(Locale::VALID_LOCALE) . '"');
+                            debugging('Problem with locale: '.$errormessage.'. '.
+                                'Requested locale: "'.$locale.'", actual locale "'.$localeinuse.'". '.
+                                'The most specific locale supported by ICU relatively to the requested locale is "'.
+                                $collator->getLocale(Locale::VALID_LOCALE).'".');
                         }
                     }
                     // Store the collator object now that we can be sure it is in a workable condition
index b5ca099..40bd6b3 100644 (file)
@@ -904,6 +904,7 @@ class core_plugin_manager {
             'qformat' => array('blackboard'),
             'enrol' => array('authorize'),
             'tool' => array('bloglevelupgrade'),
+            'theme' => array('mymobile'),
         );
 
         if (!isset($plugins[$type])) {
index 2f14254..3fb7f92 100644 (file)
@@ -2780,14 +2780,29 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2013102500.01);
     }
 
-    if ($oldversion < 2013110400.00) {
+    if ($oldversion < 2013110500.01) {
+        // MDL-38228. Corrected course_modules upgrade script instead of 2013021801.01.
+
+        // This upgrade script fixes the mismatches between DB fields course_modules.section
+        // and course_sections.sequence. It makes sure that each module is included
+        // in the sequence of at least one section.
+        // There is also a separate script for admins: admin/cli/fix_course_sortorder.php
+
+        // This script in included in each major version upgrade process so make sure we don't run it twice.
+        if (empty($CFG->movingmoduleupgradescriptwasrun)) {
+            upgrade_course_modules_sequences();
+
+            // To skip running the same script on the upgrade to the next major release.
+            set_config('movingmoduleupgradescriptwasrun', 1);
+        }
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2013110500.01);
+    }
 
-        if (!check_dir_exists($CFG->dirroot . '/theme/mymobile', false)) {
-            // Delete from config_plugins.
-            $DB->delete_records('config_plugins', array('plugin' => 'theme_mymobile'));
-            // Delete the config logs.
-            $DB->delete_records('config_log', array('plugin' => 'theme_mymobile'));
+    if ($oldversion < 2013110600.01) {
 
+        if (!file_exists($CFG->dirroot . '/theme/mymobile')) {
             // Replace the mymobile settings.
             $DB->set_field('course', 'theme', 'clean', array('theme' => 'mymobile'));
             $DB->set_field('course_categories', 'theme', 'clean', array('theme' => 'mymobile'));
@@ -2795,42 +2810,25 @@ function xmldb_main_upgrade($oldversion) {
             $DB->set_field('mnet_host', 'theme', 'clean', array('theme' => 'mymobile'));
 
             // Replace the theme configs.
-            if (get_config('core', 'theme') == 'mymobile') {
+            if (get_config('core', 'theme') === 'mymobile') {
                 set_config('theme', 'clean');
             }
-            if (get_config('core', 'thememobile') == 'mymobile') {
+            if (get_config('core', 'thememobile') === 'mymobile') {
                 set_config('thememobile', 'clean');
             }
-            if (get_config('core', 'themelegacy') == 'mymobile') {
+            if (get_config('core', 'themelegacy') === 'mymobile') {
                 set_config('themelegacy', 'clean');
             }
-            if (get_config('core', 'themetablet') == 'mymobile') {
+            if (get_config('core', 'themetablet') === 'mymobile') {
                 set_config('themetablet', 'clean');
             }
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2013110400.00);
-    }
-
-    if ($oldversion < 2013110500.01) {
-        // MDL-38228. Corrected course_modules upgrade script instead of 2013021801.01.
 
-        // This upgrade script fixes the mismatches between DB fields course_modules.section
-        // and course_sections.sequence. It makes sure that each module is included
-        // in the sequence of at least one section.
-        // There is also a separate script for admins: admin/cli/fix_course_sortorder.php
-
-        // This script in included in each major version upgrade process so make sure we don't run it twice.
-        if (empty($CFG->movingmoduleupgradescriptwasrun)) {
-            upgrade_course_modules_sequences();
-
-            // To skip running the same script on the upgrade to the next major release.
-            set_config('movingmoduleupgradescriptwasrun', 1);
+            // Hacky emulation of plugin uninstallation.
+            unset_all_config_for_plugin('theme_mymobile');
         }
 
         // Main savepoint reached.
-        upgrade_main_savepoint(true, 2013110500.01);
+        upgrade_main_savepoint(true, 2013110600.01);
     }
 
     return true;
index 07a4a3f..c712880 100644 (file)
@@ -698,6 +698,16 @@ class core_ddl_testcase extends database_driver_testcase {
         $this->assertSame('N', $columns['onenumber']->meta_type);
         $this->assertEquals(2.550, $DB->get_field('test_table1', 'onenumber', array(), IGNORE_MULTIPLE)); // Check default has been applied.
 
+        // Add one numeric field with scale of 0 and check it.
+        $field = new xmldb_field('onenumberwith0scale');
+        $field->set_attributes(XMLDB_TYPE_NUMBER, '6,0', null, XMLDB_NOTNULL, null, 2);
+        $dbman->add_field($table, $field);
+        $this->assertTrue($dbman->field_exists($table, 'onenumberwith0scale'));
+        $columns = $DB->get_columns('test_table1');
+        $this->assertEquals(6, $columns['onenumberwith0scale']->max_length);
+        // We can not use assertEquals as that accepts null/false as a valid value.
+        $this->assertSame('0', strval($columns['onenumberwith0scale']->scale));
+
         // Add one float field and check it (not official type - must work as number).
         $field = new xmldb_field('onefloat');
         $field->set_attributes(XMLDB_TYPE_FLOAT, '6,3', null, XMLDB_NOTNULL, null, 3.550);
index 2ad78aa..ec4e983 100644 (file)
@@ -475,7 +475,7 @@ class mssql_native_moodle_database extends moodle_database {
             }
 
             // Scale
-            $info->scale = $rawcolumn->scale ? $rawcolumn->scale : false;
+            $info->scale = $rawcolumn->scale;
 
             // Prepare not_null info
             $info->not_null = $rawcolumn->is_nullable == 'NO'  ? true : false;
index 95985f9..502a266 100644 (file)
@@ -565,7 +565,7 @@ class oci_native_moodle_database extends moodle_database {
                         $info->meta_type     = 'I';
                         $info->unique        = null;
                     }
-                    $info->scale = null;
+                    $info->scale = 0;
 
                 } else {
                     //float
index 7147da3..bc7bd99 100644 (file)
@@ -135,5 +135,25 @@ fontselect,fontsizeselect,wrap,code,search,replace,|,cleanup,removeformat,pastet
         upgrade_plugin_savepoint(true, 2013102900, 'editor', 'tinymce');
     }
 
+    if ($oldversion < 2013110600) {
+        // Reset redesigned editor toolbar setting.
+        $currentorder = get_config('editor_tinymce', 'customtoolbar');
+        $olddefaultorder = "wrap,formatselect,wrap,bold,italic,wrap,bullist,numlist,wrap,link,unlink,wrap,image
+
+undo,redo,wrap,underline,strikethrough,sub,sup,wrap,justifyleft,justifycenter,justifyright,wrap,outdent,indent,wrap,forecolor,backcolor,wrap,ltr,rtl,wrap,nonbreaking,charmap,table
+
+fontselect,fontsizeselect,wrap,code,search,replace,wrap,cleanup,removeformat,pastetext,pasteword,wrap,fullscreen";
+        $neworder = "wrap,formatselect,wrap,bold,italic,wrap,bullist,numlist,wrap,link,unlink,wrap,image
+
+undo,redo,wrap,underline,strikethrough,sub,sup,wrap,justifyleft,justifycenter,justifyright,wrap,outdent,indent,wrap,forecolor,backcolor,wrap,ltr,rtl
+
+fontselect,fontsizeselect,wrap,code,search,replace,wrap,nonbreaking,charmap,table,wrap,cleanup,removeformat,pastetext,pasteword,wrap,fullscreen";
+        if ($currentorder == $olddefaultorder) {
+            set_config('customtoolbar', $neworder, 'editor_tinymce');
+        }
+
+        upgrade_plugin_savepoint(true, 2013110600, 'editor', 'tinymce');
+    }
+
     return true;
 }
index b8ca304..b086d40 100644 (file)
@@ -33,9 +33,9 @@ if ($ADMIN->fulltree) {
     $settings->add(new admin_setting_heading('tinymcegeneralheader', new lang_string('settings'), ''));
     $default = "wrap,formatselect,wrap,bold,italic,wrap,bullist,numlist,wrap,link,unlink,wrap,image
 
-undo,redo,wrap,underline,strikethrough,sub,sup,wrap,justifyleft,justifycenter,justifyright,wrap,outdent,indent,wrap,forecolor,backcolor,wrap,ltr,rtl,wrap,nonbreaking,charmap,table
+undo,redo,wrap,underline,strikethrough,sub,sup,wrap,justifyleft,justifycenter,justifyright,wrap,outdent,indent,wrap,forecolor,backcolor,wrap,ltr,rtl
 
-fontselect,fontsizeselect,wrap,code,search,replace,wrap,cleanup,removeformat,pastetext,pasteword,wrap,fullscreen";
+fontselect,fontsizeselect,wrap,code,search,replace,wrap,nonbreaking,charmap,table,wrap,cleanup,removeformat,pastetext,pasteword,wrap,fullscreen";
     $settings->add(new admin_setting_configtextarea('editor_tinymce/customtoolbar',
         get_string('customtoolbar', 'editor_tinymce'), get_string('customtoolbar_desc', 'editor_tinymce', 'http://www.tinymce.com/wiki.php/TinyMCE3x:Buttons/controls'), $default, PARAM_RAW, 100, 8));
     $settings->add(new admin_setting_configtextarea('editor_tinymce/fontselectlist',
index 86703ef..44f3a92 100644 (file)
@@ -6,7 +6,7 @@
     .moodleSkin .mceLayout .mceToolbar .mceWrap {
         clear: left;
         width: 100%;
-        height: 8px;
+        height: 4px;
     }
     .moodleSkin .mceLayout .mceToolbar .mceNoWrap {
         clear: none;
index 63a7ac1..7be7506 100644 (file)
Binary files a/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/button_bg.png and b/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/button_bg.png differ
index c528a6c..f7e0741 100644 (file)
@@ -6,12 +6,13 @@
 /* New Theme */
 .moodleSkin table {background:transparent; border-spacing: 0; }
 .moodleSkin iframe {display:block;}
-.moodleSkin .mceToolbar {min-height:30px; margin: 9px;}
+.moodleSkin .mceToolbar {min-height:30px; margin: 4px;}
 .moodleSkin .mceToolbar td + td { background: #fff; border: 1px solid #CCCCCC; border-right: none; border-bottom: 1px solid #b3b3b3; }
 .moodleSkin .mceToolbar td + td:empty { display: none;}
-.moodleSkin .mceToolbar a.mceButton { display:block; height: 30px; width: 40px; margin: 0; padding: 0; }
-.moodleSkin .mceToolbar a span.mceIcon { height: 30px; width: 40px; margin: 0; }
-.moodleSkin .mceToolbar a span.mceIcon img { padding: 7px 13px; }
+.dir-rtl .moodleSkin .mceToolbar select,
+.moodleSkin .mceToolbar a.mceButton { display:block; height: 30px; width: 30px; margin: 0; padding: 0; }
+.moodleSkin .mceToolbar a span.mceIcon { height: 30px; width: 30px; margin: 0; }
+.moodleSkin .mceToolbar a span.mceIcon img { padding: 7px; }
 .moodleSkin .mceToolbar .mceGroupStart + td,
 .moodleSkin .mceToolbar .mceToolbarStart + td,
 .moodleSkin .mceToolbar .mceGroupStart + td a,
 .moodleSkin .mceToolbar .mceToolbarStart + td.mceGroupEnd,
 .moodleSkin .mceToolbar .mceToolbarStart + td.mceGroupEnd a { border-radius: 4px; }
 .moodleSkin .mceToolbar .mceLast { border: none; }
-.moodleSkin .mceToolbar .mceGroupStart { border: none; width: 9px; background: transparent;}
-.moodleSkin .mceToolbar .mceGroupEnd { border-right: 1px solid #CCCCCC; border-radius: 0 4px 4px 0; border-left: 1px solid #CCCCCC; margin-right: 9px; }
+.moodleSkin .mceToolbar .mceGroupStart { border: none; width: 4px; background: transparent;}
+.moodleSkin .mceToolbar .mceGroupEnd { border-right: 1px solid #CCCCCC; border-radius: 0 4px 4px 0; border-left: 1px solid #CCCCCC; margin-right: 4px; }
 .moodleSkin .mceToolbar .mceGroupEnd a { border-radius: 0 4px 4px 0; }
 .moodleSkin .mceToolbar td div .mceGroupEnd { border: none;}
+.moodleSkin .mceToolbar .mceListBox { height: 30px; }
 .moodleSkin .mceToolbar .mceListBox td { border: none; border-radius: 0; }
 .moodleSkin .mceToolbar .mceListBox td a { border: none; border-radius: 0; }
 .moodleSkin .mceToolbar .mceToolbarEndPlaceholder { display: none; }
 .moodleSkin .mceToolbar .mceToolbarEnd { background: transparent; border: 0; }
-.moodleSkin.mceListBoxMenu { margin-left: -4px; margin-top: 2px; }
+.moodleSkin.mceListBoxMenu { margin-left: -4px; margin-top: 0px; }
+
+
+.moodleSkin .mceToolbar .mceGroupStart + td .mceLast a { border-radius: 0;}
+
 
 .dir-rtl .moodleSkin table {background:transparent; border-spacing: 0; }
 .dir-rtl .moodleSkin iframe {display:block;}
-.dir-rtl .moodleSkin .mceToolbar {min-height:30px; margin: 9px;}
+.dir-rtl .moodleSkin .mceToolbar {min-height:30px; margin: 4px;}
 .dir-rtl .moodleSkin .mceToolbar td + td { background: #fff; border: 1px solid #CCCCCC; border-left: none; border-bottom: 1px solid #b3b3b3; }
 .dir-rtl .moodleSkin .mceToolbar td + td:empty { display: none;}
-.dir-rtl .moodleSkin .mceToolbar a.mceButton { display:block; height: 30px; width: 40px; margin: 0; padding: 0; }
-.dir-rtl .moodleSkin .mceToolbar a span.mceIcon { height: 30px; width: 40px; margin: 0; }
-.dir-rtl .moodleSkin .mceToolbar a span.mceIcon img { padding: 7px 13px; }
+.dir-rtl .moodleSkin .mceToolbar select,
+.dir-rtl .moodleSkin .mceToolbar a.mceButton { display:block; height: 30px; width: 30px; margin: 0; padding: 0; }
+.dir-rtl .moodleSkin .mceToolbar a span.mceIcon { height: 30px; width: 30px; margin: 0; }
+.dir-rtl .moodleSkin .mceToolbar a span.mceIcon img { padding: 7px 7px; }
 .dir-rtl .moodleSkin .mceToolbar .mceGroupStart + td,
 .dir-rtl .moodleSkin .mceToolbar .mceToolbarStart + td,
 .dir-rtl .moodleSkin .mceToolbar .mceGroupStart + td a,
@@ -48,8 +55,8 @@
 .dir-rtl .moodleSkin .mceToolbar .mceToolbarStart + td.mceGroupEnd,
 .dir-rtl .moodleSkin .mceToolbar .mceToolbarStart + td.mceGroupEnd a { border-radius: 4px; }
 .dir-rtl .moodleSkin .mceToolbar .mceLast { border: none; }
-.dir-rtl .moodleSkin .mceToolbar .mceGroupStart { border: none; width: 9px; background: transparent;}
-.dir-rtl .moodleSkin .mceToolbar .mceGroupEnd { border-left: 1px solid #CCCCCC; border-radius: 4px 0 0 4px; border-right: 1px solid #CCCCCC; margin-left: 9px; }
+.dir-rtl .moodleSkin .mceToolbar .mceGroupStart { border: none; width: 4px; background: transparent;}
+.dir-rtl .moodleSkin .mceToolbar .mceGroupEnd { border-left: 1px solid #CCCCCC; border-radius: 4px 0 0 4px; border-right: 1px solid #CCCCCC; margin-left: 4px; }
 .dir-rtl .moodleSkin .mceToolbar .mceGroupEnd a { border-radius: 4px 0 0 4px; }
 .dir-rtl .moodleSkin .mceToolbar td div .mceGroupEnd { border: none; }
 .dir-rtl .moodleSkin .mceToolbar .mceListBox td { border: none; border-radius: 0; }
 .moodleSkin .mceButtonDisabled .mceButtonLabel {color:#888}
 
 /* Separator */
-.moodleSkin .mceSeparator {display:block; width:0px; height:22px; margin: 0 2px 0 1px; border-left: 1px solid #BBB }
+.moodleSkin .mceSeparator {display:none;}
 
 /* ListBox */
 .moodleSkin .mceListBox {padding: 0 3px}
 .moodleSkin .mceListBox, .moodleSkin .mceListBox a {display:block}
-.moodleSkin .mceListBox .mceText {padding-left:4px; text-align:left; width:70px; background:#eaf2fb; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; height:20px; line-height:20px; overflow:hidden}
-.moodleSkin .mceListBox .mceOpen {width:14px; height:22px; background:url(img/button_bg.png) -66px 0}
+.moodleSkin .mceListBox .mceText {padding-left:4px; text-align:left; width:70px; background:#eaf2fb; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; height:30px; line-height:30px; overflow:hidden}
+.moodleSkin .mceListBox .mceOpen {width:14px; height:30px; background:url(img/button_bg.png) -66px 0}
 .moodleSkin table.mceListBoxEnabled:hover .mceText, .moodleSkin .mceListBoxHover .mceText, .moodleSkin .mceListBoxSelected .mceText {background:#FFF}
 .moodleSkin table.mceListBoxEnabled:hover .mceOpen, .moodleSkin .mceListBoxHover .mceOpen, .moodleSkin .mceListBoxSelected .mceOpen {background-position:-66px -22px}
 .moodleSkin .mceListBoxDisabled .mceText {color:gray}
 /* SplitButton */
 .moodleSkin .mceSplitButton a {display:block; direction:ltr; height: 22px;}
 .moodleSkin .mceSplitButton, .moodleSkin .mceSplitButton span {display:block; height:30px; direction:ltr; }
-.moodleSkin .mceSplitButton { width: 50px; }
-.moodleSkin .mceSplitButton:hover {background-image: radial-gradient(ellipse at center, #ffffff 60%,#dfdfdf 100%); cursor: pointer;}
-.moodleSkin .mceSplitButton:active {background-image: radial-gradient(ellipse at center, #ffffff 40%,#dfdfdf 100%);}
-.moodleSkin .mceSplitButton .mceFirst { padding: 4px 0 0 9px; }
-.moodleSkin .mceSplitButton .mceLast { background: transparent;}
+.moodleSkin .mceSplitButton {width:48px;}
+.moodleSkin .mceSplitButton .mceFirst:hover {background-image:radial-gradient(ellipse at center, #ffffff 60%,#dfdfdf 100%); cursor:pointer;}
+.moodleSkin .mceSplitButton .mceFirst:active {background-image:radial-gradient(ellipse at center, #ffffff 40%,#dfdfdf 100%);}
+.moodleSkin .mceSplitButton .mceFirst {width:30px; padding:4px 0 0 6px;}
+.moodleSkin .mceSplitButton .mceLast {background: transparent; width: 15px;}
 .moodleSkin .mceSplitButton a.mceAction {width:20px}
-.moodleSkin .mceSplitButton a.mceOpen {width:10px; background:url(img/button_bg.png) 44px 0}
+.moodleSkin .mceSplitButton a.mceOpen {width:12px; background:url(img/button_bg.png) -66px 0px; border-left: 1px dashed #DDD; border-radius: 0; height: 30px;}
 .moodleSkin .mceSplitButton span.mceOpen {display:none}
-.moodleSkin table.mceSplitButtonEnabled:hover a.mceOpen, .moodleSkin .mceSplitButtonHover a.mceOpen, .moodleSkin .mceSplitButtonSelected a.mceOpen {background-position:-44px -44px}
+.moodleSkin table.mceSplitButtonEnabled:hover a.mceOpen, .moodleSkin .mceSplitButtonHover a.mceOpen, .moodleSkin .mceSplitButtonSelected a.mceOpen {background-position:-66px -22px;}
 .moodleSkin .mceSplitButtonDisabled .mceAction {opacity:0.3;}
 .moodleSkin .mceSplitButtonActive {background-position:0 -44px}
 
 /* ColorSplitButton */
+.moodleSkin div.mceColorSplitMenu { margin-left: -1px; }
 .moodleSkin div.mceColorSplitMenu table {background:#FFF; border: 1px solid #BBB;}
 .moodleSkin .mceColorSplitMenu td {padding:2px}
 .moodleSkin .mceColorSplitMenu a {display:block; width:18px; height:18px; overflow:hidden; border:1px solid #BBB}
 .moodleSkin .mceColorSplitMenu a.mceMoreColors:hover {border:1px solid #0A246A; background-color:#B6BDD2}
 .moodleSkin a.mceMoreColors:hover {border:1px solid #0A246A}
 /* Font selector preview stuff */
-.moodleSkin .mce_forecolor span.mceAction, .moodleSkin .mce_backcolor span.mceAction {height:21px;overflow:hidden; position: relative; z-index: 1 }
+.moodleSkin .mce_forecolor span.mceAction, .moodleSkin .mce_backcolor span.mceAction {height:21px;overflow:hidden; position: relative; z-index: 1; }
 .moodleSkin .mceColorPreview {width:16px; height:16px; overflow:hidden; margin-left: 2px; position: relative; top: -18px;}
 
 /* Menu */
index 0ea7cbd..72fc96d 100644 (file)
@@ -24,7 +24,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2013110500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version   = 2013110600;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2013110500;        // Requires this Moodle version
 $plugin->component = 'editor_tinymce';  // Full name of the plugin (used for diagnostics)
 $plugin->release   = '3.5.8';           // This is NOT a directory name, see lib.php if you need to know where is the editor code!
index e149e35..c4c08e2 100644 (file)
@@ -137,14 +137,16 @@ class mbz_packer extends file_packer {
     }
 
     /**
-     * Selects appropriate packer for new archive depending on system option.
+     * Selects appropriate packer for new archive depending on system option
+     * and whether required extension is available.
      *
      * @return file_packer Suitable packer
      */
     protected function get_packer_for_archive_operation() {
         global $CFG;
+        require_once($CFG->dirroot . '/lib/filestorage/tgz_packer.php');
 
-        if ($CFG->enabletgzbackups) {
+        if ($CFG->enabletgzbackups && tgz_packer::has_required_extension()) {
             return get_file_packer('application/x-gzip');
         } else {
             return get_file_packer('application/zip');
@@ -156,13 +158,18 @@ class mbz_packer extends file_packer {
      *
      * @param string|stored_file $archivefile full pathname of zip file or stored_file instance
      * @return file_packer Suitable packer
+     * @throws moodle_exception If the file cannot be restored because of missing zlib
      */
     protected function get_packer_for_read_operation($archivefile) {
         global $CFG;
         require_once($CFG->dirroot . '/lib/filestorage/tgz_packer.php');
 
         if (tgz_packer::is_tgz_file($archivefile)) {
-            return get_file_packer('application/x-gzip');
+            if (tgz_packer::has_required_extension()) {
+                return get_file_packer('application/x-gzip');
+            } else {
+                throw new moodle_exception('errortgznozlib', 'backup');
+            }
         } else {
             return get_file_packer('application/zip');
         }
index cdb7bef..b232e4f 100644 (file)
@@ -35,6 +35,11 @@ class core_files_mbz_packer_testcase extends advanced_testcase {
 
         // Get backup packer.
         $packer = get_file_packer('application/vnd.moodle.backup');
+        require_once($CFG->dirroot . '/lib/filestorage/tgz_packer.php');
+        if (!tgz_packer::has_required_extension()) {
+            $this->markTestSkipped('zlib not available');
+            return;
+        }
 
         // Set up basic archive contents.
         $files = array('1.txt' => array('frog'));
index d61d264..d495ec8 100644 (file)
@@ -114,6 +114,9 @@ class core_files_tgz_packer_testcase extends advanced_testcase implements file_p
     public function test_to_normal_files() {
         global $CFG;
         $packer = get_file_packer('application/x-gzip');
+        if (self::skip_because_missing_zlib()) {
+            return;
+        }
 
         // Archive files.
         $files = $this->prepare_file_list();
@@ -154,6 +157,9 @@ class core_files_tgz_packer_testcase extends advanced_testcase implements file_p
      */
     public function test_to_stored_files() {
         global $CFG;
+        if (self::skip_because_missing_zlib()) {
+            return;
+        }
         $packer = get_file_packer('application/x-gzip');
 
         // Archive files.
@@ -220,6 +226,9 @@ class core_files_tgz_packer_testcase extends advanced_testcase implements file_p
      */
     public function test_only_specified_files() {
         global $CFG;
+        if (self::skip_because_missing_zlib()) {
+            return;
+        }
         $packer = get_file_packer('application/x-gzip');
 
         // Archive files.
@@ -252,6 +261,9 @@ class core_files_tgz_packer_testcase extends advanced_testcase implements file_p
      */
     public function test_file_progress() {
         global $CFG;
+        if (self::skip_because_missing_zlib()) {
+            return;
+        }
 
         // Set up.
         $filelist = $this->prepare_file_list();
@@ -309,6 +321,9 @@ class core_files_tgz_packer_testcase extends advanced_testcase implements file_p
      */
     public function test_list_files() {
         global $CFG;
+        if (self::skip_because_missing_zlib()) {
+            return;
+        }
 
         // Set up.
         $filelist = $this->prepare_file_list();
@@ -376,6 +391,9 @@ class core_files_tgz_packer_testcase extends advanced_testcase implements file_p
 
     public function test_is_tgz_file() {
         global $CFG;
+        if (self::skip_because_missing_zlib()) {
+            return;
+        }
 
         // Set up.
         $filelist = $this->prepare_file_list();
@@ -428,4 +446,19 @@ class core_files_tgz_packer_testcase extends advanced_testcase implements file_p
     public function progress($progress = file_progress::INDETERMINATE, $max = file_progress::INDETERMINATE) {
         $this->progress[] = array($progress, $max);
     }
+
+    /**
+     * Checks if zlib is available. If not, marks current test as skipped.
+     *
+     * @return bool True if text should be skipped
+     */
+    protected function skip_because_missing_zlib() {
+        global $CFG;
+        require_once($CFG->dirroot . '/lib/filestorage/tgz_packer.php');
+        if (!tgz_packer::has_required_extension()) {
+            $this->markTestSkipped('zlib not available');
+            return true;
+        }
+        return false;
+    }
 }
index bfa459d..c47662a 100644 (file)
@@ -695,6 +695,16 @@ class tgz_packer extends file_packer {
         fclose($fp);
         return ($firstbytes[0] == "\x1f" && $firstbytes[1] == "\x8b");
     }
+
+    /**
+     * The zlib extension is required for this packer to work. This is a single
+     * location for the code to check whether the extension is available.
+     *
+     * @return bool True if the extension is available OK
+     */
+    public static function has_required_extension() {
+        return extension_loaded('zlib');
+    }
 }
 
 
index 79b83eb..2e64523 100644 (file)
@@ -1113,7 +1113,9 @@ class phpFlickr {
         $args['content_type']   = isset($meta['content_type']) ? $meta['content_type'] : 1; // photo by default
         $args['hidden']         = isset($meta['hidden']) ? $meta['hidden'] : 2;             // hide from public searches by default
 
-        $args['async'] = 1;
+        // Do not enable the asynchronous more because then the query does not return a photo ID,
+        // and we need a photo ID to add the photo to a set later on.
+        // $args['async'] = 1;
         $args['api_key'] = $this->api_key;
 
         if (!empty($this->email)) {
@@ -1144,8 +1146,17 @@ class phpFlickr {
         $args['photo'] = $photo; // $this->curl will process it correctly
 
         if ($response = $this->curl->post($this->Upload, $args)) {
+            $xml = simplexml_load_string($response);
+            if ($xml['stat'] == 'fail') {
+                $this->parsed_response = array('stat' => (string) $xml['stat'], 'code' => (int) $xml->err['code'],
+                    'message' => (string) $xml->err['msg']);
+            } elseif ($xml['stat'] == 'ok') {
+                $this->parsed_response = array('stat' => (string) $xml['stat'], 'photoid' => (int) $xml->photoid);
+            }
             return true;
         } else {
+            $this->parsed_response = array('stat' => 'fail', 'code' => $this->curl->get_errno(),
+                'message' => $this->curl->error);
             return false;
         }
     }
index afc9264..423480c 100644 (file)
@@ -617,6 +617,39 @@ abstract class oauth2_client extends curl {
         return null;
     }
 
+    /**
+     * Get access token.
+     *
+     * This is just a getter to read the private property.
+     *
+     * @return string
+     */
+    public function get_accesstoken() {
+        return $this->accesstoken;
+    }
+
+    /**
+     * Get the client ID.
+     *
+     * This is just a getter to read the private property.
+     *
+     * @return string
+     */
+    public function get_clientid() {
+        return $this->clientid;
+    }
+
+    /**
+     * Get the client secret.
+     *
+     * This is just a getter to read the private property.
+     *
+     * @return string
+     */
+    public function get_clientsecret() {
+        return $this->clientsecret;
+    }
+
     /**
      * Should HTTP GET be used instead of POST?
      * Some APIs do not support POST and want oauth to use
index 39a6e05..bf74322 100644 (file)
@@ -3153,7 +3153,7 @@ EOD;
             // No name for tabtree root.
         } else if ($tabobject->inactive || $tabobject->activated || ($tabobject->selected && !$tabobject->linkedwhenselected)) {
             // Tab name without a link. The <a> tag is used for styling.
-            $str .= html_writer::tag('a', html_writer::span($tabobject->text), array('class' => 'nolink'));
+            $str .= html_writer::tag('a', html_writer::span($tabobject->text), array('class' => 'nolink moodle-has-zindex'));
         } else {
             // Tab name with a link.
             if (!($tabobject->link instanceof moodle_url)) {
index 5d1a972..e190a59 100644 (file)
@@ -177,7 +177,7 @@ class testing_repository_generator extends component_generator_base {
         $record = $this->prepare_type_record($record);
         foreach ($typeoptions as $option) {
             if (!isset($record[$option])) {
-                throw new coding_exception("$option must be present in testing::create_repository_type() $record");
+                throw new coding_exception("$option must be present in testing::create_repository_type() for $type");
             }
         }
 
index 2db1ecd..7807cae 100644 (file)
@@ -56,6 +56,9 @@ information provided here is intended especially for developers.
   to 6 hours from 24 hours because etags and x-sendfile support should make file serving less expensive.
 * Date format locale charset for windows server will come from calendar type and for gregorian it will use
   lang file.
+* The library to interact with Box.net (class boxclient) is only compatible with their APIv1 which
+  reaches its end of life on the 14th of Dec. You should migrate your scripts to make usage of the
+  new class boxnet_client(). Note that the method names and return values have changed.
 
 DEPRECATIONS:
 Various previously deprecated functions have now been altered to throw DEBUG_DEVELOPER debugging notices
index 118da7b..48cd782 100644 (file)
Binary files a/lib/yui/build/moodle-core-actionmenu/moodle-core-actionmenu-debug.js and b/lib/yui/build/moodle-core-actionmenu/moodle-core-actionmenu-debug.js differ
index 8b8d1eb..b19c01b 100644 (file)
Binary files a/lib/yui/build/moodle-core-actionmenu/moodle-core-actionmenu-min.js and b/lib/yui/build/moodle-core-actionmenu/moodle-core-actionmenu-min.js differ
index a1173c3..9614abc 100644 (file)
Binary files a/lib/yui/build/moodle-core-actionmenu/moodle-core-actionmenu.js and b/lib/yui/build/moodle-core-actionmenu/moodle-core-actionmenu.js differ
index 6964253..e8d0895 100644 (file)
@@ -332,7 +332,8 @@ YUI.add('moodle-core-dragdrop', function(Y) {
                 headerContent : dialogtitle,
                 bodyContent : droplist,
                 draggable : true,
-                visible : true
+                visible : true,
+                centered : true
             });
 
             // Focus the first drop target.
index 17044d1..6cc48ac 100644 (file)
@@ -14,7 +14,8 @@ var BODY = Y.one(Y.config.doc.body),
         MENUCONTENT : '.menu[data-rel=menu-content]',
         MENUCONTENTCHILD: 'li a',
         MENUCHILD: '.menu li a',
-        TOGGLE : '.toggle-display'
+        TOGGLE : '.toggle-display',
+        KEEPOPEN: '[data-keepopen="1"]'
     },
     ACTIONMENU,
     ALIGN = {
@@ -157,6 +158,14 @@ ACTIONMENU.prototype = {
 
         // Check tabbing.
         this.events.push(menu.delegate('key', this.checkFocus, 'down:9', SELECTOR.MENUCHILD, this));
+
+        // Close the menu after a button was pushed.
+        this.events.push(menu.delegate('click', function(e) {
+            if (e.currentTarget.test(SELECTOR.KEEPOPEN)) {
+                return;
+            }
+            this.hideMenu();
+        }, SELECTOR.MENUCONTENTCHILD, this));
     },
 
     /**
index a504604..a350104 100644 (file)
 defined('MOODLE_INTERNAL') || die();
 
 $string['addtoquicklist'] = 'Add to quicklist';
-$string['annotationcolour'] = 'Annotation color';
+$string['annotationcolour'] = 'Annotation colour';
 $string['black'] = 'Black';
 $string['blue'] = 'Blue';
-$string['cannotopenpdf'] = 'Cannot open the pdf file. The file may be corrupt, or in an unsupported format.';
+$string['cannotopenpdf'] = 'Cannot open the PDF. The file may be corrupt, or in an unsupported format.';
 $string['clear'] = 'Clear';
-$string['colourpicker'] = 'Colour Picker';
-$string['commentcolour'] = 'Comment color';
+$string['colourpicker'] = 'Colour picker';
+$string['commentcolour'] = 'Comment colour';
 $string['comment'] = 'Comments';
 $string['command'] = 'Command:';
 $string['commentcontextmenu'] = 'Comment context menu';
@@ -46,7 +46,7 @@ $string['errorgenerateimage'] = 'Error generating image with ghostscript, debugg
 $string['editpdf'] = 'Annotate PDF';
 $string['editpdf_help'] = 'Annotate students submissions directly in the browser and produce an edited downloadable PDF.';
 $string['enabled'] = 'Annotate PDF';
-$string['enabled_help'] = 'If enabled, the teacher will be able to create annotated pdf files when marking the assignments. This allows the teacher to add comments, drawing and stamps directly on top of the students work. The annotating is done in the browser and no extra software is required.';
+$string['enabled_help'] = 'If enabled, the teacher will be able to create annotated PDF files when marking the assignments. This allows the teacher to add comments, drawing and stamps directly on top of the students work. The annotating is done in the browser and no extra software is required.';
 $string['filter'] = 'Filter comments...';
 $string['generatefeedback'] = 'Generate feedback PDF';
 $string['gotopage'] = 'Go to page';
@@ -54,7 +54,7 @@ $string['green'] = 'Green';
 $string['gspath'] = 'Ghostscript path';
 $string['gspath_help'] = 'On most Linux installs, this can be left as \'/usr/bin/gs\'. On Windows it will be something like \'c:\\gs\\bin\\gswin32c.exe\' (make sure there are no spaces in the path - if necessary copy the files \'gswin32c.exe\' and \'gsdll32.dll\' to a new folder without a space in the path)';
 $string['highlight'] = 'Highlight';
-$string['jsrequired'] = 'Annotating PDF documents requires javascript. Please enable javascript in your browser if you want to use this feature.';
+$string['jsrequired'] = 'JavaScript is required to annotate a PDF. Please enable JavaScript in your browser to use this feature.';
 $string['launcheditor'] = 'Launch PDF editor...';
 $string['line'] = 'Line';
 $string['loadingeditor'] = 'Loading PDF editor';
@@ -86,8 +86,7 @@ $string['test_ok'] = 'The ghostscript path appears to be OK - please check you c
 $string['toolbarbutton'] = '{$a->tool} {$a->shortcut}';
 $string['tool'] = 'Tool';
 $string['unsavedchanges'] = 'Unsaved changes';
-$string['viewfeedbackonline'] = 'View annotated pdf...';
+$string['viewfeedbackonline'] = 'View annotated PDF...';
 $string['white'] = 'White';
 $string['yellow'] = 'Yellow';
-$string['zlibenabled'] = 'zlib enabled';
 $string['zlibnotavailable'] = 'Php extension "zlib" is not available. The annotate PDF feature relies on this php extension and will be disabled until zlib is installed and enabled.';
index 10493d0..7831262 100644 (file)
@@ -40,7 +40,7 @@ $settings->add(new admin_setting_configexecutable('assignfeedback_editpdf/gspath
                                                   '/usr/bin/gs'));
 
 $setting = new admin_setting_php_extension_enabled('assignfeedback_editpdf/zlibenabled',
-                                                   get_string('zlibenabled', 'assignfeedback_editpdf'),
+                                                   get_string('zlibenabled', 'admin'),
                                                    get_string('zlibnotavailable', 'assignfeedback_editpdf'),
                                                    'zlib');
 
index 291c8a0..6dfa259 100644 (file)
@@ -54,7 +54,7 @@
 .assignfeedback_editpdf_widget .pageheader select,
 .assignfeedback_editpdf_widget .pageheader button {
     background: none;
-    padding: 4px 10px;
+    padding: 4px 7px;
     border: 0px;
     border-radius: 0px;
     margin: 0px;
 .assignfeedback_editpdf_dropdown button {
     border: 0px;
     background: none;
-    padding-left: 10px;
-    padding-right: 10px;
-    padding-top: 6px;
-    padding-bottom: 6px;
+    padding: 6px 7px;
     border-radius: 0px;
     border-top: 1px solid #cccccc;
 }
index 1cafbfe..7d9740c 100644 (file)
Binary files a/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-debug.js and b/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-debug.js differ
index 428b46b..cdb65b2 100644 (file)
Binary files a/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-min.js and b/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-min.js differ
index 1cafbfe..7d9740c 100644 (file)
Binary files a/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor.js and b/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor.js differ
index 943f273..a305844 100644 (file)
@@ -17,7 +17,6 @@ COMMENTSEARCH = function(config) {
     config.lightbox = true;
     config.visible = false;
     config.headerContent = M.util.get_string('searchcomments', 'assignfeedback_editpdf');
-    config.zIndex = 100;
     config.footerContent = '';
     COMMENTSEARCH.superclass.constructor.apply(this, [config]);
 };
index 93efa20..781b490 100644 (file)
@@ -16,7 +16,6 @@ DROPDOWN = function(config) {
     config.width = 'auto';
     config.lightbox = false;
     config.visible = false;
-    config.zIndex = 100;
     config.footerContent = '';
     DROPDOWN.superclass.constructor.apply(this, [config]);
 };
index fe845a5..e54996a 100644 (file)
@@ -225,11 +225,18 @@ $string['manageassignsubmissionplugins'] = 'Manage assignment submission plugins
 $string['marker'] = 'Marker';
 $string['markerfilter'] = 'Marker filter';
 $string['markingallocation'] = 'Use marking allocation';
-$string['markingallocation_help'] = 'If enabled, allow markers to be allocated to individual students - requires marking workflow to be enabled.';
+$string['markingallocation_help'] = 'If enabled together with marking workflow, markers can be allocated to particular students.';
 $string['markingworkflow'] = 'Use marking workflow';
-$string['markingworkflow_help'] = 'If enabled, marks will go through a series of workflow stages before being released to students. This allows for multiple rounds of marking allows all the marks to be released to all students at one time.';
+$string['markingworkflow_help'] = 'If enabled, marks will go through a series of workflow stages before being released to students. This allows for multiple rounds of marking and allows marks to be released to all students at the same time.';
 $string['markingworkflowstate'] = 'Marking workflow state';
-$string['markingworkflowstate_help'] = 'The list of workflow states you can choose are controlled by your permissions in this assignment. The full list of valid states is:<br><ul><li>In marking - The submissions is currently being marked</li></ul>...';
+$string['markingworkflowstate_help'] = 'Possible workflow states may include (depending on your permissions):
+
+* Not marked - the marker has not yet started
+* In marking - the marker has started but not yet finished
+* Marking completed - the marker has finished but might need to go back for checking/corrections
+* In review - the marking is now with the teacher in charge for quality checking
+* Ready for release - the teacher in charge is satisfied with the marking but wait before giving students access to the marking
+* Released - the student can access the grades/feedback';
 $string['markingworkflowstateinmarking'] = 'In marking';
 $string['markingworkflowstateinreview'] = 'In review';
 $string['markingworkflowstatenotmarked'] = 'Not marked';
index 22d55b1..a7b25fc 100644 (file)
@@ -81,8 +81,8 @@ $string['noresultsviewable'] = 'The results are not currently viewable.';
 $string['notanswered'] = 'Not answered yet';
 $string['notenrolledchoose'] = 'Sorry, only enrolled users are allowed to make choices.';
 $string['notopenyet'] = 'Sorry, this activity is not available until {$a}';
-$string['numberofuser'] = 'The number of user';
-$string['numberofuserinpercentage'] = 'The number of user in percentage';
+$string['numberofuser'] = 'Number of participants';
+$string['numberofuserinpercentage'] = 'Percentage of participants';
 $string['option'] = 'Option';
 $string['optionno'] = 'Option {no}';
 $string['options'] = 'Options';
index 48f3631..6cb333f 100644 (file)
@@ -123,7 +123,7 @@ if (!$quizname = $DB->get_field($cm->modname, 'name', array('id' => $cm->instanc
             print_error('invalidcoursemodule');
 }
 
-echo $OUTPUT->heading(get_string('addrandomquestiontoquiz', 'quiz', $quizname), 2, 'mdl-left');
+echo $OUTPUT->heading(get_string('addrandomquestiontoquiz', 'quiz', $quizname), 2);
 $mform->display();
 echo $OUTPUT->footer();
 
index 77177e4..be78d72 100644 (file)
@@ -50,8 +50,24 @@ add_to_log($attemptobj->get_courseid(), 'quiz', 'manualgrade', 'comment.php?atte
 
 // Print the page header.
 $PAGE->set_pagelayout('popup');
-echo $OUTPUT->header();
-echo $OUTPUT->heading(format_string($attemptobj->get_question_name($slot)));
+$PAGE->set_heading($attemptobj->get_course()->fullname);
+$output = $PAGE->get_renderer('mod_quiz');
+echo $output->header();
+
+// Prepare summary information about this question attempt.
+$summarydata = array();
+
+// Quiz name.
+$summarydata['quizname'] = array(
+    'title'   => get_string('modulename', 'quiz'),
+    'content' => format_string($attemptobj->get_quiz_name()),
+);
+
+// Question name.
+$summarydata['questionname'] = array(
+    'title'   => get_string('question', 'quiz'),
+    'content' => $attemptobj->get_question_name($slot),
+);
 
 // Process any data that was submitted.
 if (data_submitted() && confirm_sesskey()) {
@@ -59,12 +75,15 @@ if (data_submitted() && confirm_sesskey()) {
         $transaction = $DB->start_delegated_transaction();
         $attemptobj->process_submitted_actions(time());
         $transaction->allow_commit();
-        echo $OUTPUT->notification(get_string('changessaved'), 'notifysuccess');
+        echo $output->notification(get_string('changessaved'), 'notifysuccess');
         close_window(2, true);
         die;
     }
 }
 
+// Print quiz information.
+echo $output->review_summary_table($summarydata, 0);
+
 // Print the comment form.
 echo '<form method="post" class="mform" id="manualgradingform" action="' .
         $CFG->wwwroot . '/mod/quiz/comment.php">';
@@ -91,4 +110,4 @@ echo '</form>';
 $PAGE->requires->js_init_call('M.mod_quiz.init_comment_popup', null, false, quiz_get_js_module());
 
 // End of the page.
-echo $OUTPUT->footer();
+echo $output->footer();
index 1d30639..206bd9a 100644 (file)
@@ -56,6 +56,7 @@ $PAGE->set_title($strquizzes);
 $PAGE->set_button($streditquestions);
 $PAGE->set_heading($course->fullname);
 echo $OUTPUT->header();
+echo $OUTPUT->heading($strquizzes, 2);
 
 // Get all the appropriate data.
 if (!$quizzes = get_all_instances_in_course("quiz", $course)) {
index 66cdf32..5a22fa1 100644 (file)
@@ -650,7 +650,7 @@ $string['randomwithsubcat'] = 'Questions from this category and its subcategorie
 $string['readytosend'] = 'You are about to send your whole quiz to be graded.  Are you sure you want to continue?';
 $string['reattemptquiz'] = 'Re-attempt quiz';
 $string['recentlyaddedquestion'] = 'Recently added question!';
-$string['recurse'] = 'Include questions from sub-categories too';
+$string['recurse'] = 'Include questions from subcategories too';
 $string['regrade'] = 'Regrade all attempts';
 $string['regradecomplete'] = 'All attempts have been regraded';
 $string['regradecount'] = '{$a->changed} out of {$a->attempt} grades were changed';
index 7528226..8d9144f 100644 (file)
@@ -80,6 +80,7 @@ $PAGE->set_title($title);
 $PAGE->set_heading($course->fullname);
 
 echo $OUTPUT->header();
+echo $OUTPUT->heading(format_string($quiz->name, true, array('context' => $context)));
 
 if ($override->groupid) {
     $group = $DB->get_record('groups', array('id' => $override->groupid), 'id, name');
index b298780..37ef724 100644 (file)
@@ -194,7 +194,7 @@ $PAGE->set_pagelayout('admin');
 $PAGE->set_title($pagetitle);
 $PAGE->set_heading($course->fullname);
 echo $OUTPUT->header();
-echo $OUTPUT->heading($pagetitle);
+echo $OUTPUT->heading(format_string($quiz->name, true, array('context' => $context)));
 
 $mform->display();
 
index e6a5d84..260c84b 100644 (file)
@@ -72,6 +72,7 @@ $PAGE->set_pagelayout('admin');
 $PAGE->set_title(get_string('overrides', 'quiz'));
 $PAGE->set_heading($course->fullname);
 echo $OUTPUT->header();
+echo $OUTPUT->heading(format_string($quiz->name, true, array('context' => $context)));
 
 // Delete orphaned group overrides.
 $sql = 'SELECT o.id
index 7cf51e9..6900a3b 100644 (file)
@@ -99,6 +99,8 @@ class mod_quiz_renderer extends plugin_renderer_base {
     public function review_question_not_allowed($message) {
         $output = '';
         $output .= $this->header();
+        $output .= $this->heading(format_string($attemptobj->get_quiz_name(), true,
+                                  array("context" => $attemptobj->get_quizobj()->get_context())));
         $output .= $this->notification($message);
         $output .= $this->close_window_button();
         $output .= $this->footer();
@@ -392,6 +394,8 @@ class mod_quiz_renderer extends plugin_renderer_base {
     public function start_attempt_page(quiz $quizobj, mod_quiz_preflight_check_form $mform) {
         $output = '';
         $output .= $this->header();
+        $output .= $this->heading(format_string($quizobj->get_quiz_name(), true,
+                                  array("context" => $quizobj->get_context())));
         $output .= $this->quiz_intro($quizobj->get_quiz(), $quizobj->get_cm());
         ob_start();
         $mform->display();
@@ -879,7 +883,7 @@ class mod_quiz_renderer extends plugin_renderer_base {
      * Generates the table heading.
      */
     public function view_table_heading() {
-        return $this->heading(get_string('summaryofattempts', 'quiz'));
+        return $this->heading(get_string('summaryofattempts', 'quiz'), 3);
     }
 
     /**
@@ -1052,14 +1056,13 @@ class mod_quiz_renderer extends plugin_renderer_base {
                 $a->method = quiz_get_grading_option_name($quiz->grademethod);
                 $a->mygrade = quiz_format_grade($quiz, $viewobj->mygrade);
                 $a->quizgrade = quiz_format_grade($quiz, $quiz->grade);
-                $resultinfo .= $this->heading(get_string('gradesofar', 'quiz', $a), 2, 'main');
+                $resultinfo .= $this->heading(get_string('gradesofar', 'quiz', $a), 3);
             } else {
                 $a = new stdClass();
                 $a->grade = quiz_format_grade($quiz, $viewobj->mygrade);
                 $a->maxgrade = quiz_format_grade($quiz, $quiz->grade);
                 $a = get_string('outofshort', 'quiz', $a);
-                $resultinfo .= $this->heading(get_string('yourfinalgradeis', 'quiz', $a), 2,
-                        'main');
+                $resultinfo .= $this->heading(get_string('yourfinalgradeis', 'quiz', $a), 3);
             }
         }
 
@@ -1069,11 +1072,11 @@ class mod_quiz_renderer extends plugin_renderer_base {
                     array('class' => 'overriddennotice'))."\n";
         }
         if ($viewobj->gradebookfeedback) {
-            $resultinfo .= $this->heading(get_string('comment', 'quiz'), 3, 'main');
+            $resultinfo .= $this->heading(get_string('comment', 'quiz'), 3);
             $resultinfo .= html_writer::div($viewobj->gradebookfeedback, 'quizteacherfeedback') . "\n";
         }
         if ($viewobj->feedbackcolumn) {
-            $resultinfo .= $this->heading(get_string('overallfeedback', 'quiz'), 3, 'main');
+            $resultinfo .= $this->heading(get_string('overallfeedback', 'quiz'), 3);
             $resultinfo .= html_writer::div(
                     quiz_feedback_for_grade($viewobj->mygrade, $quiz, $context),
                     'quizgradefeedback') . "\n";
@@ -1157,7 +1160,7 @@ class mod_quiz_renderer extends plugin_renderer_base {
 
         $graph = html_writer::empty_tag('img', array('src' => $url, 'alt' => $title));
 
-        return $this->heading($title) . html_writer::tag('div', $graph, array('class' => 'graph'));
+        return $this->heading($title, 3) . html_writer::tag('div', $graph, array('class' => 'graph'));
     }
 }
 
index cd7d487..f6d5822 100644 (file)
@@ -67,6 +67,8 @@ abstract class quiz_default_report {
         $PAGE->set_title(format_string($quiz->name));
         $PAGE->set_heading($course->fullname);
         echo $OUTPUT->header();
+        $context = context_module::instance($cm->id);
+        echo $OUTPUT->heading(format_string($quiz->name, true, array('context' => $context)));
     }
 
     /**
index e793b0c..344bc37 100644 (file)
@@ -276,7 +276,7 @@ class quiz_grading_report extends quiz_default_report {
             groups_print_activity_menu($this->cm, $this->list_questions_url());
         }
 
-        echo $OUTPUT->heading(get_string('questionsthatneedgrading', 'quiz_grading'));
+        echo $OUTPUT->heading(get_string('questionsthatneedgrading', 'quiz_grading'), 3);
         if ($includeauto) {
             $linktext = get_string('hideautomaticallygraded', 'quiz_grading');
         } else {
@@ -316,7 +316,7 @@ class quiz_grading_report extends quiz_default_report {
         }
 
         if (empty($data)) {
-            echo $OUTPUT->heading(get_string('nothingfound', 'quiz_grading'));
+            echo $OUTPUT->notification(get_string('nothingfound', 'quiz_grading'));
             return;
         }
 
@@ -375,7 +375,7 @@ class quiz_grading_report extends quiz_default_report {
         $a = new stdClass();
         $a->number = $this->questions[$slot]->number;
         $a->questionname = format_string($counts->name);
-        echo $OUTPUT->heading(get_string('gradingquestionx', 'quiz_grading', $a));
+        echo $OUTPUT->heading(get_string('gradingquestionx', 'quiz_grading', $a), 3);
         echo html_writer::tag('p', html_writer::link($this->list_questions_url(),
                 get_string('backtothelistofquestions', 'quiz_grading')),
                 array('class' => 'mdl-align'));
index 5f62bc1..54cfc94 100644 (file)
@@ -310,7 +310,7 @@ class quiz_overview_report extends quiz_attempts_report {
      */
     protected function finish_regrade($nexturl) {
         global $OUTPUT, $PAGE;
-        echo $OUTPUT->heading(get_string('regradecomplete', 'quiz_overview'));
+        echo $OUTPUT->heading(get_string('regradecomplete', 'quiz_overview'), 3);
         echo $OUTPUT->continue_button($nexturl);
         echo $OUTPUT->footer();
         die();
index d8e09e7..4945b2d 100644 (file)
@@ -233,13 +233,13 @@ class quiz_statistics_report extends quiz_default_report {
 
         } else {
             // On-screen display of overview report.
-            echo $OUTPUT->heading(get_string('quizinformation', 'quiz_statistics'));
+            echo $OUTPUT->heading(get_string('quizinformation', 'quiz_statistics'), 3);
             echo $this->output_caching_info($quizstats, $quiz->id, $groupstudents, $whichattempts, $reporturl);
             echo $this->everything_download_options();
             $quizinfo = $quizstats->get_formatted_quiz_info_data($course, $cm, $quiz);
             echo $this->output_quiz_info_table($quizinfo);
             if ($quizstats->s()) {
-                echo $OUTPUT->heading(get_string('quizstructureanalysis', 'quiz_statistics'));
+                echo $OUTPUT->heading(get_string('quizstructureanalysis', 'quiz_statistics'), 3);
                 $this->output_quiz_structure_analysis_table($quizstats->s(), $questionstats, $subquestionstats);
                 $this->output_statistics_graph($quiz->id, $currentgroup, $whichattempts);
             }
@@ -305,10 +305,10 @@ class quiz_statistics_report extends quiz_default_report {
         }
 
         // Display the various bits.
-        echo $OUTPUT->heading(get_string('questioninformation', 'quiz_statistics'));
+        echo $OUTPUT->heading(get_string('questioninformation', 'quiz_statistics'), 3);
         echo html_writer::table($questioninfotable);
         echo $this->render_question_text($questionstat->question);
-        echo $OUTPUT->heading(get_string('questionstatistics', 'quiz_statistics'));
+        echo $OUTPUT->heading(get_string('questionstatistics', 'quiz_statistics'), 3);
         echo html_writer::table($questionstatstable);
     }
 
@@ -347,7 +347,7 @@ class quiz_statistics_report extends quiz_default_report {
         $qtable->export_class_instance($exportclass);
         if (!$this->table->is_downloading()) {
             // Output an appropriate title.
-            echo $OUTPUT->heading(get_string('analysisofresponses', 'quiz_statistics'));
+            echo $OUTPUT->heading(get_string('analysisofresponses', 'quiz_statistics'), 3);
 
         } else {
             // Work out an appropriate title.
@@ -447,7 +447,7 @@ class quiz_statistics_report extends quiz_default_report {
 
         // XHTML download is a special case.
         if ($this->table->is_downloading() == 'xhtml') {
-            echo $OUTPUT->heading(get_string('quizinformation', 'quiz_statistics'));
+            echo $OUTPUT->heading(get_string('quizinformation', 'quiz_statistics'), 3);
             echo $this->output_quiz_info_table($quizinfo);
             return;
         }
index d1821ca..18b84fd 100644 (file)
@@ -1,7 +1,13 @@
 This files describes API changes for quiz report plugins.
 
 Overview of this plugin type at http://docs.moodle.org/dev/Quiz_reports
+=== 2.6 ===
 
+* Improving the display page and heading levels to have a proper nesting.
+We are reducing the amount of white spaces for the top report by making
+'separate group' options and attempts to be displayed inline.
+In grading report, we are changing 'no questions' from using heading to
+notification message. (MDL-41615)
 
 === 2.3 ===
 
index 7359ff0..4080a2d 100644 (file)
@@ -50,6 +50,7 @@ $accessmanager = $attemptobj->get_access_manager(time());
 $options = $attemptobj->get_display_options(true);
 
 $PAGE->set_pagelayout('popup');
+$PAGE->set_heading($attemptobj->get_course()->fullname);
 $output = $PAGE->get_renderer('mod_quiz');
 
 // Check permissions.
index 0265221..a94e60f 100644 (file)
@@ -48,6 +48,7 @@ $PAGE->set_url($quizobj->view_url());
 // Check login and sesskey.
 require_login($quizobj->get_course(), false, $quizobj->get_cm());
 require_sesskey();
+$PAGE->set_heading($quizobj->get_course()->fullname);
 
 // If no questions have been set up yet redirect to edit.php or display an error.
 if (!$quizobj->has_questions()) {
index 589a927..4a8051f 100644 (file)
@@ -333,8 +333,19 @@ table.quizattemptsummary .noreviewmessage {
 .quizattemptcounts {
     clear: left;
     text-align: center;
+    display:inline;
+    margin-left:20%;
+}
+.dir-rtl .quizattemptcounts {
+    margin-left:0;
+    margin-right: 20%;
+}
+#page-mod-quiz-view .quizattemptcounts,
+.dir-rtl #page-mod-quiz-view .quizattemptcounts {
+    display: block;
+    margin-left: 0;
+    margin-right: 0;
 }
-
 /** Mod quiz summary **/
 #page-mod-quiz-summary #content {
     text-align: center;
@@ -745,7 +756,6 @@ table#categoryquestions {
     width: 1.4em;
     padding-right: 0.3em;
     padding-left: 0;
-    z-index: 99;
     text-align: right;
     color: #333;
 }
@@ -774,7 +784,6 @@ table#categoryquestions {
     border-radius: 0.2em;
     border-bottom-left-radius: 0;
     border-top-left-radius: 0;
-    z-index: 900;
     display: block;
     margin: 0;
     background-color: #ddf;
@@ -794,7 +803,6 @@ table#categoryquestions {
     border-radius: 0.2em;
     border-bottom-left-radius: 0;
     border-top-left-radius: 0;
-    z-index: 900;
     display: block;
     margin: 0;
     background-color: #ddf;
@@ -838,7 +846,6 @@ table#categoryquestions {
     position: absolute;
     right: 0.3em;
     top: 0;
-    z-index: 900;
     display: block;
     padding: 0.2em;
     background-color: #F9F9F9;
@@ -1048,7 +1055,6 @@ bank window's title is prominent enough*/
     top: 0.2em;
     right: 0.2em;
     display: inline;
-    z-index: 900;
 }
 #page-mod-quiz-edit .quizpagedelete img {
     background-color: #d6d6d6;
index bb01f54..a7b5326 100644 (file)
@@ -2,6 +2,8 @@ This files describes API changes in the quiz code.
 
 
 === 2.6 ===
+* As part of improving the page usability and accessibility, we updated the
+  heading levels for quiz module so it has a proper nesting. (MDL-41615)
 
 * mod_quiz_renderer::view_best_score has been removed. (It did not do what the
   name suggested anyway.)
index a6850f5..7f902a5 100644 (file)
@@ -49,7 +49,7 @@ $string['displayselect_help'] = 'This setting, together with the file type and w
 * Force download - The user is prompted to download the file
 * Open - Only the file is displayed in the browser window
 * In pop-up - The file is displayed in a new browser window without menus or an address bar
-* In frame - The file is displayed within a frame below the the navigation bar and file description
+* In frame - The file is displayed within a frame below the navigation bar and file description
 * New window - The file is displayed in a new browser window with menus and an address bar';
 $string['displayselect_link'] = 'mod/file/mod';
 $string['displayselectexplain'] = 'Choose display type, unfortunately not all types are suitable for all files.';
index bd02fe2..505d725 100644 (file)
@@ -56,7 +56,7 @@ $string['attls15short'] = 'put myself in their shoes';
 $string['attls16'] = 'One could call my way of analysing things \'putting them on trial\' because I am careful to consider all the evidence.';
 $string['attls16short'] = 'putting on trial';
 $string['attls17'] = 'I value the use of logic and reason over the incorporation of my own concerns when solving problems.';
-$string['attls17short'] = 'i value logic most';
+$string['attls17short'] = 'I value logic most';
 $string['attls18'] = 'I can obtain insight into opinions that differ from mine through empathy.';
 $string['attls18short'] = 'insight from empathy';
 $string['attls19'] = 'When I encounter people whose opinions seem alien to me, I make a deliberate effort to \'extend\' myself into that person, to try to see how they could have those opinions.';
index 1f6a305..19b886c 100644 (file)
@@ -39,7 +39,7 @@ $string['displayselect_help'] = 'This setting, together with the URL file type a
 * Embed - The URL is displayed within the page below the navigation bar together with the URL description and any blocks
 * Open - Only the URL is displayed in the browser window
 * In pop-up - The URL is displayed in a new browser window without menus or an address bar
-* In frame - The URL is displayed within a frame below the the navigation bar and URL description
+* In frame - The URL is displayed within a frame below the navigation bar and URL description
 * New window - The URL is displayed in a new browser window with menus and an address bar';
 $string['displayselectexplain'] = 'Choose display type, unfortunately not all types are suitable for all URLs.';
 $string['externalurl'] = 'External URL';
index d6f3e39..86578cc 100644 (file)
@@ -37,7 +37,7 @@ $string['noallocationtoadd'] = 'No allocations to add';
 $string['nogroupusers'] = '<p>Warning: If the workshop is in \'visible groups\' mode or \'separate groups\' mode, then users MUST be part of at least one group to have peer-assessments allocated to them by this tool. Non-grouped users can still be given new self-assessments or have existing assessments removed.</p>
 <p>These users are currently not in a group: {$a}</p>';
 $string['numofdeallocatedassessment'] = 'Deallocating {$a} assessment(s)';
-$string['numofrandomlyallocatedsubmissions'] = 'Randomly allocating {$a} submissions';
+$string['numofrandomlyallocatedsubmissions'] = 'Randomly assigning {$a} allocations';
 $string['numofreviews'] = 'Number of reviews';
 $string['numofselfallocatedsubmissions'] = 'Self-allocating {$a} submission(s)';
 $string['numperauthor'] = 'per submission';
diff --git a/portfolio/boxnet/db/upgrade.php b/portfolio/boxnet/db/upgrade.php
new file mode 100644 (file)
index 0000000..2f445a5
--- /dev/null
@@ -0,0 +1,62 @@
+<?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/>.
+
+/**
+ * Upgrade.
+ *
+ * @package    portfolio_boxnet
+ * @copyright  2013 Frédéric Massart
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Upgrade function.
+ *
+ * @param int $oldversion the version we are upgrading from.
+ * @return bool result
+ */
+function xmldb_portfolio_boxnet_upgrade($oldversion) {
+    global $CFG, $DB;
+
+    $dbman = $DB->get_manager();
+
+    if ($oldversion < 2013110602) {
+        require_once($CFG->libdir . '/portfoliolib.php');
+        require_once($CFG->dirroot . '/portfolio/boxnet/db/upgradelib.php');
+
+        $existing = $DB->get_record('portfolio_instance', array('plugin' => 'boxnet'), '*', IGNORE_MULTIPLE);
+        if ($existing) {
+
+            // Only disable or message the admins when the portfolio hasn't been set for APIv2.
+            $instance = portfolio_instance($existing->id, $existing);
+            if ($instance->get_config('clientid') === null && $instance->get_config('clientsecret') === null) {
+
+                // Disable Box.net.
+                $instance->set('visible', 0);
+                $instance->save();
+
+                // Message the admins.
+                portfolio_boxnet_admin_upgrade_notification();
+            }
+        }
+
+        upgrade_plugin_savepoint(true, 2013110602, 'portfolio', 'boxnet');
+    }
+
+    return true;
+}
diff --git a/portfolio/boxnet/db/upgradelib.php b/portfolio/boxnet/db/upgradelib.php
new file mode 100644 (file)
index 0000000..fe87bd6
--- /dev/null
@@ -0,0 +1,55 @@
+<?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/>.
+
+/**
+ * Locallib.
+ *
+ * @package    portfolio_boxnet
+ * @copyright  2013 Frédéric Massart
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Send a message to the admin in regard with the APIv1 migration.
+ *
+ * @return void
+ */
+function portfolio_boxnet_admin_upgrade_notification() {
+    $admins = get_admins();
+
+    if (empty($admins)) {
+        return;
+    }
+    $a = new stdClass();
+    $a->docsurl = get_docs_url('Box.net_APIv1_migration');
+
+    foreach ($admins as $admin) {
+        $message = new stdClass();
+        $message->component         = 'moodle';
+        $message->name              = 'notices';
+        $message->userfrom          = get_admin();
+        $message->userto            = $admin;
+        $message->smallmessage      = get_string('apiv1migration_message_small', 'portfolio_boxnet');
+        $message->subject           = get_string('apiv1migration_message_subject', 'portfolio_boxnet');
+        $message->fullmessage       = get_string('apiv1migration_message_content', 'portfolio_boxnet', $a);
+        $message->fullmessagehtml   = get_string('apiv1migration_message_content', 'portfolio_boxnet', $a);
+        $message->fullmessageformat = FORMAT_PLAIN;
+        $message->notification      = 1;
+        message_send($message);
+    }
+}
index ed67b3b..b1f9449 100644 (file)
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-$string['apikey'] = 'API key';
-$string['err_noapikey'] = 'No API key';
-$string['err_noapikey_help'] = 'There is no API key configured for this plugin. You can get one of these from OpenBox development page.';
+$string['apiv1migration_message_content'] = 'As part of the recent Moodle upgrade to 2.6, the Box.net portfolio plugin has been disabled. To re-enable it, you need to re-configure it as described in the documentation {$a->docsurl}.';
+$string['apiv1migration_message_small'] = 'This plugin has been disabled, as it requires configuration as described in the documentation Box.net APIv1 migration.';
+$string['apiv1migration_message_subject'] = 'Important information regarding Box.net portfolio plugin';
+$string['clientid'] = 'Client ID';
+$string['clientsecret'] = 'Client secret';
 $string['existingfolder'] = 'Existing folder to put file(s) into';
 $string['folderclash'] = 'The folder you asked to create already exists!';
 $string['foldercreatefailed'] = 'Failed to create your target folder on box.net';
 $string['folderlistfailed'] = 'Failed to retrieve a folder listing from box.net';
+$string['missinghttps'] = 'HTTPS required';
+$string['missinghttps_help'] = 'Box.net will only work with an HTTPS enabled website.';
+$string['missingoauthkeys'] = 'Missing client ID and secret';
+$string['missingoauthkeys_help'] = 'There is no client ID or secret configured for this plugin. You can get one of these from Box.net development page.';
 $string['newfolder'] = 'New folder to put file(s) into';
 $string['noauthtoken'] = 'Could not retrieve an authentication token for use in this session';
 $string['notarget'] = 'You must specify either an existing folder or a new folder to upload into';
@@ -38,10 +44,11 @@ $string['password'] = 'Your box.net password (will not be stored)';
 $string['pluginname'] = 'Box.net';
 $string['sendfailed'] = 'Failed to send content to box.net: {$a}';
 $string['setupinfo'] = 'Setup instructions';
-$string['setupinfodetails'] = 'To obtain API key, log in to Box.net and visit their <a href="{$a->servicesurl}">OpenBox development page</a>. In \'Developer Tools\', follow \'Create new application\' and create new application for your Moodle site. API key is displayed in \'Backend parameters\' section of the application edit form. In that form, fill \'Redirect URL\' field to:<br /><code>{$a->callbackurl}</code><br />Optionally, you can also provide other information about your Moodle site. These values can be edited later at \'View my applications\' page.';
+$string['setupinfodetails'] = 'To obtain a client ID and secret, log in to Box.net and visit their <a href="{$a->servicesurl}">developers page</a>. Follow \'Create new application\' and create new application for your Moodle site. The client ID ans secret are displayed in \'OAuth2 parameters\' section of the application edit form. Optionally, you can also provide other information about your Moodle site.';
 $string['sharedfolder'] = 'Shared';
 $string['sharefile'] = 'Share this file?';
 $string['sharefolder'] = 'Share this new folder?';
 $string['targetfolder'] = 'Target folder';
 $string['tobecreated'] = 'To be created';
 $string['username'] = 'Your box.net username (will not be stored)';
+$string['warninghttps'] = 'Box.net requires your website to be using HTTPS in order for the portfolio to work.';
index 3a9093b..ef8030a 100644 (file)
@@ -22,29 +22,23 @@ class portfolio_plugin_boxnet extends portfolio_plugin_push_base {
     public function send_package() {
         // if we need to create the folder, do it now
         if ($newfolder = $this->get_export_config('newfolder')) {
-            if (!$created = $this->boxclient->createFolder($newfolder, array('share' => (int)$this->get_export_config('sharefolder')))) {
+            $created = $this->boxclient->create_folder($newfolder);
+            if (empty($created->id)) {
                 throw new portfolio_plugin_exception('foldercreatefailed', 'portfolio_boxnet');
             }
-            $this->folders[$created['folder_id']] = $created['folder_name'];
-            $this->set_export_config(array('folder' => $created['folder_id']));
+            $this->folders[$created->id] = $created->name;
+            $this->set_export_config(array('folder' => $created->id));
         }
         foreach ($this->exporter->get_tempfiles() as $file) {
-            $return = $this->boxclient->uploadFile(
-                array(
-                    'file'      => $file,
-                    'folder_id' => $this->get_export_config('folder'),
-                    'share'     => $this->get_export_config('sharefile'),
-                )
-            );
-            if (array_key_exists('status', $return) && $return['status'] == 'upload_ok'
-                    && array_key_exists('id', $return) && count($return['id']) == 1) {
-                $returnid = array_keys($return['id']);
-                $this->rename_file($return['id'][array_pop($returnid)], $file->get_filename());
-                // if this fails, the file was sent but not renamed - this triggers a warning but is not fatal.
+            $return = $this->boxclient->upload_file($file, $this->get_export_config('folder'));
+            if (!empty($result->type) && $result->type == 'error') {
+                throw new portfolio_plugin_exception('sendfailed', 'portfolio_boxnet', $result->message);
+            }
+            $createdfile = reset($return->entries);
+            if (!empty($createdfile->id)) {
+                $result = $this->rename_file($createdfile->id, $file->get_filename());
+                // If this fails, the file was sent but not renamed.
             }
-        }
-        if ($this->boxclient->isError()) {
-            throw new portfolio_plugin_exception('sendfailed', 'portfolio_boxnet', $this->boxclient->getErrorMsg());
         }
     }
 
@@ -52,22 +46,24 @@ class portfolio_plugin_boxnet extends portfolio_plugin_push_base {
         $allfolders = $this->get_folder_list();
         if ($newfolder = $this->get_export_config('newfolder')) {
             $foldername = $newfolder . ' (' . get_string('tobecreated', 'portfolio_boxnet') . ')';
-        } elseif ($this->get_export_config('folder')) {
+        } else if ($this->get_export_config('folder')) {
             $foldername = $allfolders[$this->get_export_config('folder')];
         } else {
-            $foldername = '';
+            $foldername = '/';
         }
         return array(
-            get_string('targetfolder', 'portfolio_boxnet') => $foldername
+            get_string('targetfolder', 'portfolio_boxnet') => s($foldername)
         );
     }
 
     public function get_interactive_continue_url() {
-        return 'http://box.net/files#0:f:' . $this->get_export_config('folder');
+        return 'https://app.box.net/files/0/f/' . $this->get_export_config('folder') . '/';
     }
 
     public function expected_time($callertime) {
-        return $callertime;
+        // We're forcing this to be run 'interactively' because the plugin
+        // does not support running in cron.
+        return PORTFOLIO_TIME_LOW;
     }
 
     public static function has_admin_config() {
@@ -75,28 +71,22 @@ class portfolio_plugin_boxnet extends portfolio_plugin_push_base {
     }
 
     public static function get_allowed_config() {
-        return array('apikey');
+        return array('clientid', 'clientsecret');
     }
 
     public function has_export_config() {
         return true;
     }
 
-    public function get_allowed_user_config() {
-        return array('authtoken', 'authtokenctime');
-    }
-
     public function get_allowed_export_config() {
-        return array('folder', 'newfolder', 'sharefile', 'sharefolder');
+        return array('folder', 'newfolder');
     }
 
     public function export_config_form(&$mform) {
         $folders = $this->get_folder_list();
-        $mform->addElement('checkbox', 'plugin_sharefile', get_string('sharefile', 'portfolio_boxnet'));
         $mform->addElement('text', 'plugin_newfolder', get_string('newfolder', 'portfolio_boxnet'));
         $mform->setType('plugin_newfolder', PARAM_RAW);
-        $mform->addElement('checkbox', 'plugin_sharefolder', get_string('sharefolder', 'portfolio_boxnet'));
-        $folders[0] = '----';
+        $folders[0] = '/';
         ksort($folders);
         $mform->addElement('select', 'plugin_folder', get_string('existingfolder', 'portfolio_boxnet'), $folders);
     }
@@ -111,134 +101,115 @@ class portfolio_plugin_boxnet extends portfolio_plugin_push_base {
     public static function admin_config_form(&$mform) {
         global $CFG;
 
-        $mform->addElement('text', 'apikey', get_string('apikey', 'portfolio_boxnet'));
-        $mform->addRule('apikey', get_string('required'), 'required', null, 'client');
-        $mform->setType('apikey', PARAM_RAW_TRIMMED);
+        $mform->addElement('text', 'clientid', get_string('clientid', 'portfolio_boxnet'));
+        $mform->addRule('clientid', get_string('required'), 'required', null, 'client');
+        $mform->setType('clientid', PARAM_RAW_TRIMMED);
+
+        $mform->addElement('text', 'clientsecret', get_string('clientsecret', 'portfolio_boxnet'));
+        $mform->addRule('clientsecret', get_string('required'), 'required', null, 'client');
+        $mform->setType('clientsecret', PARAM_RAW_TRIMMED);
+
         $a = new stdClass();
-        $a->servicesurl = 'http://www.box.net/developers/services';
-        $a->callbackurl = $CFG->wwwroot . '/portfolio/add.php?postcontrol=1&type=boxnet';
+        $a->servicesurl = 'https://app.box.com/developers/services';
         $mform->addElement('static', 'setupinfo', get_string('setupinfo', 'portfolio_boxnet'),
             get_string('setupinfodetails', 'portfolio_boxnet', $a));
+
+        if (strpos($CFG->wwwroot, 'https') !== 0) {
+            $mform->addElement('static', 'warninghttps', '', get_string('warninghttps', 'portfolio_boxnet'));
+        }
     }
 
     public function steal_control($stage) {
         if ($stage != PORTFOLIO_STAGE_CONFIG) {
             return false;
         }
-        if ($this->authtoken) {
-            return false;
-        }
-        if (!$this->ensure_ticket()) {
-            throw new portfolio_plugin_exception('noticket', 'portfolio_boxnet');
+        if (empty($this->boxclient)) {
+            $returnurl = new moodle_url('/portfolio/add.php', array('postcontrol' => 1, 'type' => 'boxnet',
+                'sesskey' => sesskey()));
+            $this->boxclient = new boxnet_client($this->get_config('clientid'), $this->get_config('clientsecret'), $returnurl, '');
         }
-        $token = $this->get_user_config('authtoken', $this->get('user')->id);
-        $ctime= $this->get_user_config('authtokenctime', $this->get('user')->id);
-        if (!empty($token) && (($ctime + 60*60*20) > time())) {
-            $this->authtoken = $token;
-            $this->boxclient->auth_token = $token;
+        if ($this->boxclient->is_logged_in()) {
             return false;
         }
-        return 'http://www.box.net/api/1.0/auth/'.$this->ticket;
+        return $this->boxclient->get_login_url();
     }
 
     public function post_control($stage, $params) {
         if ($stage != PORTFOLIO_STAGE_CONFIG) {
             return;
         }
-        if (!array_key_exists('auth_token', $params) || empty($params['auth_token'])) {
+        if (!$this->boxclient->is_logged_in()) {
             throw new portfolio_plugin_exception('noauthtoken', 'portfolio_boxnet');
         }
-        $this->authtoken = $params['auth_token'];
-        $this->boxclient->auth_token = $this->authtoken;
-        $this->set_user_config(array('authtoken' => $this->authtoken, 'authtokenctime' => time()), $this->get('user')->id);
     }
 
-    private function ensure_ticket() {
-        if (!empty($this->boxclient)) {
-            return true;
-        }
-        $this->boxclient = new boxclient($this->get_config('apikey'), '');
-        $ticket_return = $this->boxclient->getTicket();
-        if ($this->boxclient->isError() || empty($ticket_return)) {
-            throw new portfolio_plugin_exception('noticket', 'portfolio_boxnet');
-        }
-        $this->ticket = $ticket_return['ticket'];
-        return $this->ticket;
-    }
-
-    private function ensure_account_tree() {
-        if (!empty($this->accounttree)) {
-            return;
-        }
-        if (empty($this->ticket)
-            || empty($this->authtoken)
-            || empty($this->boxclient)) {
-            // if we don't have these we're pretty much screwed
-            throw new portfolio_plugin_exception('folderlistfailed', 'portfolio_boxnet');
-            return false;
-        }
-        $this->accounttree = $this->boxclient->getAccountTree();
-        if ($this->boxclient->isError()) {
-            throw new portfolio_plugin_exception('folderlistfailed', 'portfolio_boxnet');
-        }
-        if (!is_array($this->accounttree)) {
-            return false;
+    /**
+     * Get the folder list.
+     *
+     * This is limited to the folders in the root folder.
+     *
+     * @return array of folders.
+     */
+    protected function get_folder_list() {
+        if (empty($this->folders)) {
+            $folders = array();
+            $result = $this->boxclient->get_folder_items();
+            foreach ($result->entries as $item) {
+                if ($item->type != 'folder') {
+                    continue;
+                }
+                $folders[$item->id] = $item->name;
+                if (!empty($item->shared)) {
+                    $folders[$item->id] .= ' (' . get_string('sharedfolder', 'portfolio_boxnet') . ')';
+                }
+            }
+            $this->folders = $folders;
         }
+        return $this->folders;
     }
 
-    private function get_folder_list() {
-        if (!empty($this->folders)) {
-            return $this->folders;
-        }
-        $this->ensure_account_tree();
-        $folders = array();
-        foreach ($this->accounttree['folder_id'] as $key => $id) {
-            if (empty($id)) {
-                continue;
+    /**
+     * Rename a file.
+     *
+     * If the name is already taken, we append the current date to the file
+     * to prevent name conflicts.
+     *
+     * @param int $fileid The file ID.
+     * @param string $newname The new name.
+     * @return bool Whether it succeeded or not.
+     */
+    protected function rename_file($fileid, $newname) {
+        $result = $this->boxclient->rename_file($fileid, $newname);
+        if (!empty($result->type) && $result->type == 'error') {
+            $bits = explode('.', $newname);
+            $suffix = '';
+            if (count($bits) == 1) {
+                $prefix = $newname;
+            } else {
+                $suffix = '.' . array_pop($bits);
+                $prefix = implode('.', $bits);
             }
-            $name = $this->accounttree['folder_name'][$key];
-            if (!empty($this->accounttree['shared'][$key])) {
-                $name .= ' (' . get_string('sharedfolder', 'portfolio_boxnet') . ')';
+            $newname = $prefix . ' (' . date('Y-m-d H-i-s') . ')' . $suffix;
+            $result = $this->boxclient->rename_file($fileid, $newname);
+            if (empty($result->type) || $result->type != 'error') {
+                return true;
+            } else {
+                // We could not rename the file for some reason...
+                debugging('Error while renaming the file on Box.net', DEBUG_DEVELOPER);
             }
-            $folders[$id] = $name;
-        }
-        $this->folders = $folders;
-        return $folders;
-    }
-
-    private function rename_file($fileid, $newname) {
-        // look at moving this to the boxnet client class
-        $this->ensure_account_tree();
-        $count = 1;
-        $bits = explode('.', $newname);
-        $suffix = '';
-        if (count($bits) == 1) {
-            $prefix = $newname;
         } else {
-            $suffix = '.' . array_pop($bits);
-            $prefix = implode('.', $bits);
-        }
-        while (true) {
-            if (!array_key_exists('file_name', $this->accounttree) || !in_array($newname, $this->accounttree['file_name'])) {
-                for ($i = 0; $i < 2; $i++) {
-                    if ($this->boxclient->renameFile($fileid, $newname)) {
-                        return true;
-                    }
-                }
-                debugging("tried three times to rename file and failed");
-                return false;
-            }
-            $newname = $prefix . '(' . $count . ')' . $suffix;
-            $count++;
+            return true;
         }
         return false;
     }
 
     public function instance_sanity_check() {
-        if (!$this->get_config('apikey')) {
-            return 'err_noapikey';
+        global $CFG;
+        if (!$this->get_config('clientid') || !$this->get_config('clientsecret')) {
+            return 'missingoauthkeys';
+        } else if (strpos($CFG->wwwroot, 'https') !== 0) {
+            return 'missinghttps';
         }
-    //@TODO see if we can verify the api key without actually getting an authentication token
     }
 
     public static function allows_multiple_instances() {
index 5270713..698b5ac 100644 (file)
@@ -24,7 +24,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2013110500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version   = 2013110602;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2013110500;        // Requires this Moodle version
 $plugin->component = 'portfolio_boxnet'; // Full name of the plugin (used for diagnostics)
 $plugin->cron      = 0;
index 6fc9659..df85a00 100644 (file)
@@ -64,7 +64,7 @@ class portfolio_plugin_flickr extends portfolio_plugin_push_base {
                         'hidden'        => $this->get_export_config('hidden')));
                 if ($return) {
                     // Attach photo to a set if requested
-                    if ($this->get_export_config('set')) {
+                    if ($this->get_export_config('set') && !empty($this->flickr->parsed_response['photoid'])) {
                         $this->flickr->photosets_addPhoto($this->get_export_config('set'),
                             $this->flickr->parsed_response['photoid']);
                     }
@@ -188,10 +188,12 @@ class portfolio_plugin_flickr extends portfolio_plugin_push_base {
 
         $mform->setDefaults(array('plugin_is_public' => true));
 
-        $sets = $this->get_sets();
-
-        if (!empty($sets)) {
-            $sets[0] = '----';
+        $rawsets = $this->get_sets();
+        if (!empty($rawsets)) {
+            $sets = array('0' => '----');
+            foreach ($rawsets as $key => $value) {
+                $sets[$key] = $value;
+            }
             $mform->addElement('select', 'plugin_set', get_string('set', 'portfolio_flickr'), $sets);
         }
     }
index b07317f..56b490f 100644 (file)
@@ -138,7 +138,7 @@ class core_question_renderer extends plugin_renderer_base {
         if (!$numbertext) {
             return '';
         }
-        return html_writer::tag('h2', $numbertext, array('class' => 'no'));
+        return html_writer::tag('h3', $numbertext, array('class' => 'no'));
     }
 
     /**
@@ -150,7 +150,7 @@ class core_question_renderer extends plugin_renderer_base {
      */
     protected function add_part_heading($heading, $content) {
         if ($content) {
-            $content = html_writer::tag('h3', $heading, array('class' => 'accesshide')) . $content;
+            $content = html_writer::tag('h4', $heading, array('class' => 'accesshide')) . $content;
         }
         return $content;
     }
@@ -456,7 +456,7 @@ class core_question_renderer extends plugin_renderer_base {
             $table->data[] = $row;
         }
 
-        return html_writer::tag('h3', get_string('responsehistory', 'question'),
+        return html_writer::tag('h4', get_string('responsehistory', 'question'),
                 array('class' => 'responsehistoryheader')) . html_writer::tag('div',
                 html_writer::table($table, true), array('class' => 'responsehistoryheader'));
     }
index a6c03c2..bb77339 100644 (file)
@@ -10,6 +10,9 @@ question_engine::is_manual_grade_in_range.
 ($qa, $options) to ($qa, $behaviouroutput, $options). If you have overridden
 that method you will need to update your code.
 
+3) Heading level for number(), add_part_heading() and respond_history()
+has been lowered by one level. These changes are part of improving the page
+accessibility and making heading to have proper nesting. (MDL-41615)
 
 === Earlier changes ===
 
index 035bc3e..1fb0c07 100644 (file)
@@ -44,7 +44,7 @@ class qtype_description_walkthrough_test extends qbehaviour_walkthrough_test_bas
                 $this->quba->get_question_attempt($this->slot)->get_behaviour_name());
 
         $this->check_current_output(
-                new question_contains_tag_with_contents('h3', get_string('informationtext', 'qtype_description'))
+                new question_contains_tag_with_contents('h4', get_string('informationtext', 'qtype_description'))
         );
 
         // Further tests of the description qtype are in
index 7c58a6b..2757b2f 100644 (file)
@@ -106,14 +106,11 @@ $string['units'] = 'Units';
 $string['unitselect'] = 'a drop-down menu';
 $string['unitx'] = 'Unit {no} ';
 $string['validnumberformats'] = 'Valid number formats';
-$string['validnumberformats_help'] = '
-* regular numbers 13500.67, 13 500.67, 13500,67 or 13 500,67
+$string['validnumberformats_help'] = '* regular numbers 13500.67, 13 500.67, 13500,67 or 13 500,67
 
-* if you use , as thousand separator *always* put the decimal . as in
- 13,500.67 : 13,500.
+* if your language pack settings (langconfig.php file) uses a comma (,) as thousand separator *always* put the decimal point (.) as in 13,500.67 : 13,500.
 
-* for exponent form, say 1.350067 * 10<sup>4</sup>, use
- 1.350067 E4 : 1.350067 E04 ';
+* for exponent form, say 1.350067 * 10<sup>4</sup>, use 1.350067 E4 : 1.350067 E04';
 
 $string['validnumbers'] = '13500.67, 13 500.67, 13,500.67, 13500,67, 13 500,67, 1.350067 E4 or 1.350067 E04';
 $string['xmustbenumeric'] = '{$a} must be a number.';
index 952462e..0e15605 100644 (file)
@@ -29,6 +29,6 @@ $string['pluginname'] = 'Random';
 $string['pluginname_help'] = 'A random question is not a question type as such, but is a way of inserting a randomly-chosen question from a specified category into an activity.';
 $string['pluginnameediting'] = 'Editing a random question';
 $string['randomqname'] = 'Random ({$a})';
-$string['randomqplusname'] = 'Random ({$a} and sub-categories)';
+$string['randomqplusname'] = 'Random ({$a} and subcategories)';
 $string['selectedby'] = '{$a->questionname} selected by {$a->randomname}';
 $string['selectmanualquestions'] = 'Random questions can use manually graded questions';
index 0a63ad7..b940dd2 100644 (file)
@@ -50,7 +50,7 @@ class qtype_truefalse_walkthrough_test extends qbehaviour_walkthrough_test_base
         $this->check_current_output(
                 $this->get_contains_question_text_expectation($tf),
                 $this->get_does_not_contain_feedback_expectation(),
-                new question_contains_tag_with_contents('h3',
+                new question_contains_tag_with_contents('h4',
                         get_string('questiontext', 'question')));
         $this->assertEquals(get_string('false', 'qtype_truefalse'),
                 $this->quba->get_right_answer_summary($this->slot));
diff --git a/repository/boxnet/cli/migrationv1.php b/repository/boxnet/cli/migrationv1.php
new file mode 100644 (file)
index 0000000..0187f41
--- /dev/null
@@ -0,0 +1,61 @@
+<?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/>.
+
+/**
+ * Box.net migration CLI script.
+ *
+ * @package    repository_boxnet
+ * @copyright  2013 Frédéric Massart
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define('CLI_SCRIPT', true);
+require(__DIR__ . '/../../../config.php');
+require_once($CFG->libdir . '/clilib.php');
+require_once($CFG->dirroot . '/repository/boxnet/locallib.php');
+
+// Now get cli options.
+list($options, $unrecognized) = cli_get_params(array(
+    'help' => false,
+    'confirm' => '',
+));
+
+if ($unrecognized) {
+    $unrecognized = implode("\n  ", $unrecognized);
+    cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
+}
+
+$help =
+"Box.net APIv1 migration tool.
+
+Options:
+-h, --help                 Print out this help
+--confirm                  Proceed with the migration
+
+Example:
+\$ sudo -u www-data /usr/bin/php admin/tool/boxnetv1migrationtool/cli/migrate.php --confirm=1
+";
+
+if ($options['help'] || empty($options['confirm'])) {
+    echo $help;
+    die();
+}
+
+if ($options['confirm']) {
+    mtrace("Box.net migration running...");
+    repository_boxnet_migrate_references_from_apiv1();
+}
+
diff --git a/repository/boxnet/db/upgrade.php b/repository/boxnet/db/upgrade.php
new file mode 100644 (file)
index 0000000..f30ebe2
--- /dev/null
@@ -0,0 +1,75 @@
+<?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/>.
+
+/**
+ * Upgrade.
+ *
+ * @package    repository_boxnet
+ * @copyright  2013 Frédéric Massart
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Upgrade function.
+ *
+ * @param int $oldversion the version we are upgrading from.
+ * @return bool result
+ */
+function xmldb_repository_boxnet_upgrade($oldversion) {
+    global $CFG, $DB;
+
+    $dbman = $DB->get_manager();
+
+    if ($oldversion < 2013110503) {
+        // Delete old user preferences containing auth tokens.
+        $DB->delete_records('user_preferences', array('name' => 'boxnet__auth_token'));
+        upgrade_plugin_savepoint(true, 2013110503, 'repository', 'boxnet');
+    }
+
+    if ($oldversion < 2013110700) {
+        require_once($CFG->dirroot . '/repository/lib.php');
+        require_once($CFG->dirroot . '/repository/boxnet/db/upgradelib.php');
+
+        $clientid = get_config('boxnet', 'clientid');
+        $clientsecret = get_config('boxnet', 'clientsecret');
+
+        // Only proceed if the repository hasn't been set for APIv2 yet.
+        if ($clientid === false && $clientsecret === false) {
+            $params = array();
+            $params['context'] = array();
+            $params['onlyvisible'] = false;
+            $params['type'] = 'boxnet';
+            $instances = repository::get_instances($params);
+
+            // Notify the admin about the migration process if they are using the repo.
+            if (!empty($instances)) {
+                repository_boxnet_admin_upgrade_notification();
+            }
+
+            // Hide the repository.
+            $repositorytype = repository::get_type_by_typename('boxnet');
+            if (!empty($repositorytype)) {
+                $repositorytype->update_visibility(false);
+            }
+        }
+
+        upgrade_plugin_savepoint(true, 2013110700, 'repository', 'boxnet');
+    }
+
+    return true;
+}
diff --git a/repository/boxnet/db/upgradelib.php b/repository/boxnet/db/upgradelib.php
new file mode 100644 (file)
index 0000000..c0cf9de
--- /dev/null
@@ -0,0 +1,55 @@
+<?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/>.
+
+/**
+ * Locallib.
+ *
+ * @package    repository_boxnet
+ * @copyright  2013 Frédéric Massart
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Send a message to the admin in regard with the APIv1 migration.
+ *
+ * @return void
+ */
+function repository_boxnet_admin_upgrade_notification() {
+    $admins = get_admins();
+
+    if (empty($admins)) {
+        return;
+    }
+    $a = new stdClass();
+    $a->docsurl = get_docs_url('Box.net_APIv1_migration');
+
+    foreach ($admins as $admin) {
+        $message = new stdClass();
+        $message->component         = 'moodle';
+        $message->name              = 'notices';
+        $message->userfrom          = get_admin();
+        $message->userto            = $admin;
+        $message->smallmessage      = get_string('apiv1migration_message_small', 'repository_boxnet');
+        $message->subject           = get_string('apiv1migration_message_subject', 'repository_boxnet');
+        $message->fullmessage       = get_string('apiv1migration_message_content', 'repository_boxnet', $a);
+        $message->fullmessagehtml   = get_string('apiv1migration_message_content', 'repository_boxnet', $a);
+        $message->fullmessageformat = FORMAT_PLAIN;
+        $message->notification      = 1;
+        message_send($message);
+    }
+}
index 27defbe..84c6592 100644 (file)
  */
 
 $string['apikey'] = 'API key';
+$string['apiv1migration_message_content'] = 'As part of the recent Moodle upgrade (2.6, 2.5.3, 2.4.7), the Box.net repository plugin has been disabled. To re-enable it, you need to re-configure it as described in the documentation {$a->docsurl}.';
+$string['apiv1migration_message_small'] = 'This plugin has been disabled, as it requires configuration as described in the documentation Box.net APIv1 migration.';
+$string['apiv1migration_message_subject'] = 'Important information regarding Box.net repository plugin';
 $string['boxnet:view'] = 'View box.net repository';
+$string['cannotcreatereference'] = 'Cannot create a reference, not enough permissions to share the file on Box.net.';
+$string['clientid'] = 'Client ID';
+$string['clientsecret'] = 'Client secret';
 $string['configplugin'] = 'Box.net configuration';
-$string['callbackurl'] = 'Redirect URL';
-$string['callbackurltext'] = '1. Visit <a href="http://www.box.net/developers/services">www.box.net/developers/services</a> again.
-2. Make sure you set the redirect URL of this box.net service to {$a}.';
-$string['callbackwarning'] = '1. Get a Box.net API from <a href="http://www.box.net/developers/services">www.box.net/developers/services</a> for this Moodle site.
-2. Enter the Box.net API key here, then click Save and then return to this page. You will see that Moodle has generated a redirect URL for you.
-3. Edit your Box.net details on the box.net website again and set the redirect URL.';
-
-$string['information'] = 'Get an API key from the <a href="http://www.box.net/developers/services">Box.net developer page</a> for your Moodle site.';
+$string['filesourceinfo'] = 'Box.net ({$a->fullname}): {$a->filename}';
+$string['information'] = 'Get a client ID and secret from the <a href="https://app.box.com/developers/services">Box.net developer page</a> for your Moodle site.';
 $string['invalidpassword'] = 'Invalid password';
+$string['migrationadvised'] = 'It appears that you were using Box.net with the API version 1, have you run the <a href="{$a}">migration tool</a> to convert the old references?';
+$string['migrationinfo'] = '<p>As part of the migration to the new API provided by Box.net, your file references have to be migrated. Unfortunately the reference system is not compatible with the API v2, so we are going to download them and convert them to real files.</p>
+<p>Please also be aware that the migration can <strong>take a very long time</strong>, depending on how many references are used, and how large their files are.</p>
+<p>You can run the migration tool by clicking the button below, or alternatively by executing the CLI script: repository/boxnet/cli/migrationv1.php.</p>
+<p>Find out more <a href="{$a->docsurl}">here</a>.</p>';
+$string['migrationtool'] = 'Box.net APIv1 migration tool';
 $string['nullfilelist'] = 'There are no files in this repository';
 $string['password'] = 'Password';
 $string['pluginname_help'] = 'Repository on Box.net';
 $string['pluginname'] = 'Box.net';
+$string['runthemigrationnow'] = 'Run the migration tool now';
 $string['saved'] = 'Box.net data saved';
 $string['shareurl'] = 'Share URL';
 $string['username'] = 'Username for Box.net';
+$string['warninghttps'] = 'Box.net requires your website to be using HTTPS in order for the repository to work.';
index 830b537..cde7327 100644 (file)
@@ -30,11 +30,28 @@ require_once($CFG->libdir . '/boxlib.php');
  *
  * @since 2.0
  * @package    repository_boxnet
- * @copyright  2009 Dongsheng Cai {@link http://dongsheng.org}
+ * @copyright  2010 Dongsheng Cai {@link http://dongsheng.org}
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 class repository_boxnet extends repository {
-    private $boxclient;
+
+    /** @const MANAGE_URL Manage URL. */
+    const MANAGE_URL = 'https://app.box.com/files';
+
+    /** @const SESSION_PREFIX Key used to store information in the session. */
+    const SESSION_PREFIX = 'repository_boxnet';
+
+    /** @var string Client ID */
+    protected $clientid;
+
+    /** @var string Client secret */
+    protected $clientsecret;
+
+    /** @var string Access token */
+    protected $accesstoken;
+
+    /** @var object Box.net object */
+    protected $boxnetclient;
 
     /**
      * Constructor
@@ -45,73 +62,108 @@ class repository_boxnet extends repository {
      */
     public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) {
         parent::__construct($repositoryid, $context, $options);
-        $this->api_key = $this->get_option('api_key');
-        $this->setting_prefix = 'boxnet_';
 
-        $this->auth_token = get_user_preferences($this->setting_prefix.'_auth_token', '');
-        $this->logged = false;
-        if (!empty($this->auth_token)) {
-            $this->logged = true;
-        }
-        // already logged
-        if(!empty($this->logged)) {
-            if(empty($this->boxclient)) {
-                $this->boxclient = new boxclient($this->api_key, $this->auth_token);
+        $clientid = get_config('boxnet', 'clientid');
+        $clientsecret = get_config('boxnet', 'clientsecret');
+        $returnurl = new moodle_url('/repository/repository_callback.php');
+        $returnurl->param('callback', 'yes');
+        $returnurl->param('repo_id', $this->id);
+        $returnurl->param('sesskey', sesskey());
+
+        $this->boxnetclient = new boxnet_client($clientid, $clientsecret, $returnurl, '');
+    }
+
+    /**
+     * Construct a breadcrumb from a path.
+     *
+     * @param string $fullpath Path containing multiple parts separated by slashes.
+     * @return array Array expected to be generated in {@link self::get_listing()}.
+     */
+    protected function build_breadcrumb($fullpath) {
+        $breadcrumb = array(array(
+            'name' => get_string('pluginname', 'repository_boxnet'),
+            'path' => ''
+        ));
+        $breadcrumbpath = '';
+        $crumbs = explode('/', $fullpath);
+        foreach ($crumbs as $crumb) {
+            if (empty($crumb)) {
+                // That is probably the root crumb, we've already added it.
+                continue;
             }
-        } else {
-            $this->boxclient = new boxclient($this->api_key);
+            list($unused, $tosplit) = explode(':', $crumb, 2);
+            if (strpos($tosplit, '|') !== false) {
+                list($id, $crumbname) = explode('|', $tosplit, 2);
+            } else {
+                $crumbname = $tosplit;
+            }
+            $breadcrumbpath .= '/' . $crumb;
+            $breadcrumb[] = array(
+                'name' => urldecode($crumbname),
+                'path' => $breadcrumbpath
+            );
         }
+        return $breadcrumb;
     }
 
     /**
-     * check if user logged
+     * Build a part of the path.
      *
-     * @return boolean
+     * This is used to construct the path that the user is currently browsing.
+     * It must contain a 'type', and a 'value'. Then it can also contain a
+     * 'name' which is very useful to prevent extra queries to get the name only.
+     *
+     * See {@link self::split_part} to extra the information from a part.
+     *
+     * @param string $type Type of part, typically 'folder' or 'search'.
+     * @param string $value The value of the part, eg. a folder ID or search terms.
+     * @param string $name The name of the part.
+     * @return string type:value or type:value|name
      */
-    public function check_login() {
-        return $this->logged;
+    protected function build_part($type, $value, $name = '') {
+        $return = $type . ':' . urlencode($value);
+        if ($name !== '') {
+            $return .= '|' . urlencode($name);
+        }
+        return $return;
     }
 
     /**
-     * reset auth token
+     * Extract information from a part of path.
      *
-     * @return string
+     * @param string $part value generated from {@link self::build_parth()}.
+     * @return array containing type, value and name.
      */
-    public function logout() {
-        // reset auth token
-        set_user_preference($this->setting_prefix . '_auth_token', '');
-        return $this->print_login();
+    protected function split_part($part) {
+        list($type, $tosplit) = explode(':', $part);
+        $name = '';
+        if (strpos($tosplit, '|') !== false) {
+            list($value, $name) = explode('|', $tosplit, 2);
+        } else {
+            $value = $tosplit;
+        }
+        return array($type, urldecode($value), urldecode($name));
     }
 
     /**
-     * Save settings
+     * check if user logged
      *
-     * @param array $options
-     * @return mixed
+     * @return boolean
      */
-    public function set_option($options = array()) {
-        if (!empty($options['api_key'])) {
-            set_config('api_key', trim($options['api_key']), 'boxnet');
-        }
-        unset($options['api_key']);
-        $ret = parent::set_option($options);
-        return $ret;
+    public function check_login() {
+        return $this->boxnetclient->is_logged_in();
     }
 
     /**
-     * Get settings
+     * reset auth token
      *
-     * @param string $config
-     * @return mixed
+     * @return string
      */
-    public function get_option($config = '') {
-        if($config==='api_key') {
-            return trim(get_config('boxnet', 'api_key'));
-        } else {
-            $options['api_key'] = trim(get_config('boxnet', 'api_key'));
+    public function logout() {
+        if ($this->check_login()) {
+            $this->boxnetclient->log_out();
         }
-        $options = parent::get_option($config);
-        return $options;
+        return $this->print_login();
     }
 
     /**
@@ -121,29 +173,33 @@ class repository_boxnet extends repository {
      * @return mixed
      */
     public function search($search_text, $page = 0) {
-        global $OUTPUT;
-        $list = array();
-        $ret  = array();
-        $tree = $this->boxclient->getAccountTree();
-        if (!empty($tree)) {
-            $filenames = $tree['file_name'];
-            $fileids   = $tree['file_id'];
-            $filesizes = $tree['file_size'];
-            $filedates = $tree['file_date'];
-            $fileicon  = $tree['thumbnail'];
-            foreach ($filenames as $n=>$v){
-                if(strstr(strtolower($v), strtolower($search_text)) !== false) {
-                    $list[] = array('title'=>$v,
-                            'size'=>$filesizes[$n],
-                            'date'=>$filedates[$n],
-                            'source'=>'https://www.box.com/api/1.0/download/'
-                                .$this->auth_token.'/'.$fileids[$n],
-                            'thumbnail' => $OUTPUT->pix_url(file_extension_icon($v, 90))->out(false));
-                }
+        return $this->get_listing($this->build_part('search', $search_text));
+    }
+
+    /**
+     * Downloads a repository file and saves to a path.
+     *
+     * @param string $ref reference to the file
+     * @param string $filename to save file as
+     * @return array
+     */
+    public function get_file($ref, $filename = '') {
+        $ref = unserialize(self::convert_to_valid_reference($ref));
+        $path = $this->prepare_file($filename);
+        if (!empty($ref->downloadurl)) {
+            $c = new curl();
+            $result = $c->download_one($ref->downloadurl, null, array('filepath' => $filename,
+                'timeout' => self::GETFILE_TIMEOUT, 'followlocation' => true));
+            $info = $c->get_info();
+            if ($result !== true || !isset($info['http_code']) || $info['http_code'] != 200) {
+                throw new moodle_exception('errorwhiledownload', 'repository', '', $result);
+            }
+        } else {
+            if (!$this->boxnetclient->download_file($ref->fileid, $path)) {
+                throw new moodle_exception('cannotdownload', 'repository');
             }
         }
-        $ret['list'] = array_filter($list, array($this, 'filter'));
-        return $ret;
+        return array('path' => $path);
     }
 
     /**
@@ -153,16 +209,65 @@ class repository_boxnet extends repository {
      * @param string $page
      * @return mixed
      */
-    public function get_listing($path = '/', $page = ''){
-        $list = array();
-        $ret  = array();
+    public function get_listing($fullpath = '', $page = ''){
+        global $OUTPUT;
+
+        $ret = array();
         $ret['list'] = array();
-        $tree = $this->boxclient->getfiletree($path);
-        $ret['manage'] = 'http://www.box.com/files';
-        $ret['path'] = array(array('name'=>'Root', 'path'=>0));
-        if(!empty($tree)) {
-            $ret['list'] = array_filter($tree, array($this, 'filter'));
+        $ret['manage'] = self::MANAGE_URL;
+        $ret['dynload'] = true;
+
+        $crumbs = explode('/', $fullpath);
+        $path = array_pop($crumbs);
+
+        if (empty($path)) {
+            $type = 'folder';
+            $pathid = 0;
+            $pathname = get_string('pluginname', 'repository_boxnet');
+        } else {
+            list($type, $pathid, $pathname) = $this->split_part($path);
+        }
+
+        $ret['path'] = $this->build_breadcrumb($fullpath);
+        $folders = array();
+        $files = array();
+
+        if ($type == 'search') {
+            $result = $this->boxnetclient->search($pathname);
+        } else {
+            $result = $this->boxnetclient->get_folder_items($pathid);
+        }
+        foreach ($result->entries as $item) {
+            if ($item->type == 'folder') {
+                $folders[$item->name . ':' . $item->id] = array(
+                    'title' => $item->name,
+                    'path' => $fullpath . '/' . $this->build_part('folder', $item->id, $item->name),
+                    'date' => strtotime($item->modified_at),
+                    'thumbnail' => $OUTPUT->pix_url(file_folder_icon(64))->out(false),
+                    'thumbnail_height' => 64,
+                    'thumbnail_width' => 64,
+                    'children' => array(),
+                    'size' => $item->size,
+                );
+            } else {
+                $files[$item->name . ':' . $item->id] = array(
+                    'title' => $item->name,
+                    'source' => $this->build_part('file', $item->id, $item->name),
+                    'size' => $item->size,
+                    'date' => strtotime($item->modified_at),
+                    'thumbnail' => $OUTPUT->pix_url(file_extension_icon($item->name, 64))->out(false),
+                    'thumbnail_height' => 64,
+                    'thumbnail_width' => 64,
+                    'author' => $item->owned_by->name,
+                );
+            }
         }
+
+        collatorlib::ksort($folders, core_collator::SORT_NATURAL);
+        collatorlib::ksort($files, core_collator::SORT_NATURAL);
+        $ret['list'] = array_merge($folders, $files);
+        $ret['list'] = array_filter($ret['list'], array($this, 'filter'));
+
         return $ret;
     }
 
@@ -172,24 +277,16 @@ class repository_boxnet extends repository {
      * @return array
      */
     public function print_login(){
-        $t = $this->boxclient->getTicket();
+        $url = $this->boxnetclient->get_login_url();
         if ($this->options['ajax']) {
+            $ret = array();
             $popup_btn = new stdClass();
             $popup_btn->type = 'popup';
-            $popup_btn->url = ' https://www.box.com/api/1.0/auth/' . $t['ticket'];
-
-            $ret = array();
+            $popup_btn->url = $url->out(false);
             $ret['login'] = array($popup_btn);
             return $ret;
         } else {
-            echo '<table>';
-            echo '<tr><td><label>'.get_string('username', 'repository_boxnet').'</label></td>';
-            echo '<td><input type="text" name="boxusername" /></td></tr>';
-            echo '<tr><td><label>'.get_string('password', 'repository_boxnet').'</label></td>';
-            echo '<td><input type="password" name="boxpassword" /></td></tr>';
-            echo '<input type="hidden" name="ticket" value="'.$t['ticket'].'" />';
-            echo '</table>';
-            echo '<input type="submit" value="'.get_string('enter', 'repository').'" />';
+            echo html_writer::link($url, get_string('login', 'repository'), array('target' => '_blank'));
         }
     }
 
@@ -199,15 +296,14 @@ class repository_boxnet extends repository {
      * @return array
      */
     public static function get_type_option_names() {
-        return array('api_key', 'pluginname');
+        return array('clientid', 'clientsecret', 'pluginname');
     }
 
     /**
-     * Store the auth token returned by box.net
+     * Catch the request token.
      */
     public function callback() {
-        $this->auth_token  = optional_param('auth_token', '', PARAM_TEXT);
-        set_user_preference($this->setting_prefix . '_auth_token',    $this->auth_token);
+        $this->boxnetclient->is_logged_in();
     }
 
     /**
@@ -219,41 +315,63 @@ class repository_boxnet extends repository {
     public static function type_config_form($mform, $classname = 'repository') {
         global $CFG;
         parent::type_config_form($mform);
-        $public_account = get_config('boxnet', 'public_account');
-        $api_key = get_config('boxnet', 'api_key');
-        if (empty($api_key)) {
-            $api_key = '';
-        }
+
+        $clientid = get_config('boxnet', 'clientid');
+        $clientsecret = get_config('boxnet', 'clientsecret');
         $strrequired = get_string('required');
-        $mform->addElement('text', 'api_key', get_string('apikey', 'repository_boxnet'), array('value'=>$api_key,'size' => '40'));
-        $mform->addRule('api_key', $strrequired, 'required', null, 'client');
-        $mform->setType('api_key', PARAM_RAW_TRIMMED);
-        $mform->addElement('static', null, '',  get_string('information','repository_boxnet'));
-
-        //retrieve the flickr instances
-        $params = array();
-        $params['context'] = array();
-        //$params['currentcontext'] = $this->context;
-        $params['onlyvisible'] = false;
-        $params['type'] = 'boxnet';
-        $instances = repository::get_instances($params);
-        if (empty($instances)) {
-            $callbackurl = get_string('callbackwarning', 'repository_boxnet');
-            $mform->addElement('static', null, '',  $callbackurl);
-        } else {
-            $instance = array_shift($instances);
-            $callbackurl = $CFG->wwwroot.'/repository/repository_callback.php?repo_id='.$instance->id;
-            $mform->addElement('static', 'callbackurl', '', get_string('callbackurltext', 'repository_boxnet', $callbackurl));
+
+        $mform->addElement('text', 'clientid', get_string('clientid', 'repository_boxnet'),
+            array('value' => $clientid, 'size' => '40'));
+        $mform->addRule('clientid', $strrequired, 'required', null, 'client');
+        $mform->setType('clientid', PARAM_RAW_TRIMMED);
+
+        $mform->addElement('text', 'clientsecret', get_string('clientsecret', 'repository_boxnet'),
+            array('value' => $clientsecret, 'size' => '40'));
+        $mform->addRule('clientsecret', $strrequired, 'required', null, 'client');
+        $mform->setType('clientsecret', PARAM_RAW_TRIMMED);
+
+        $mform->addElement('static', null, '',  get_string('information', 'repository_boxnet'));
+
+        if (strpos($CFG->wwwroot, 'https') !== 0) {
+            $mform->addElement('static', null, '',  get_string('warninghttps', 'repository_boxnet'));
+        }
+
+        if (get_config('boxnet', 'api_key')) {
+            $url = new moodle_url('/repository/boxnet/migrationv1.php');
+            $url = $url->out();
+            $mform->addElement('static', null, '', get_string('migrationadvised', 'repository_boxnet', $url));
         }
     }
 
     /**
-     * Box.net supports file linking and copying
+     * Box.net supports copied and links.
+     *
+     * Theoretically this API is ready for references, though it only works for
+     * Box.net Business accounts, but it is not enabled because we are not supporting it.
      *
      * @return int
      */
     public function supported_returntypes() {
-        return FILE_INTERNAL | FILE_EXTERNAL | FILE_REFERENCE;
+        return FILE_INTERNAL | FILE_EXTERNAL;
+    }
+
+    /**
+     * Convert a reference to the new reference style.
+     *
+     * While converting Box.net to APIv2 we introduced a new format for
+     * file references, see {@link self::get_file_reference()}. This function
+     * ensures that the format is always the same regardless of the whether
+     * the reference was from APIv1 or v2.
+     *
+     * @param mixed $reference File reference.
+     * @return stdClass Valid file reference.
+     */
+    public static function convert_to_valid_reference($reference) {
+        if (strpos($reference, 'http') === 0) {
+            // It is faster to check if the reference is a URL rather than trying to unserialize it.
+            $reference = serialize((object) array('downloadurl' => $reference, 'fileid' => '', 'filename' => '', 'userid' => ''));
+        }
+        return $reference;
     }
 
     /**
@@ -263,19 +381,56 @@ class repository_boxnet extends repository {
      * @return string file referece
      */
     public function get_file_reference($source) {
-        // Box.net returns a url.
-        return $source;
+        global $USER;
+        list($type, $fileid, $filename) = $this->split_part($source);
+        $reference = new stdClass();
+        $reference->fileid = $fileid;
+        $reference->filename = $filename;
+        $reference->userid = $USER->id;
+        $reference->downloadurl = '';
+        if (optional_param('usefilereference', false, PARAM_BOOL)) {
+            try {
+                $shareinfo = $this->boxnetclient->share_file($reference->fileid);
+            } catch (moodle_exception $e) {
+                throw new repository_exception('cannotcreatereference', 'repository_boxnet');
+            }
+            $reference->downloadurl = $shareinfo->download_url;
+        }
+        return serialize($reference);
     }
 
+    /**
+     * Get a link to the file.
+     *
+     * This returns the URL of the web view of the file. To generate this link the
+     * file must be shared.
+     *
+     * @param stdClass $reference Reference.
+     * @return string URL.
+     */
+    public function get_link($reference) {
+        $reference = unserialize(self::convert_to_valid_reference($reference));
+        $shareinfo = $this->boxnetclient->share_file($reference->fileid, false);
+        return $shareinfo->url;
+    }
+
+    /**
+     * Synchronize the references.
+     *
+     * @param stored_file $file Stored file.
+     * @return boolean
+     */
     public function sync_reference(stored_file $file) {
         if ($file->get_referencelastsync() + DAYSECS > time()) {
             // Synchronise not more often than once a day.
             return false;
         }
-        $c = new curl;
+        $c = new curl();
+        $reference = unserialize(self::convert_to_valid_reference($file->get_reference()));
+        $url = $reference->downloadurl;
         if (file_extension_in_typegroup($file->get_filename(), 'web_image')) {
             $path = $this->prepare_file('');
-            $result = $c->download_one($file->get_reference(), null, array('filepath' => $path, 'timeout' => self::SYNCIMAGE_TIMEOUT));
+            $result = $c->download_one($url, null, array('filepath' => $path, 'timeout' => self::SYNCIMAGE_TIMEOUT));
             $info = $c->get_info();
             if ($result === true && isset($info['http_code']) && $info['http_code'] == 200) {
                 $fs = get_file_storage();
@@ -284,7 +439,7 @@ class repository_boxnet extends repository {
                 return true;
             }
         }
-        $c->get($file->get_reference(), null, array('timeout' => self::SYNCIMAGE_TIMEOUT, 'followlocation' => true, 'nobody' => true));
+        $c->get($url, null, array('timeout' => self::SYNCIMAGE_TIMEOUT, 'followlocation' => true, 'nobody' => true));
         $info = $c->get_info();
         if (isset($info['http_code']) && $info['http_code'] == 200 &&
                 array_key_exists('download_content_length', $info) &&
@@ -306,31 +461,25 @@ class repository_boxnet extends repository {
      * @return string
      */
     public function get_reference_details($reference, $filestatus = 0) {
-        // Indicate it's from box.net repository + secure URL
-        $details = $this->get_name() . ': ' . $reference;
+        // Indicate it's from box.net repository.
+        $reference = unserialize(self::convert_to_valid_reference($reference));
         if (!$filestatus) {
-            return $details;
+            return $this->get_name() . ': ' . $reference->filename;
         } else {
-            return get_string('lostsource', 'repository', $details);
+            return get_string('lostsource', 'repository', $reference->filename);
         }
     }
 
     /**
-     * Return the source information
+     * Return the source information.
      *
-     * @param stdClass $url
+     * @param string $source Not the reference, just the source.
      * @return string|null
      */
-    public function get_file_source_info($url) {
+    public function get_file_source_info($source) {
         global $USER;
-        $array = explode('/', $url);
-        $fileid = array_pop($array);
-        $fileinfo = $this->boxclient->get_file_info($fileid, self::SYNCFILE_TIMEOUT);
-        if (!empty($fileinfo)) {
-            return 'Box ('. fullname($USER). '): '. (string)$fileinfo->file_name. ': '. $url;
-        } else {
-            return 'Box: '. $url;
-        }
+        list($type, $fileid, $filename) = $this->split_part($source);
+        return 'Box ('. fullname($USER) . '): ' . $filename;
     }
 
     /**
@@ -343,9 +492,7 @@ class repository_boxnet extends repository {
      * @param array $options additional options affecting the file serving
      */
     public function send_file($storedfile, $lifetime=null , $filter=0, $forcedownload=false, array $options = null) {
-        $ref = $storedfile->get_reference();
-        // Let box.net serve the file. It will return 'no such file' content if file not found
-        // also if file has the different name than alias, it will be returned with the box.net filename
-        header('Location: ' . $ref);
+        $ref = unserialize(self::convert_to_valid_reference($storedfile->get_reference()));
+        header('Location: ' . $ref->downloadurl);
     }
 }
diff --git a/repository/boxnet/locallib.php b/repository/boxnet/locallib.php
new file mode 100644 (file)
index 0000000..29ba307
--- /dev/null
@@ -0,0 +1,191 @@
+<?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/>.
+
+/**
+ * Box.net locallib.
+ *
+ * @package    repository_boxnet
+ * @copyright  2013 Frédéric Massart
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Migrate the references to local files.
+ *
+ * As the APIv1 is reaching its end of life on the 14th of Dec 2013, and we cannot
+ * convert the existing references to new references, we need to convert them
+ * to real files.
+ *
+ * @todo   Deprecate/remove this function after the 14th of December 2013.
+ * @return void
+ */
+function repository_boxnet_migrate_references_from_apiv1() {
+    global $DB;
+
+    // A string that the old references contain.
+    $apiv1signature = '/api/1.0/download/';
+
+    // Downloading the files could take a very long time!
+    @set_time_limit(0);
+
+    // Create directory to download temporary files.
+    $dir = make_temp_directory('download/repository_boxnet/');
+
+    // Create a dummy file for the broken files.
+    $fs = get_file_storage();
+    list($dummyhash, $dummysize, $unused) = $fs->add_string_to_pool('Lost reference from Box.net');
+
+    // Get the Box.net instances. There should be only one.
+    $sql = "SELECT i.id, i.typeid, r.id, r.type
+              FROM {repository} r, {repository_instances} i
+             WHERE i.typeid = r.id
+               AND r.type = :type";
+    $ids = $DB->get_fieldset_sql($sql, array('type' => 'boxnet'));
+    if (empty($ids)) {
+        // We did not find any instance of Box.net. Let's just ignore this migration.
+        mtrace('Could not find any instance of the repository, aborting migration...');
+        return;
+    }
+
+    // The next bit is copied from the function file_storage::instance_sql_fields()
+    // because it is private and there is nothing in file_storage that suits our needs here.
+    $filefields = array('contenthash', 'pathnamehash', 'contextid', 'component', 'filearea',
+        'itemid', 'filepath', 'filename', 'userid', 'filesize', 'mimetype', 'status', 'source',
+        'author', 'license', 'timecreated', 'timemodified', 'sortorder', 'referencefileid');
+    $referencefields = array('repositoryid' => 'repositoryid',
+        'reference' => 'reference',
+        'lastsync' => 'referencelastsync');
+    $fields = array();
+    $fields[] = 'f.id AS id';
+    foreach ($filefields as $field) {
+        $fields[] = "f.{$field}";
+    }
+    foreach ($referencefields as $field => $alias) {
+        $fields[] = "r.{$field} AS {$alias}";
+    }
+    $fields = implode(', ', $fields);
+
+    // We are not using repository::convert_references_to_local() or file_storage::get_external_files()
+    // because they would select too many records and load everything in memory as it is not using a recordset.
+    // Also, we filter the results not to get the draft area which should not be converted.
+    list($sqlfragment, $fragmentparams) = $DB->get_in_or_equal($ids, SQL_PARAMS_NAMED);
+    $sql = "SELECT " . $fields . "
+              FROM {files_reference} r
+              LEFT JOIN {files} f
+                   ON f.referencefileid = r.id
+             WHERE r.repositoryid $sqlfragment
+               AND f.referencefileid IS NOT NULL
+               AND NOT (f.component = :component
+               AND f.filearea = :filearea)";
+
+    // For each reference we download the file. Then we add it to the file pool and update the references.
+    // The reason why we are re-inventing the wheel here is because the current API ends up calling
+    // repository::get_file() which includes a download timeout. As we are trying our best to copy
+    // the files here, we want to ignre any timeout.
+    $filerecords = $DB->get_recordset_sql($sql, array_merge($fragmentparams, array('component' => 'user', 'filearea' => 'draft')));
+    $referenceids = array();
+    foreach ($filerecords as $filerecord) {
+        $file = $fs->get_file_instance($filerecord);
+        $reference = unserialize(repository_boxnet::convert_to_valid_reference($file->get_reference()));
+
+        if (empty($reference->downloadurl)) {
+            // Something is wrong...
+            mtrace('Skipping malformed reference (id: ' . $file->get_referencefileid() . ')');
+            continue;
+        } else if (strpos($reference->downloadurl, $apiv1signature) === false) {
+            // This is not an old reference, we are not supposed to work on thos.
+            mtrace('Skipping non APIv1 reference (id: ' . $file->get_referencefileid() . ')');
+            continue;
+        } else if (isset($referenceids[$file->get_referencefileid()])) {
+            // We have already worked on that reference, we skip any other file related to it.
+            // We cannot work on them here because they have been updated in the database but our
+            // recordset does not have those new values. They will be taken care of after this foreach.
+            continue;
+        }
+
+        mtrace('Starting migration of file reference ' . $file->get_referencefileid());
+
+        // Manually import the file to the file pool to prevent timeout limitations of the repository method get_file().
+        // We ignore the fact that the content of the file could exist locally because we want to synchronize the file
+        // now to prevent the repository to try to download the file as well.
+        $saveas = $dir . uniqid('', true) . '_' . time() . '.tmp';
+        $c = new curl();
+        $result = $c->download_one($reference->downloadurl, null, array('filepath' => $saveas, 'followlocation' => true));
+        $info = $c->get_info();
+        if ($result !== true || !isset($info['http_code']) || $info['http_code'] != 200) {
+            // There was a problem while trying to download the reference...
+            if ($fs->content_exists($file->get_contenthash()) && $file->get_contenthash() != sha1('')) {
+                // Fortunately we already had a local version of this reference, so we keep it. We have to
+                // set it synchronized or there is a risk that repository::sync_reference() will try to download
+                // the file again. We cannot use $file->get_contenthash() and $file->get_filesize() because they
+                // cause repository::sync_reference() to be called.
+                $file->set_synchronized($filerecord->contenthash, $filerecord->filesize);
+                mtrace('Could not download reference, using last synced file. (id: ' . $file->get_referencefileid() . ')');
+            } else {
+                // We don't know what the file was, but what can we do? In order to prevent a re-attempt to fetch the
+                // file in the next bit of this script (import_external_file()), we set a dummy content to the reference.
+                $file->set_synchronized($dummyhash, $dummysize);
+                mtrace('Could not download reference, dummy file used. (id: ' . $file->get_referencefileid() . ')');
+            }
+        } else {
+            try {
+                // The file has been downloaded, we add it to the file pool and synchronize
+                // all the files using this reference.
+                list($contenthash, $filesize, $unused) = $fs->add_file_to_pool($saveas);
+                $file->set_synchronized($contenthash, $filesize);
+            } catch (moodle_exception $e) {
+                // Something wrong happened...
+                mtrace('Something went wrong during sync (id: ' . $file->get_referencefileid() . ')');
+            }
+        }
+
+        // Log the reference IDs.
+        $referenceids[$file->get_referencefileid()] = $file->get_referencefileid();
+
+        // Now that the file is downloaded, we can loop over all the files using this reference
+        // to convert them to local copies. We have chosen to do that in this loop so that if the
+        // execution fails in the middle, we would not have to redownload the files again and again.
+        // By the way, we cannot use the records fetched in $filerecords because they will not be updated.
+        $sql = "SELECT " . $fields . "
+                  FROM {files} f
+                  LEFT JOIN {files_reference} r
+                       ON f.referencefileid = r.id
+                 WHERE f.referencefileid = :refid
+                   AND NOT (f.component = :component
+                   AND f.filearea = :filearea)";
+        $reffilerecords = $DB->get_recordset_sql($sql, array('component' => 'user', 'filearea' => 'draft',
+            'refid' => $file->get_referencefileid()));
+        foreach ($reffilerecords as $reffilerecord) {
+            $reffile = $fs->get_file_instance($reffilerecord);
+            try {
+                // Updating source to remove trace of APIv1 URL.
+                $reffile->set_source('Box APIv1 reference');
+            } catch (moodle_exception $e) {
+                // Do not fail for this lame reason...
+            }
+            try {
+                $fs->import_external_file($reffile);
+                mtrace('File using reference converted to local file (id: ' . $reffile->get_id() . ')');
+            } catch (moodle_exception $e) {
+                // Oh well... we tried what we could!
+                $reffile->delete_reference();
+                mtrace('Failed to convert file from reference to local file, sorry! (id: ' . $reffile->get_id() . ')');
+            }
+        }
+    }
+
+    mtrace('Migration finished.');
+}
diff --git a/repository/boxnet/migrationv1.php b/repository/boxnet/migrationv1.php
new file mode 100644 (file)
index 0000000..30d80d1
--- /dev/null
@@ -0,0 +1,69 @@
+<?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/>.
+
+/**
+ * Box.net APIv1 migration tool.
+ *
+ * This tool is intended to migrate the references of the APIv1 of Box.net
+ * as this API is going end of life in December 14th 2013. As there is no
+ * way to support the references in the APIv2, we will convert those old
+ * references to local files.
+ *
+ * This operation can take a long time depending on the number of references
+ * used and their size.
+ *
+ * @package    repository_boxnet
+ * @copyright  2013 Frédéric Massart
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @todo       Deprecate/remove this tool after the 14th of December 2013.
+ */
+
+define('NO_OUTPUT_BUFFERING', true);
+
+require_once(__DIR__ . '/../../config.php');
+require_once($CFG->libdir . '/adminlib.php');
+require_once($CFG->dirroot . '/repository/boxnet/locallib.php');
+
+require_login();
+require_capability('moodle/site:config', context_system::instance());
+
+$title = get_string('migrationtool', 'repository_boxnet');
+$PAGE->set_context(context_system::instance());
+$PAGE->set_pagelayout('maintenance');
+$PAGE->set_title($title);
+$PAGE->set_heading($title);
+$PAGE->set_url(new moodle_url('/repository/boxnet/migrationv1.php'));
+$PAGE->navbar->add($title);
+
+$confirm = optional_param('confirm', false, PARAM_BOOL);
+
+echo $OUTPUT->header();
+echo $OUTPUT->heading('Reference migration tool');
+
+if ($confirm && confirm_sesskey()) {
+    echo html_writer::start_tag('pre', array());
+    repository_boxnet_migrate_references_from_apiv1();
+    echo html_writer::end_tag('pre', array());
+} else {
+    $a = new stdClass();
+    $a->docsurl = get_docs_url('Box.net_APIv1_migration');
+    echo html_writer::tag('p', get_string('migrationinfo', 'repository_boxnet', $a));
+    $execurl = new moodle_url('/repository/boxnet/migrationv1.php', array('confirm' => 1, 'sesskey' => sesskey()));
+    $button = new single_button($execurl, get_string('runthemigrationnow', 'repository_boxnet'));
+    echo $OUTPUT->render($button);
+}
+
+echo $OUTPUT->footer();
index 82308ed..6c45fe0 100644 (file)
@@ -41,8 +41,11 @@ class repository_boxnet_generator extends testing_repository_generator {
      */
     protected function prepare_type_record(array $record) {
         $record = parent::prepare_type_record($record);
-        if (!isset($record['api_key'])) {
-            $record['api_key'] = 'api_key';
+        if (!isset($record['clientid'])) {
+            $record['clientid'] = 'clientid';
+        }
+        if (!isset($record['clientsecret'])) {
+            $record['clientsecret'] = 'clientsecret';
         }
         return $record;
     }
index ec97183..4b3ab0a 100644 (file)
@@ -26,6 +26,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2013110500;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version   = 2013110700;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2013110500;        // Requires this Moodle version
 $plugin->component = 'repository_boxnet'; // Full name of the plugin (used for diagnostics)
index 42523b6..3e3a3ba 100644 (file)
@@ -27,6 +27,6 @@ $string['configplugin'] = 'Configuration for recent files repository';
 $string['recentfilesnumber'] = 'Number of recent files';
 $string['emptyfilelist'] = 'There are no files to show';
 $string['notitle'] = 'notitle';
-$string['recent:view'] = 'View recent files repsitory plugin';
+$string['recent:view'] = 'View recent files repository plugin';
 $string['pluginname_help'] = 'Files recently used by current user';
 $string['pluginname'] = 'Recent files';
index 016f2fb..1bb8cb0 100644 (file)
@@ -18,6 +18,18 @@ class theme_anomaly_core_renderer extends core_renderer {
         if (empty($bc->blockinstanceid) || !strip_tags($bc->title)) {
             $bc->collapsible = block_contents::NOT_HIDEABLE;
         }
+        if (!empty($bc->blockinstanceid)) {
+            $bc->attributes['data-instanceid'] = $bc->blockinstanceid;
+        }
+        $skiptitle = strip_tags($bc->title);
+        if ($bc->blockinstanceid && !empty($skiptitle)) {
+            $bc->attributes['aria-labelledby'] = 'instance-'.$bc->blockinstanceid.'-header';
+        } else if (!empty($bc->arialabel)) {
+            $bc->attributes['aria-label'] = $bc->arialabel;
+        }
+        if ($bc->dockable) {
+            $bc->attributes['data-dockable'] = 1;
+        }
         if ($bc->collapsible == block_contents::HIDDEN) {
             $bc->add_class('hidden');
         }
@@ -25,7 +37,6 @@ class theme_anomaly_core_renderer extends core_renderer {
             $bc->add_class('block_with_controls');
         }
 
-        $skiptitle = strip_tags($bc->title);
         if (empty($skiptitle)) {
             $output = '';
             $skipdest = '';
index 46603ac..25a4031 100644 (file)
@@ -368,7 +368,7 @@ input#id_externalurl {direction:ltr;}
 .groupmanagementtable #addselect_wrapper label {font-weight: normal;}
 .dir-rtl .groupmanagementtable p {text-align: right;}
 #group-usersummary {width: 14em;}
-.groupselector {margin-top: 3px;margin-bottom: 3px;}
+.groupselector {margin-top: 3px;margin-bottom: 3px;display: inline-block;}
 
 /**
  * Login
@@ -736,39 +736,23 @@ body.tag .managelink {padding: 5px;}
 .corelightbox {background-color:#CCC;position:absolute;top:0;left:0;width:100%;height:100%;text-align:center;}
 .corelightbox img {position:fixed;top:50%; left: 50%;}
 
-.mod-indent-1 {margin-left:30px;}
-.mod-indent-2 {margin-left:60px;}
-.mod-indent-3 {margin-left:90px;}
-.mod-indent-4 {margin-left:120px;}
-.mod-indent-5 {margin-left:150px;}
-.mod-indent-6 {margin-left:180px;}
-.mod-indent-7 {margin-left:210px;}
-.mod-indent-8 {margin-left:240px;}
-.mod-indent-9 {margin-left:270px;}
-.mod-indent-10 {margin-left:300px;}
-.mod-indent-11 {margin-left:330px;}
-.mod-indent-12 {margin-left:360px;}
-.mod-indent-13 {margin-left:390px;}
-.mod-indent-14 {margin-left:420px;}
+.mod-indent {display:table-cell;}
+.mod-indent-1    {width:30px;}
+.mod-indent-2    {width:60px;}
+.mod-indent-3    {width:90px;}
+.mod-indent-4    {width:120px;}
+.mod-indent-5    {width:150px;}
+.mod-indent-6    {width:180px;}
+.mod-indent-7    {width:210px;}
+.mod-indent-8    {width:240px;}
+.mod-indent-9    {width:270px;}
+.mod-indent-10   {width:300px;}
+.mod-indent-11   {width:330px;}
+.mod-indent-12   {width:360px;}
+.mod-indent-13   {width:390px;}
+.mod-indent-14   {width:420px;}
 .mod-indent-15,
-.mod-indent-huge {margin-left:420px;}
-
-.dir-rtl .mod-indent-1 {margin-right:30px;margin-left:0;}
-.dir-rtl .mod-indent-2 {margin-right:60px;margin-left:0;}
-.dir-rtl .mod-indent-3 {margin-right:90px;margin-left:0;}
-.dir-rtl .mod-indent-4 {margin-right:120px;margin-left:0;}
-.dir-rtl .mod-indent-5 {margin-right:150px;margin-left:0;}
-.dir-rtl .mod-indent-6 {margin-right:180px;margin-left:0;}
-.dir-rtl .mod-indent-7 {margin-right:210px;margin-left:0;}
-.dir-rtl .mod-indent-8 {margin-right:240px;margin-left:0;}
-.dir-rtl .mod-indent-9 {margin-right:270px;margin-left:0;}
-.dir-rtl .mod-indent-10 {margin-right:300px;margin-left:0;}
-.dir-rtl .mod-indent-11 {margin-right:330px;margin-left:0;}
-.dir-rtl .mod-indent-12 {margin-right:360px;margin-left:0;}
-.dir-rtl .mod-indent-13 {margin-right:390px;margin-left:0;}
-.dir-rtl .mod-indent-14 {margin-right:420px;margin-left:0;}
-.dir-rtl .mod-indent-15,
-.dir-rtl .mod-indent-huge {margin-right:420px;margin-left:0;}
+.mod-indent-huge {width:420px;}
 
 .dir-rtl .mform .fitem .felement {margin-right: 16%;margin-left:auto;text-align: right;}
 .dir-rtl .mform .fitem .felement input[name=email],
@@ -1138,6 +1122,9 @@ sup {vertical-align: super;}
 .moodle-dialogue-base .moodle-dialogue.moodle-dialogue-tooltip {
     z-index: 3001;
 }
+.moodle-dialogue-base .moodle-dialogue.moodle-dialogue-tooltip .moodle-dialogue-bd {
+    overflow: auto;
+}
 
 /* Question Bank - Question Chooser "Close" button */
 #page-question-edit.dir-rtl a.container-close {right:auto;left:6px;}
index 17f8deb..e7cc6f9 100644 (file)
     right: 0;
 }
 
-.section .activity .mod-indent {
+.section .activity .mod-indent-outer {
+    display: table;
     padding-left: 24px;
 }
 
-.dir-rtl .section .activity .mod-indent {
+.dir-rtl .section .activity .mod-indent-outer {
     padding-left: auto;
     padding-right: 24px;
 }
 }
 
 .editing .sitetopic .section .activity .activityinstance,
-.editing .course-content .section .activity .activityinstance {
+.editing .course-content .section .activity .activityinstance,
+.editing .sitetopic .section .activity .contentwithoutlink,
+.editing .course-content .section .activity .contentwithoutlink {
     padding-right: 200px;
-    height: 2em;
-    display: table-cell;
 }
 
 .dir-rtl.editing .sitetopic .section .activity .activityinstance,
-.dir-rtl.editing .course-content .section .activity .activityinstance {
+.dir-rtl.editing .course-content .section .activity .activityinstance,
+.dir-rtl.editing .sitetopic .section .activity .contentwithoutlink,
+.dir-rtl.editing .course-content .section .activity .contentwithoutlink {
     padding-left: 200px;
-    padding-right: auto;
+    padding-right: initial;
+}
+
+.sitetopic .section .activity .activityinstance,
+.course-content .section .activity .activityinstance,
+.sitetopic .section .activity .contentwithoutlink,
+.course-content .section .activity .contentwithoutlink {
+    padding-right: 32px;
+    height: 2em;
+    display: table-cell;
+}
+
+.dir-rtl .sitetopic .section .activity .activityinstance,
+.dir-rtl .course-content .section .activity .activityinstance,
+.dir-rtl .sitetopic .section .activity .contentwithoutlink,
+.dir-rtl .course-content .section .activity .contentwithoutlink {
+    padding-left: 32px;
+    padding-right: initial;
 }
 
 .course-content .section .activity .filler {
 .sitetopic .section .activity .availabilityinfo,
 .sitetopic .section .activity .contentafterlink,
 .course-content .section .activity .availabilityinfo,
-.course-content .section .activity .contentafterlink { margin-top: 0.5em; margin-left: 30px;}
+.course-content .section .activity .contentafterlink { margin-top: 0.5em;}
 .dir-rtl .sitetopic .section .activity .availabilityinfo,
 .dir-rtl .sitetopic .section .activity .contentafterlink,
 .dir-rtl .course-content .section .activity .availabilityinfo,
@@ -299,7 +319,6 @@ li.section.hidden span.commands a.editing_show {cursor:default;}
 span.editinstructions {
     position: absolute;
     top: 0px;
-    left: 0px;
     margin-top: -22px;
     margin-left: 30px;
     line-height: 16px;
@@ -358,7 +377,7 @@ input.titleeditor { vertical-align: text-bottom; }
 #course-category-listings .listing-actions > * {display:inline-block;line-height:2.2em;}
 #course-category-listings .listing-actions > .moodle-actionmenu {display:inline-block;}
 .coursecat-management-header .moodle-actionmenu[data-enhanced].show .menu a,
-#course-category-listings .listing-actions > .moodle-actionmenu .menu a {padding-left:1em;}
+#course-category-listings .listing-actions > .moodle-actionmenu .menu a {padding: 4px 1em;}
 #course-category-listings .listing-actions .iconsmall {margin-left:0.5em;}
 #course-category-listings ul.ml {list-style: none;margin:1em 0;}
 #course-category-listings ul.ml ul.ml {margin:0;}
@@ -372,7 +391,7 @@ input.titleeditor { vertical-align: text-bottom; }
 #course-category-listings li[data-selected='1'].highlight > div {background-color:#ddffaa;}
 #course-category-listings li+li > div,
 #course-category-listings li:first-child > div {border-top-color:#f7f7f9;}
-#course-category-listings li .tree-icon {vertical-align:text-top;margin-right:0.5em;width:12px;height:12px;}
+#course-category-listings li .tree-icon {margin-right:0.5em;width:12px;height:12px;}
 .dir-rtl #course-category-listings li .tree-icon {margin-left:0.5em;}
 #course-category-listings li[data-selected='1'] > div {background-color:#FFFFD8;border-top-color: #e1e1e8;border-bottom-color:#f7f7f9;}
 #course-category-listings li[data-selected='1'] li:first-of-type > div,
@@ -381,10 +400,12 @@ input.titleeditor { vertical-align: text-bottom; }
 #course-category-listings > div > div > ul.ml > li:first-child > div {border-top:0;}
 
 #course-category-listings .listing-actions .moodle-actionmenu:not([data-enhanced]) li {line-height:normal;}
+#course-category-listings .listing-actions .moodle-actionmenu:not([data-enhanced]) > .menubar li,
 #course-category-listings .listing-actions .moodle-actionmenu:not([data-enhanced]) > .menubar a,
 #course-category-listings .listing-actions .moodle-actionmenu:not([data-enhanced]) > .menu .menu-action-text {display:inline-block;}
 #course-category-listings .listing-actions .moodle-actionmenu:not([data-enhanced]) > .menubar a {color:inherit;}
-#course-category-listings .listing-actions .moodle-actionmenu:not([data-enhanced]) > .menubar a > img {display:none;}
+#course-category-listings .listing-actions .moodle-actionmenu:not([data-enhanced]) > .menubar a > img,
+#course-category-listings .listing-actions .moodle-actionmenu:not([data-enhanced]) > .menubar .caret {display:none;}
 
 .jsenabled #course-category-listings .moodle-actionmenu[data-enhance] .toggle-display img {
     width: auto;
@@ -394,13 +415,14 @@ input.titleeditor { vertical-align: text-bottom; }
     padding-right: 4px;
 }
 .jsenabled #course-category-listings .moodle-actionmenu[data-enhance] .toggle-display.textmenu .caret {
-    margin-top: 10px;
+    vertical-align:text-top;
 }
 
 #course-category-listings .item-actions {margin-right:1em;display:inline-block;display:initial;}
-#course-category-listings .item-actions img {margin: 0 4px;vertical-align:inherit;}
+#course-category-listings .item-actions img {margin: 0 4px;}
+#course-category-listings .item-actions .menubar img {vertical-align:inherit;}
 #course-category-listings .item-actions .menu img {max-width:none;width:12px;}
-#course-category-listings .item-actions .menu a {padding:4px 1em 4px 4px;}
+#course-category-listings .item-actions.show .menu a {padding:4px 1em 4px 4px;}
 
 #course-category-listings li .tree-icon {margin-left:0;}
 #course-category-listings li li .tree-icon {margin-left:1em;}
@@ -420,13 +442,14 @@ input.titleeditor { vertical-align: text-bottom; }
 .dir-rtl #course-category-listings li li li li li li li .tree-icon {margin-right:5em;}
 .dir-rtl #course-category-listings li li li li li li li li .tree-icon {margin-right:5.5em;}
 
-#course-listing .listitem .drag-handle {margin-right:0.5em;}
+#course-listing .listitem .drag-handle {display:none;}
+.jsenabled #course-listing .listitem .drag-handle {margin-right:0.5em;display:inline-block;cursor:pointer;}
 #course-listing .listitem .categoryname {display:inline-block;margin-left:1em;color:#a1a1a8;}
 #course-listing .listitem .coursename {display:inline-block;}
 
 #category-listing .course-count {color:#a1a1a8;margin-right:2em;min-width:3.5em;display:inline-block;}
 #category-listing .listitem.collapsed > ul.ml {display: none;}
-#category-listing .course-count .smallicon {width:0.8em;height:0.8em;vertical-align:middle;margin:0 0.3em;}
+#category-listing .course-count .smallicon {width:0.8em;height:0.8em;margin:0 0.3em;}
 
 #category-listing .listitem > div > .ba-checkbox {vertical-align:middle;width:2.2em;text-align:center;margin:-1px 0;padding-top:2px;margin-right:0.5em;}
 .dir-rtl #category-listing .listitem > div > .ba-checkbox {margin-left:0.5em;margin-right:0.5em;}
@@ -461,8 +484,10 @@ input.titleeditor { vertical-align: text-bottom; }
 
 #course-category-listings .detail-pair {border-bottom:1px solid #e1e1e8;margin:0 1em;}
 #course-category-listings .detail-pair > * {display:inline-block;line-height:2.2em;}
-#course-category-listings .detail-pair .pair-key {font-weight:bold;text-align:right;}
+#course-category-listings .detail-pair .pair-key {font-weight:bold;text-align:left;}
+.dir-rtl #course-category-listings .detail-pair .pair-key {text-align:right;}
 #course-category-listings .detail-pair .pair-key span {margin-right: 1em;display:block;}
+.dir-rtl #course-category-listings .detail-pair .pair-key span {margin-right: 0;}
 #course-category-listings .detail-pair:last-child {border-bottom-width:0;}
 
 #course-category-listings .bulk-actions .detail-pair > * {display:block;width:100%;}
@@ -472,6 +497,7 @@ input.titleeditor { vertical-align: text-bottom; }
 #course-category-listings .select-a-category .notifymessage,
 #course-category-listings .select-a-category .alert {margin: 1em;}
 
+.dir-rtl.jsenabled .moodle-actionmenu[data-enhanced] .menu.align-tr-br {right: inherit;}
 /** Management header styling **/
 .coursecat-management-header {vertical-align:middle;}
 .coursecat-management-header h2 {display:inline-block;text-align:left;}
index e4175af..2fda102 100644 (file)
@@ -20,7 +20,7 @@ body.has_dock {margin-left:30px;}
 #dockeditempanel {min-width:200px;position:relative;z-index:12000;left:100%;}
 #dockeditempanel.dockitempanel_hidden {display:none;}
 #dockeditempanel .dockeditempanel_content {background-color:#fff;border:1px solid #000;z-index:12050;}
-#dockeditempanel .dockeditempanel_bd {overflow:auto;width:auto;}
+#dockeditempanel .dockeditempanel_bd {overflow:auto;width:100%;}
 #dockeditempanel .dockeditempanel_bd .block_docked {margin:10px;}
 #dockeditempanel .dockeditempanel_bd .block_navigation .block_tree li {overflow:visible;}
 #dockeditempanel .dockeditempanel_hd {border-bottom:1px solid #000;}
@@ -44,4 +44,4 @@ body.has_dock {margin-left:30px;}
 body.dir-rtl.has_dock  {margin-left: 0px; margin-right: 30px}
 
 /* Test span used to calculate positioning of docked item labels */
-.transform-test-node { position:absolute;line-height:normal; }
\ No newline at end of file
+.transform-test-node { position:absolute;line-height:normal; }
index 2fa3898..acb32c5 100644 (file)
@@ -32,8 +32,8 @@ background:#E2E2E2;filter:progid:DXImageTransform.Microsoft.gradient(startColors
 .dir-rtl .file-picker .fp-repo-area {border-left:1px solid #BBBBBB;border-right:none;float:right;}
 .file-picker .fp-repo-items {float:left;width:693px;}
 .dir-rtl .file-picker .fp-repo-items {float:right;}
-.file-picker .fp-navbar {background:#F2F2F2;min-height:48px;border-bottom:1px solid #BBBBBB;padding:5px 8px;}
-.file-picker .fp-content {background:#FFFFFF;clear:both;overflow:auto;height:432px;}
+.file-picker .fp-navbar {background:#F2F2F2;min-height:40px;border-bottom:1px solid #BBBBBB;}
+.file-picker .fp-content {background:#FFFFFF;clear:both;overflow:auto;height:452px;}
 .filepicker.moodle-dialogue-fullscreen .file-picker .fp-content {width:100%;}
 
 .file-picker .fp-content-loading {height:100%;width:100%;display:table;text-align:center;}
@@ -70,14 +70,14 @@ background:#E2E2E2;filter:progid:DXImageTransform.Microsoft.gradient(startColors
 .dir-rtl .fp-toolbar {float:right;}
 .fp-toolbar.empty {display:none;}
 .fp-toolbar .disabled {display:none;}
-.file-picker .fp-toolbar div, .fp-navbar .filemanager-toolbar .fp-toolbar div {float:left;margin:9px 0 9px 9px;background:#FFFFFF;border:1px solid #CCCCCC;border-bottom:1px solid #B3B3B3;border-radius:4px;width:40px;height:30px;}
+.file-picker .fp-toolbar div, .fp-navbar .filemanager-toolbar .fp-toolbar div {float:left;margin:4px 0 4px 4px;background:#FFFFFF;border:1px solid #CCCCCC;border-bottom:1px solid #B3B3B3;border-radius:4px;width:30px;height:30px;}
 .fp-toolbar div {display:block;}
-.fp-toolbar a {display:block;height:30px;width:40px;}
+.fp-toolbar a {display:block;height:30px;width:30px;}
 .fp-toolbar a:hover {background-image:radial-gradient(ellipse at center, #ffffff 60%,#dfdfdf 100%);background-color:#ebebeb;}
 .fp-toolbar a:active {background-image:radial-gradient(ellipse at center, #ffffff 40%,#dfdfdf 100%);background-color:#dfdfdf;}
-.dir-rtl .fp-navbar .filemanager-toolbar .fp-toolbar div {margin:9px 9px 9px 0;}
+.dir-rtl .fp-navbar .filemanager-toolbar .fp-toolbar div {margin:4px 4px 4px 0;}
 .file-picker .fp-toolbar div.disabled {display:none;}
-.fp-toolbar img {vertical-align:-15%;margin:7px 12px;}
+.fp-toolbar img {vertical-align:-15%;margin:7px;}
 .file-picker .fp-toolbar .fp-tb-search {width:235px;height:30px;}
 .file-picker .fp-toolbar .fp-tb-search .fp-def-search {border:0;background:transparent;margin:0;padding:0;width:235px;}
 .dir-rtl .file-picker .fp-toolbar .fp-tb-search {width:242px;}
@@ -86,14 +86,13 @@ background:#E2E2E2;filter:progid:DXImageTransform.Microsoft.gradient(startColors
 .dir-rtl .fp-toolbar img {vertical-align:-35%;}
 .dir-rtl .file-picker .fp-viewbar, .dir-rtl .fp-navbar .filemanager-toolbar .fp-viewbar {float:left;}
 .dir-rtl .file-picker .fp-viewbar {margin-left:0;}
-.file-picker .fp-viewbar, .fp-navbar .filemanager-toolbar .fp-viewbar {float:right;margin:9px; background:white;border:1px solid #CCCCCC;border-radius:4px;border-bottom:1px solid #B3B3B3;height:30px;}
-.fp-viewbar .fp-vb-icons, .fp-viewbar .fp-vb-details, .fp-viewbar .fp-vb-tree {width:40px;height:30px;display:block;float:left;border-right:1px solid #CCCCCC;}
+.file-picker .fp-viewbar, .fp-navbar .filemanager-toolbar .fp-viewbar {float:right;margin:4px; background:white;border:1px solid #CCCCCC;border-radius:4px;border-bottom:1px solid #B3B3B3;height:30px;}
+.fp-viewbar .fp-vb-icons, .fp-viewbar .fp-vb-details, .fp-viewbar .fp-vb-tree {width:30px;height:30px;display:block;float:left;border-right:1px solid #CCCCCC;}
 .fp-viewbar a.fp-vb-icons {border-radius:4px 0 0 4px;}
 .fp-viewbar .fp-vb-tree {border-right:0;border-radius:0 4px 4px 0;}
-.fp-viewbar a img {margin:7px 12px;}
-.fp-viewbar a:hover {background-image:radial-gradient(ellipse at center, #ffffff 60%,#dfdfdf 100%);background-color:#ebebeb;}
-.fp-viewbar a:active {background-image:radial-gradient(ellipse at center, #ffffff 40%,#dfdfdf 100%);background-color:#dfdfdf;}
-.fp-viewbar a.checked {background-color:#dfdfdf;}
+.fp-viewbar a img {margin:7px;}
+.fp-viewbar a.checked:hover, .fp-viewbar a:hover {background-image:radial-gradient(ellipse at center, #ffffff 60%,#dfdfdf 100%);background-color:#ebebeb;}
+.fp-viewbar a.checked, .fp-viewbar a:active {background-image:radial-gradient(ellipse at center, #ffffff 40%,#dfdfdf 100%);background-color:#dfdfdf;}
 .fp-viewbar.disabled a {opacity:.45;background:none;cursor:default;}
 .file-picker .fp-clear-left {clear:left;}
 
@@ -284,7 +283,7 @@ a.ygtvspacer:hover {color:transparent;text-decoration:none;}
  */
 .fp-restrictions{text-align:right;}
 .filemanager .fp-navbar {background:#F2F2F2;border-top:1px solid #BBBBBB;border-left:1px solid #BBBBBB;border-right:1px solid #BBBBBB;}
-.filemanager-toolbar {min-height:50px;}
+.filemanager-toolbar {min-height:40px;}
 .fp-pathbar {border-top:1px solid #BBBBBB;padding:5px 8px 1px;min-height:20px;}
 
 .filemanager .fp-pathbar.empty {display:none;}
index dff73ab..a304806 100644 (file)
@@ -51,7 +51,7 @@ body.path-question-type .fitem_fgroup .accesshide {font: inherit;left: 0;positio
 .dir-rtl .que {text-align: right;}
 
 .que .info {float: left;width: 7em;padding:0.5em;margin-bottom: 1.8em;background: #eee;}
-.que h2.no {margin: 0;font-size: 0.8em;line-height: 1;}
+.que h3.no {margin: 0;font-size: 0.8em;line-height: 1;}
 .que span.qno {font-size: 1.5em;font-weight:bold;}
 .que .info > div {font-size: 0.8em;margin-top: 0.7em;}
 .que .info .questionflag.editable {cursor:pointer;}
index 4819985..57aa020 100644 (file)
@@ -434,8 +434,11 @@ a.skip:active {
 .groupselector {
     margin-top: 3px;
     margin-bottom: 3px;
+    display: inline-block;
+}
+.groupselector label {
+    display: inline-block;
 }
-
 // Login
 .loginbox {
     margin: 15px;
@@ -1153,113 +1156,60 @@ body.tag .managelink {
     top: 50%;
     left: 50%;
 }
+
+.mod-indent-outer {
+    display: table;
+}
+.mod-indent {
+    display: table-cell;
+}
 .mod-indent-1 {
-    margin-left: 30px;
+    width: 30px;
 }
 .mod-indent-2 {
-    margin-left: 60px;
+    width: 60px;
 }
 .mod-indent-3 {
-    margin-left: 90px;
+    width: 90px;
 }
 .mod-indent-4 {
-    margin-left: 120px;
+    width: 120px;
 }
 .mod-indent-5 {
-    margin-left: 150px;
+    width: 150px;
 }
 .mod-indent-6 {
-    margin-left: 180px;
+    width: 180px;
 }
 .mod-indent-7 {
-    margin-left: 210px;
+    width: 210px;
 }
 .mod-indent-8 {
-    margin-left: 240px;
+    width: 240px;
 }
 .mod-indent-9 {
-    margin-left: 270px;
+    width: 270px;
 }
 .mod-indent-10 {
-    margin-left: 300px;
+    width: 300px;
 }
 .mod-indent-11 {
-    margin-left: 330px;
+    width: 330px;
 }
 .mod-indent-12 {
-    margin-left: 360px;
+    width: 360px;
 }
 .mod-indent-13 {
-    margin-left: 390px;
+    width: 390px;
 }
 .mod-indent-14 {
-    margin-left: 420px;
+    width: 420px;
 }
 .mod-indent-15,
 .mod-indent-huge {
-    margin-left: 420px;
-}
-.dir-rtl .mod-indent-1 {
-    margin-right: 30px;
-    margin-left: 0;
-}
-.dir-rtl .mod-indent-2 {
-    margin-right: 60px;
-    margin-left: 0;
-}
-.dir-rtl .mod-indent-3 {
-    margin-right: 90px;
-    margin-left: 0;
-}
-.dir-rtl .mod-indent-4 {
-    margin-right: 120px;
-    margin-left: 0;
-}
-.dir-rtl .mod-indent-5 {
-    margin-right: 150px;
-    margin-left: 0;
-}
-.dir-rtl .mod-indent-6 {
-    margin-right: 180px;
-    margin-left: 0;
-}
-.dir-rtl .mod-indent-7 {
-    margin-right: 210px;
-    margin-left: 0;
-}
-.dir-rtl .mod-indent-8 {
-    margin-right: 240px;
-    margin-left: 0;
-}
-.dir-rtl .mod-indent-9 {
-    margin-right: 270px;
-    margin-left: 0;
-}
-.dir-rtl .mod-indent-10 {
-    margin-right: 300px;
-    margin-left: 0;
-}
-.dir-rtl .mod-indent-11 {
-    margin-right: 330px;
-    margin-left: 0;
-}
-.dir-rtl .mod-indent-12 {
-    margin-right: 360px;
-    margin-left: 0;
-}
-.dir-rtl .mod-indent-13 {
-    margin-right: 390px;
-    margin-left: 0;
-}
-.dir-rtl .mod-indent-14 {
-    margin-right: 420px;
-    margin-left: 0;
-}
-.dir-rtl .mod-indent-15,
-.dir-rtl .mod-indent-huge {
-    margin-right: 420px;
-    margin-left: 0;
+    width: 420px;
 }
+
 /* Audio player size in 'block' mode (can only change width, height is hardcoded in JS) */
 .resourcecontent .mediaplugin_mp3 object {
     height: 25px;
@@ -1618,6 +1568,10 @@ body#page-lib-editor-tinymce-plugins-moodlemedia-preview {
 
 .moodle-dialogue-base .moodle-dialogue.moodle-dialogue-tooltip {
     z-index: 3001;
+
+    .moodle-dialogue-bd {
+        overflow: auto;
+    }
 }
 
 /* Question Bank - Question Chooser "Close" button */
index 0ee6428..9e0bcef 100644 (file)
@@ -57,7 +57,7 @@
             top: 0;
         }
 
-        .mod-indent {
+        .mod-indent-outer {
             /**
              * Add appropriate padding such that nothing overlaps the
              * absolute positioned move icon.
             top: 0;
         }
 
+        .contentwithoutlink,
         .activityinstance {
+
+            min-width: 40%;
+            display: table-cell;
+            padding-right: 4px;
+            min-height: 2em;
+
             .dimmed {
                 img.activityicon {
                   opacity: 0.5;
             right: 100%;
         }
 
-        .mod-indent {
+        .mod-indent-outer {
             /**
              * Add appropriate padding such that nothing overlaps the
              * absolute positioned move icon.
              */
-            padding-left: auto;
+            padding-left: initial;
             padding-right: 32px;
         }
 
             left: 0;
             right: auto;
         }
+
+        .contentwithoutlink,
+        .activityinstance {
+            padding-left: 4px;
+            padding-right: initial;
+        }
     }
 }
 
 .editing {
     .section {
         .activity {
+            .contentwithoutlink,
             .activityinstance {
-                min-width: 40%;
-                display: table-cell;
                 padding-right: 200px;
-                min-height: 2em;
             }
         }
     }
 .dir-rtl.editing {
     .section {
         .activity {
+            .contentwithoutlink,
             .activityinstance {
                 padding-left: 200px;
                 padding-right: 0;
     white-space: nowrap;
     display: inline;
 }
-.section .activity.modtype_label .commands {
-    margin-left: 40%;
-    padding-left: .2em;
-}
 .section .activity.modtype_label.label {
     font-weight: normal;
     padding: .2em;
@@ -841,9 +849,6 @@ span.editinstructions {
                 padding-left:1rem;
             }
         }
-        .iconsmall {
-            vertical-align:text-bottom;
-        }
         .moodle-actionmenu:not([data-enhanced]) {
             li {line-height:normal;}
             > .menubar a {
@@ -852,6 +857,9 @@ span.editinstructions {
                 > img {
                     display:none;
                 }
+                .caret {
+                    display: none;
+                }
             }
             > .menu .menu-action-text {
                 display:inline-block;
@@ -873,8 +881,9 @@ span.editinstructions {
             }
         }
         .tree-icon {
-            vertical-align:text-top;
             margin: 2px 6px 0 0;
+            width:12px;
+            vertical-align:inherit;
         }
         &[data-selected='1'] {
             > div {
@@ -913,8 +922,11 @@ span.editinstructions {
         display:initial;
         img {
             margin: 0 4px;
+            height:12px;
+            padding: 0;
+            vertical-align: inherit;
         }
-        .menu {
+        &.show .menu {
             a {
                 padding:4px 1em 4px 4px;
             }
@@ -923,6 +935,9 @@ span.editinstructions {
                 max-width:none;
             }
         }
+        .menu-action-text {
+            vertical-align: inherit;
+        }
     }
 
     .listitem {
@@ -997,10 +1012,6 @@ span.editinstructions {
             .coursename {
                 display:inline-block;
             }
-            .drag-handle {
-                display:inline-block;
-                margin: 0 6px 0 0;
-            }
             > div {
                 padding-left:1rem;
             }
@@ -1010,7 +1021,6 @@ span.editinstructions {
           display: none;
         }
         .bulk-action-checkbox {
-            vertical-align:middle;
             margin:-2px 6px 0 0;
         }
     }
@@ -1021,7 +1031,6 @@ span.editinstructions {
         .listitem {
             > div {
                 > .ba-checkbox {
-                    vertical-align:middle;
                     width:2.2em;
                     text-align:center;
                     margin:-1px 0.5em 0 0;
@@ -1047,14 +1056,12 @@ span.editinstructions {
             min-width:3.5em;
             display:inline-block;
             .smallicon {
-                width:0.8rem;
-                height:0.8rem;
-                vertical-align:middle;
-                margin:0 0.3rem;
+                width:12px;
+                margin-left:4px;
+                vertical-align: inherit;
             }
         }
         .bulk-action-checkbox {
-            vertical-align:middle;
             margin-right: -3px;
         }
         .category-listing > ul > .listitem:first-child {
@@ -1118,6 +1125,15 @@ span.editinstructions {
     }
 }
 
+#course-category-listings #course-listing .listitem .drag-handle {
+    display: none;
+}
+.jsenabled #course-category-listings #course-listing .listitem .drag-handle {
+    display:inline-block;
+    margin: 0 6px 0 0;
+    cursor:pointer;
+}
+
 .dir-rtl #course-category-listings {
     #category-listing,
     #course-listing {
@@ -1198,12 +1214,19 @@ span.editinstructions {
         }
     }
   .detail-pair {
+        > * {
+            float: right;
+            margin-right: 0;
+        }
         .pair-key {
             span {
                 margin-right:0;
                 margin-left: 0;
             }
         }
+        .pair-value {
+            margin-right: 0.5em;
+        }
     }
 }
 
index 1336d72..0c99cab 100644 (file)
 .file-picker .fp-navbar {
     background: #F2F2F2;
     border-bottom: 1px solid #BBBBBB;
-    min-height: 48px;
+    min-height: 40px;
 }
 .file-picker .fp-navbar .fp-viewbar {
-    margin: 9px;
+    margin: 4px;
 }
 
 .file-picker .fp-content {
     background: #FFFFFF;
     clear: both;
     overflow: auto;
-    height: 432px;
+    height: 452px;
 }
 .filepicker.moodle-dialogue-fullscreen .file-picker .fp-content {
     width: 100%;
     text-align: right;
 }
 .dir-rtl .file-picker .fp-toolbar {
-    padding: 9px;
+    padding: 4px;
 }
 .dir-rtl .file-picker .fp-list {
     text-align: right;
 .fp-toolbar div {
     display: block;
     float: left;
-    margin-right: 9px;
+    margin-right: 4px;
 }
 .dir-rtl .fp-toolbar div {
     display: block;
     float: right;
-    margin-left: 9px;
+    margin-left: 4px;
     margin-right: 0px;
 }
 .fp-toolbar img {
     background: white;
 }
 .fp-repo-items fp-viewbar {
-    margin: 9px;
+    margin: 4px;
 }
 .dir-rtl .fp-toolbar img {
     vertical-align: -35%;
 }
 
 .fp-viewbar a {
-    width: 40px;
+    width: 30px;
     height: 30px;
     border-right: 1px solid #CCC;
     display: block;
     float:left;
 }
+.fp-viewbar a.checked:hover,
 .fp-viewbar a:hover {
     background-image: radial-gradient(ellipse at center, #ffffff 60%,#dfdfdf 100%);
     background-color: #ebebeb;
 }
 
+.fp-viewbar a.checked,
 .fp-viewbar a:active {
     background-image: radial-gradient(ellipse at center, #ffffff 40%,#dfdfdf 100%);
     background-color: #dfdfdf;
     border-radius: 0 4px 4px 0;
 }
 .fp-viewbar a img {
-    margin: 7px 12px;
-}
-
-.fp-viewbar a.checked {
-    background-color: #dfdfdf;
+    margin: 7px;
 }
 
 .fp-viewbar.disabled a {
@@ -794,7 +792,7 @@ a.ygtvspacer:hover {
     border-bottom: none;
 }
 .filemanager-toolbar{
-    padding: 9px;
+    padding: 4px;
     overflow: hidden;
 }
 .fp-pathbar {
@@ -804,7 +802,7 @@ a.ygtvspacer:hover {
 }
 
 .file-picker .fp-toolbar {
-    padding: 9px;
+    padding: 4px;
 }
 
 .fp-toolbar .fp-btn-add,
@@ -819,7 +817,7 @@ a.ygtvspacer:hover {
     border-bottom: 1px solid #B3B3B3;
     border-radius: 4px;
     background: white;
-    width: 40px;
+    width: 30px;
     height: 30px;
 }
 
@@ -842,7 +840,7 @@ a.ygtvspacer:hover {
 .fp-tb-refresh a
 {
     display: block;
-    width: 40px;
+    width: 30px;
     height: 30px;
     border-radius: 4px;
 }
@@ -854,7 +852,7 @@ a.ygtvspacer:hover {
 .fp-tb-manage img,
 .fp-tb-logout img,
 .fp-tb-refresh img {
-    margin: 7px 12px;
+    margin: 7px;
 }
 
 .filemanager .fp-pathbar.empty {
index c6e5109..094381c 100644 (file)
@@ -165,7 +165,7 @@ body.path-question-type .fitem_fgroup .accesshide {
     border: 1px solid darken(spin(@grayLighter, -10), 7%);
     .border-radius(2px);
 }
-.que h2.no {
+.que h3.no {
     margin: 0;
     font-size: 0.8em;
     line-height: 1;
index b72b2d7..12fb987 100644 (file)
@@ -1,4 +1,4 @@
-.layout-option-noheader #page-header,.layout-option-nonavbar #page-navbar,.layout-option-nofooter #page-footer,.layout-option-nocourseheader .course-content-header,.layout-option-nocoursefooter .course-content-footer{display:none}.empty-region-side-pre #block-region-side-pre,.empty-region-side-post #block-region-side-post{display:none}.empty-region-side-post #region-bs-main-and-pre.span9{width:100%}.empty-region-side-pre #region-main{float:none;width:100%}.empty-region-side-post.used-region-side-pre #region-main.span8{width:74.46808510638297%;*width:74.41489361702126%}.empty-region-side-post.used-region-side-pre #block-region-side-pre.span4{width:23.404255319148934%;*width:23.351063829787233%}.empty-region-side-post #region-bs-main-and-post.span9 #region-main.span8{width:100%}.dir-ltr,.mdl-left,.dir-rtl .mdl-right{text-align:left}.dir-rtl,.mdl-right,.dir-rtl .mdl-left{text-align:right}#add,#remove,.centerpara,.mdl-align{text-align:center}a.dimmed,a.dimmed:link,a.dimmed:visited,a.dimmed_text,a.dimmed_text:link,a.dimmed_text:visited,.dimmed_text,.dimmed_text a,.dimmed_text a:link,.dimmed_text a:visited,.usersuspended,.usersuspended a,.usersuspended a:link,.usersuspended a:visited,.dimmed_category,.dimmed_category a{color:#999}.activity.label .dimmed_text{opacity:.5;filter:alpha(opacity=50)}.unlist,.unlist li,.inline-list,.inline-list li,.block .list,.block .list li,.section li.activity,.section li.movehere,.tabtree li{padding:0;margin:0;list-style:none}.inline,.inline-list li{display:inline}.notifytiny{font-size:10.5px}.notifytiny li,.notifytiny td{font-size:100%}.red,.notifyproblem{color:#b94a48}.green,.notifysuccess{color:#468847}.reportlink{text-align:right}a.autolink.glossary:hover{cursor:help}.collapsibleregioncaption{white-space:nowrap}.collapsibleregioncaption img{vertical-align:middle}.jsenabled .hiddenifjs{display:none}.visibleifjs{display:none}.jsenabled .visibleifjs{display:inline}.jsenabled .collapsibleregion{overflow:hidden}.jsenabled .collapsed .collapsibleregioninner{visibility:hidden}.collapsible-actions{display:none;text-align:right}.dir-rtl .collapsible-actions{text-align:left}.jsenabled .collapsible-actions{display:block}.collapsible-actions .collapseexpand{padding-left:20px;background:url([[pix:t/collapsed]]) 2px center no-repeat}.dir-rtl .collapsible-actions .collapseexpand{padding-right:20px;padding-left:0;background:url([[pix:t/collapsed_rtl]]) right center no-repeat}.collapsible-actions .collapse-all,.dir-rtl .collapsible-actions .collapse-all{background-image:url([[pix:t/expanded]])}.yui-overlay .yui-widget-bd{position:relative;top:0;left:0;z-index:1;padding:2px 5px;color:#000;background-color:#ffee69;border:1px solid #a6982b;border-top-color:#d4c237}.clearer{display:block;height:1px;padding:0;margin:0;clear:both;background:transparent;border-width:0}.bold,.warning,.errorbox .title,.pagingbar .title,.pagingbar .thispage{font-weight:bold}img.resize{width:1em;height:1em}.block img.resize,.breadcrumb img.resize{width:.8em;height:.9em}img.icon{width:16px;height:16px;padding-right:6px;vertical-align:text-bottom}.dir-rtl img.icon{padding-right:0;padding-left:6px}img.iconsmall{width:12px;height:12px;margin-right:3px;vertical-align:middle}img.iconhelp,.helplink img{width:16px;height:16px;padding-left:3px;vertical-align:text-bottom}h1 img.iconhelp,h1 img.icon,h2 img.iconhelp,h2 img.icon,h3 img.iconhelp,h3 img.icon,h4 img.iconhelp,h4 img.icon,h5 img.iconhelp,h5 img.icon,h6 img.iconhelp,h6 img.icon{padding:4px;vertical-align:middle}.dir-rtl img.iconhelp,.dir-rtl .helplink img{padding-right:3px;padding-left:0}img.iconlarge{width:24px;height:24px;vertical-align:middle}img.iconsort{padding-left:.3em;margin-bottom:.15em;vertical-align:text-bottom}.dir-rtl img.iconsort{padding-right:.3em;padding-left:0}img.icontoggle{width:50px;height:17px;vertical-align:middle}img.iconkbhelp{width:49px;height:17px}img.icon-pre,.dir-rtl img.icon-post{padding-right:3px;padding-left:0}img.icon-post,.dir-rtl img.icon-pre{padding-right:0;padding-left:3px}.boxaligncenter{margin-right:auto;margin-left:auto}.boxalignright{margin-right:0;margin-left:auto}.boxalignleft{margin-right:auto;margin-left:0}.boxwidthnarrow{width:30%}.boxwidthnormal{width:50%}.boxwidthwide{width:80%}.headermain{font-weight:bold}#maincontent{display:block;height:1px;overflow:hidden}img.uihint{cursor:help}#addmembersform table{margin-right:auto;margin-left:auto}.flexible th{white-space:nowrap}table.flexible .emptyrow{display:none}img.emoticon{width:15px;height:15px;vertical-align:middle}form.popupform,form.popupform div{display:inline}.arrow_button input{overflow:hidden}.action-icon img.smallicon{margin:0 .3em;vertical-align:text-bottom}.no-overflow{padding-bottom:1px;overflow:auto}.pagelayout-report .no-overflow{overflow:visible}.no-overflow>.generaltable{margin-bottom:0}.accesshide{position:absolute;left:-10000px;font-size:1em;font-weight:normal}.dir-rtl .accesshide{top:-30000px;left:auto}span.hide,div.hide{display:none}a.skip-block,a.skip{position:absolute;top:-1000em;font-size:.85em;text-decoration:none}a.skip-block:focus,a.skip-block:active,a.skip:focus,a.skip:active{position:static;display:block}.skip-block-to{display:block;height:1px;overflow:hidden}.addbloglink{text-align:center}.blog_entry .audience{padding-right:4px;text-align:right}.blog_entry .tags{margin-top:15px}.blog_entry .tags .action-icon img.smallicon{width:16px;height:16px}.blog_entry .content{margin-left:43px}#page-group-index #groupeditform{text-align:center}#doc-contents h1{margin:1em 0 0 0}#doc-contents ul{width:90%;padding:0;margin:0}#doc-contents ul li{list-style-type:none}.groupmanagementtable td{vertical-align:top}.groupmanagementtable #existingcell,.groupmanagementtable #potentialcell{width:42%}.groupmanagementtable #buttonscell{width:16%}.groupmanagementtable #buttonscell p.arrow_button input{width:auto;min-width:80%;margin:0 auto}.groupmanagementtable #removeselect_wrapper,.groupmanagementtable #addselect_wrapper{width:100%}.groupmanagementtable #removeselect_wrapper label,.groupmanagementtable #addselect_wrapper label{font-weight:normal}.dir-rtl .groupmanagementtable p{text-align:right}#group-usersummary{width:14em}.groupselector{margin-top:3px;margin-bottom:3px}.loginbox{margin:15px;overflow:visible}.loginbox.twocolumns{margin:15px}.loginbox h2,.loginbox .subcontent{padding:10px;margin:5px;text-align:center}.loginbox .loginpanel .desc{padding:0;margin:0;margin-top:15px;margin-bottom:5px}.loginbox .signuppanel .subcontent{text-align:left}.dir-rtl .loginbox .signuppanel .subcontent{text-align:right}.loginbox .loginsub{margin-right:0;margin-left:0}.loginbox .guestsub,.loginbox .forgotsub,.loginbox .potentialidps{margin:5px 12%}.loginbox .potentialidps .potentialidplist{margin-left:40%}.loginbox .potentialidps .potentialidplist div{text-align:left}.loginbox .loginform{margin-top:1em;text-align:left}.loginbox .loginform .form-label{float:left;width:44%;text-align:right;white-space:nowrap;direction:rtl}.dir-rtl .loginbox .loginform .form-label{float:left;width:44%;text-align:right;white-space:nowrap;direction:ltr}.loginbox .loginform .form-input{float:right;width:55%}.loginbox .loginform .form-input input{width:6em}.loginbox .signupform{margin-top:1em;text-align:center}.loginbox.twocolumns .loginpanel,.loginbox.twocolumns .signuppanel{display:block;float:left;width:48%;min-height:30px;padding:0;padding-bottom:2000px;margin:0;margin-bottom:-2000px;margin-left:2.76243%;border:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.loginbox .potentialidp .smallicon{margin:0 .3em;vertical-align:text-bottom}.notepost{margin-bottom:1em}.notepost .userpicture{float:left;margin-right:5px}.notepost .content,.notepost .footer{clear:both}.notesgroup{margin-left:20px}.path-my .coursebox .overview{margin:15px 30px 10px 30px}.path-my .coursebox .info{float:none;margin:0}.mod_introbox{padding:10px}table.mod_index{width:100%}.comment-ctrl{display:none;padding:0;margin:0;font-size:12px}.comment-ctrl h5{padding:5px;margin:0}.comment-area{max-width:400px;padding:5px}.comment-area textarea{width:100%;overflow:auto}.comment-area .fd{text-align:right}.comment-meta span{color:gray}.comment-link img{vertical-align:text-bottom}.comment-list{padding:0;margin:0;overflow:auto;font-size:11px;list-style:none}.comment-list li{position:relative;padding:.3em;margin:2px;margin-bottom:5px;clear:both;list-style:none}.comment-list li.first{display:none}.comment-paging{text-align:center}.comment-paging .pageno{padding:2px}.comment-paging .curpage{border:1px solid #CCC}.comment-message .picture{float:left;width:20px}.dir-rtl .comment-message .picture{float:right}.comment-message .text{padding:0;margin:0}.comment-message .text p{padding:0;margin:0 18px 0 0}.comment-delete{position:absolute;top:0;right:0;margin:.3em}.dir-rtl .comment-delete{position:absolute;right:auto;left:0;margin:.3em}.comment-delete-confirm{width:5em;padding:2px;text-align:center;background:#eee}.comment-container{float:left;margin:4px}.comment-report-selectall{display:none}.comment-link{display:none}.jsenabled .comment-link{display:block}.jsenabled .showcommentsnonjs{display:none}.jsenabled .comment-report-selectall{display:inline}.completion-expired{background:#f2dede}.completion-expected{font-size:10.5px}.completion-sortchoice,.completion-identifyfield{font-size:10.5px;vertical-align:bottom}.completion-progresscell{text-align:right}.completion-expired .completion-expected{font-weight:bold}#page-tag-coursetags_edit .coursetag_edit_centered{position:relative;width:600px;margin:20px auto}#page-tag-coursetags_edit .coursetag_edit_row{clear:both}#page-tag-coursetags_edit .coursetag_edit_row .coursetag_edit_left{float:left;width:50%;text-align:right}#page-tag-coursetags_edit .coursetag_edit_row .coursetag_edit_right{margin-left:50%}#page-tag-coursetags_edit .coursetag_edit_input3{display:none}#page-tag-coursetags_more .coursetag_more_large{font-size:120%}#page-tag-coursetags_more .coursetag_more_small{font-size:80%}#page-tag-coursetags_more .coursetag_more_link{font-size:80%}#tag-description,#tag-blogs{width:100%}#tag-management-box{margin-bottom:10px;line-height:20px}#tag-user-table{width:100%;padding:3px;clear:both}#tag-user-table{*zoom:1}#tag-user-table:before,#tag-user-table:after{display:table;line-height:0;content:""}#tag-user-table:after{clear:both}img.user-image{width:100px;height:100px}#small-tag-cloud-box{width:300px;margin:0 auto}#big-tag-cloud-box{float:none;width:600px;margin:0 auto}ul#tag-cloud-list{padding:5px;margin:0;list-style:none}ul#tag-cloud-list li{display:inline;margin:0;list-style-type:none}#tag-search-box{margin:10px auto;text-align:center}#tag-search-results-container{width:100%;padding:0}#tag-search-results{display:block;float:left;width:60%;padding:0;margin:15px 20% 0 20%}#tag-search-results li{float:left;width:30%;padding-right:1%;padding-left:1%;line-height:20px;text-align:left;list-style:none}span.flagged-tag,span.flagged-tag a{color:#b94a48}table#tag-management-list{width:100%;text-align:left}table#tag-management-list td,table#tag-management-list th{padding:4px;text-align:left;vertical-align:middle}.tag-management-form{text-align:center}#relatedtags-autocomplete-container{width:100%;min-height:4.6em;margin-right:auto;margin-left:auto}#relatedtags-autocomplete{position:relative;display:block;width:60%;margin-right:auto;margin-left:auto}#relatedtags-autocomplete .yui-ac-content{position:absolute;left:20%;z-index:9050;width:420px;overflow:hidden;background:#fff;border:1px solid #404040}#relatedtags-autocomplete .ysearchquery{position:absolute;right:10px;z-index:10;color:#808080}#relatedtags-autocomplete .yui-ac-shadow{position:absolute;z-index:9049;width:100%;margin:.3em;background:#a0a0a0}#relatedtags-autocomplete ul{width:100%;padding:0;margin:0;list-style-type:none}#relatedtags-autocomplete li{padding:0 5px;white-space:nowrap;cursor:default}#relatedtags-autocomplete li.yui-ac-highlight{background:#ffc}h2.tag-heading,div#tag-description,div#tag-blogs,body.tag .managelink{padding:5px}.tag_cloud .s20{font-size:1.5em;font-weight:bold}.tag_cloud .s19{font-size:1.5em}.tag_cloud .s18{font-size:1.4em;font-weight:bold}.tag_cloud .s17{font-size:1.4em}.tag_cloud .s16{font-size:1.3em;font-weight:bold}.tag_cloud .s15{font-size:1.3em}.tag_cloud .s14{font-size:1.2em;font-weight:bold}.tag_cloud .s13{font-size:1.2em}.tag_cloud .s12,.tag_cloud .s11{font-size:1.1em;font-weight:bold}.tag_cloud .s10,.tag_cloud .s9{font-size:1.1em}.tag_cloud .s8,.tag_cloud .s7{font-size:1em;font-weight:bold}.tag_cloud .s6,.tag_cloud .s5{font-size:1em}.tag_cloud .s4,.tag_cloud .s3{font-size:.9em;font-weight:bold}.tag_cloud .s2,.tag_cloud .s1{font-size:.9em}.tag_cloud .s0{font-size:.8em}#webservice-doc-generator td{text-align:left;border:0 solid black}.smartselect{position:absolute}.smartselect .smartselect_mask{background-color:#fff}.smartselect ul{padding:0;margin:0}.smartselect ul li{list-style:none}.smartselect .smartselect_menu{margin-right:5px}.safari .smartselect .smartselect_menu{margin-left:2px}.smartselect .smartselect_menu,.smartselect .smartselect_submenu{display:none;background-color:#FFF;border:1px solid #000}.smartselect .smartselect_menu.visible,.smartselect .smartselect_submenu.visible{display:block}.smartselect .smartselect_menu_content ul li{position:relative;padding:2px 5px}.smartselect .smartselect_menu_content ul li a{color:#333;text-decoration:none}.smartselect .smartselect_menu_content ul li a.selectable{color:inherit}.smartselect .smartselect_submenuitem{background-image:url([[pix:moodle|t/collapsed]]);background-position:100%;background-repeat:no-repeat}.smartselect.spanningmenu .smartselect_submenu{position:absolute;top:-1px;left:100%}.smartselect.spanningmenu .smartselect_submenu a{padding-right:16px;white-space:nowrap}.smartselect.spanningmenu .smartselect_menu_content ul li a.selectable:hover{text-decoration:underline}.smartselect.compactmenu .smartselect_submenu{position:relative;z-index:1010;display:none;margin:2px -3px;margin-left:10px;border-width:0}.smartselect.compactmenu .smartselect_submenu.visible{display:block}.smartselect.compactmenu .smartselect_menu{z-index:1000;overflow:hidden}.smartselect.compactmenu .smartselect_submenu .smartselect_submenu{z-index:1020}.smartselect.compactmenu .smartselect_submenuitem:hover>.smartselect_menuitem_label{font-weight:bold}#page-admin-registration-register .registration_textfield{width:300px}.userenrolment{width:100%;border-collapse:collapse}.userenrolment td{height:41px;padding:0}.userenrolment .subfield{margin-right:5px}.userenrolment .col_userdetails .subfield_picture{float:left}.userenrolment .col_lastseen{width:150px}.userenrolment .col_role{width:262px}.userenrolment .col_role .roles{margin-right:30px}.userenrolment .col_role .role{float:left;padding:3px;margin:3px}.dir-rtl .userenrolment .col_role .role{float:right}.userenrolment .col_role .role a{margin-left:3px;cursor:pointer}.userenrolment .col_role .addrole{float:right;width:18px;height:18px;margin:3px;text-align:center;background-color:#dff0d8;border:1px solid #d6e9c6}.userenrolment .col_role .addrole img{vertical-align:baseline}.userenrolment .hasAllRoles .col_role .addrole{display:none}.userenrolment .col_group .groups{margin-right:30px}.userenrolment .col_group .group{float:left;padding:3px;margin:3px;white-space:nowrap}.userenrolment .col_group .group a{margin-left:3px;cursor:pointer}.userenrolment .col_group .addgroup{float:right;width:18px;height:18px;margin:3px;text-align:center}.userenrolment .col_group .addgroup a img{vertical-align:bottom}.userenrolment .col_enrol .enrolment{float:left;padding:3px;margin:3px}.userenrolment .col_enrol .enrolment a{float:right;margin-left:3px}#page-enrol-users .enrol_user_buttons{float:right}#page-enrol-users.dir-rtl .enrol_user_buttons{float:left}#page-enrol-users .enrol_user_buttons .enrolusersbutton{display:inline;margin-left:1em}#page-enrol-users .enrol_user_buttons .enrolusersbutton div,#page-enrol-users .enrol_user_buttons .enrolusersbutton form{display:inline}#page-enrol-users .enrol_user_buttons .enrolusersbutton input{padding-right:6px;padding-left:6px}#page-enrol-users.dir-rtl .col_userdetails .subfield_picture{float:right}#page-enrol-users .user-enroller-panel .uep-search-results .user .details{width:237px}.dir-rtl .headermain{float:right}.dir-rtl .headermenu{float:left}.dir-rtl .loginbox .loginform .form-label{float:right;text-align:left}.dir-rtl .loginbox .loginform .form-input{text-align:right}.dir-rtl .yui3-menu-hidden{left:0}#page-admin-roles-define.dir-rtl #rolesform .felement{margin-right:180px}#page-message-edit.dir-rtl table.generaltable th.c0{text-align:right}.corelightbox{position:absolute;top:0;left:0;width:100%;height:100%;text-align:center;background-color:#CCC}.corelightbox img{position:fixed;top:50%;left:50%}.mod-indent-1{margin-left:30px}.mod-indent-2{margin-left:60px}.mod-indent-3{margin-left:90px}.mod-indent-4{margin-left:120px}.mod-indent-5{margin-left:150px}.mod-indent-6{margin-left:180px}.mod-indent-7{margin-left:210px}.mod-indent-8{margin-left:240px}.mod-indent-9{margin-left:270px}.mod-indent-10{margin-left:300px}.mod-indent-11{margin-left:330px}.mod-indent-12{margin-left:360px}.mod-indent-13{margin-left:390px}.mod-indent-14{margin-left:420px}.mod-indent-15,.mod-indent-huge{margin-left:420px}.dir-rtl .mod-indent-1{margin-right:30px;margin-left:0}.dir-rtl .mod-indent-2{margin-right:60px;margin-left:0}.dir-rtl .mod-indent-3{margin-right:90px;margin-left:0}.dir-rtl .mod-indent-4{margin-right:120px;margin-left:0}.dir-rtl .mod-indent-5{margin-right:150px;margin-left:0}.dir-rtl .mod-indent-6{margin-right:180px;margin-left:0}.dir-rtl .mod-indent-7{margin-right:210px;margin-left:0}.dir-rtl .mod-indent-8{margin-right:240px;margin-left:0}.dir-rtl .mod-indent-9{margin-right:270px;margin-left:0}.dir-rtl .mod-indent-10{margin-right:300px;margin-left:0}.dir-rtl .mod-indent-11{margin-right:330px;margin-left:0}.dir-rtl .mod-indent-12{margin-right:360px;margin-left:0}.dir-rtl .mod-indent-13{margin-right:390px;margin-left:0}.dir-rtl .mod-indent-14{margin-right:420px;margin-left:0}.dir-rtl .mod-indent-15,.dir-rtl .mod-indent-huge{margin-right:420px;margin-left:0}.resourcecontent .mediaplugin_mp3 object{width:600px;height:25px}.resourcecontent audio.mediaplugin_html5audio{width:600px}.resourceimage{max-width:100%}.mediaplugin_mp3 object{width:300px;height:15px}audio.mediaplugin_html5audio{width:300px}.core_media_preview.pagelayout-embedded #content{padding:0}.core_media_preview.pagelayout-embedded #maincontent{height:0}body#page-lib-editor-tinymce-plugins-moodlemedia-preview{min-width:0;padding:0;margin:0;background:0}.dir-rtl .ygtvtn,.dir-rtl .ygtvtm,.dir-rtl .ygtvtmh,.dir-rtl .ygtvtmhh,.dir-rtl .ygtvtp,.dir-rtl .ygtvtph,.dir-rtl .ygtvtphh,.dir-rtl .ygtvln,.dir-rtl .ygtvlm,.dir-rtl .ygtvlmh,.dir-rtl .ygtvlmhh,.dir-rtl .ygtvlp,.dir-rtl .ygtvlph,.dir-rtl .ygtvlphh,.dir-rtl .ygtvdepthcell,.dir-rtl .ygtvok,.dir-rtl .ygtvok:hover,.dir-rtl .ygtvcancel,.dir-rtl .ygtvcancel:hover{width:18px;height:22px;cursor:pointer;background-image:url([[pix:theme|yui2-treeview-sprite-rtl]]);background-repeat:no-repeat}.dir-rtl .ygtvtn{background-position:0 -5600px}.dir-rtl .ygtvtm{background-position:0 -4000px}.dir-rtl .ygtvtmh,.dir-rtl .ygtvtmhh{background-position:0 -4800px}.dir-rtl .ygtvtp{background-position:0 -6400px}.dir-rtl .ygtvtph,.dir-rtl .ygtvtphh{background-position:0 -7200px}.dir-rtl .ygtvln{background-position:0 -1600px}.dir-rtl .ygtvlm{background-position:0 0}.dir-rtl .ygtvlmh,.dir-rtl .ygtvlmhh{background-position:0 -800px}.dir-rtl .ygtvlp{background-position:0 -2400px}.dir-rtl .ygtvlph,.dir-rtl .ygtvlphh{background-position:0 -3200px}.dir-rtl .ygtvdepthcell{background-position:0 -8000px}.dir-rtl .ygtvok{background-position:0 -8800px}.dir-rtl .ygtvok:hover{background-position:0 -8844px}.dir-rtl .ygtvcancel{background-position:0 -8822px}.dir-rtl .ygtvcancel:hover{background-position:0 -8866px}.dir-rtl.yui-skin-sam .yui-panel .hd{text-align:right}.dir-rtl .yui-skin-sam .yui-layout .yui-layout-unit div.yui-layout-bd{text-align:right}.dir-rtl .clearlooks2.ie9 .mceAlert .mceMiddle span,.dir-rtl .clearlooks2 .mceConfirm .mceMiddle span{top:44px}.dir-rtl .o2k7Skin table,.dir-rtl .o2k7Skin tbody,.dir-rtl .o2k7Skin a,.dir-rtl .o2k7Skin img,.dir-rtl .o2k7Skin tr,.dir-rtl .o2k7Skin div,.dir-rtl .o2k7Skin td,.dir-rtl .o2k7Skin iframe,.dir-rtl .o2k7Skin span,.dir-rtl .o2k7Skin *,.dir-rtl .o2k7Skin .mceText,.dir-rtl .o2k7Skin .mceListBox .mceText{text-align:right}.path-rating .ratingtable{width:100%;margin-bottom:1em}.path-rating .ratingtable th.rating{width:100%}.path-rating .ratingtable td.rating,.path-rating .ratingtable td.time{text-align:center;white-space:nowrap}.initialbar a{padding-right:2px}.moodle-dialogue-base .moodle-dialogue-lightbox{background-color:#AAA}.moodle-dialogue-base .hidden,.moodle-dialogue-base .moodle-dialogue-hidden{display:none}.no-scrolling{overflow:hidden}.moodle-dialogue-base .moodle-dialogue-fullscreen{position:fixed;top:0;right:0;bottom:-50px;left:0}.moodle-dialogue-base .moodle-dialogue-fullscreen .moodle-dialogue-content{overflow:auto}.moodle-dialogue-base .moodle-dialogue-fullscreen .closebutton{width:28px;height:16px;background-size:100%}.moodle-dialogue-base .moodle-dialogue{z-index:600;padding:0;margin:0;background:0;border:0;outline:#000 dotted 0}.moodle-dialogue-base .moodle-dialogue-wrap{margin-top:-3px;margin-left:-3px;background-color:#fff;border:1px solid #ccc;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;-webkit-box-shadow:5px 5px 20px 0 #666;-moz-box-shadow:5px 5px 20px 0 #666;box-shadow:5px 5px 20px 0 #666}.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd,.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd.yui3-widget-hd{padding:5px;margin:0;font-size:12px;font-weight:normal;letter-spacing:1px;color:#333;text-align:center;text-shadow:1px 1px 1px #fff;background:#ccc;background-color:#ebebeb;background-image:-moz-linear-gradient(top,#fff,#ccc);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#ccc));background-image:-webkit-linear-gradient(top,#fff,#ccc);background-image:-o-linear-gradient(top,#fff,#ccc);background-image:linear-gradient(to bottom,#fff,#ccc);background-repeat:repeat-x;border-bottom:1px solid #bbb;-webkit-border-radius:10px 10px 0 0;-moz-border-radius:10px 10px 0 0;border-radius:10px 10px 0 0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffcccccc',GradientType=0);filter:0}.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd h1{display:inline;padding:0;margin:0;font-size:100%;font-weight:bold}.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd .yui3-widget-buttons{padding:5px}.moodle-dialogue-base .closebutton{display:inline-block;float:right;width:25px;height:15px;padding:0;vertical-align:middle;cursor:pointer;background-image:url([[pix:theme|sprite]]);background-repeat:no-repeat;border-style:none}.dir-rtl .moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd .yui3-widget-buttons{right:auto;left:0}.moodle-dialogue-base .moodle-dialogue .moodle-dialogue-bd{padding:1em;font-size:12px;line-height:2em;color:#555}.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-content{padding:0;background:#FFF}.moodle-dialogue-base .moodle-dialogue-fullscreen .moodle-dialogue-hd{padding:10px;font-size:16px}.moodle-dialogue-base .moodle-dialogue-fullscreen .moodle-dialogue-content{position:absolute;top:0;right:0;bottom:50px;left:0;margin:0;overflow:auto;border:0}.moodle-dialogue-base .moodle-dialogue-fullscreen .moodle-dialogue-hd,.moodle-dialogue-base .moodle-dialogue-fullscreen .moodle-dialogue-wrap{border-radius:0}.moodle-dialogue-confirm .confirmation-dialogue{text-align:center}.moodle-dialogue-confirm .confirmation-dialogue input{text-align:center}.moodle-dialogue-exception .moodle-exception-message{text-align:center}.moodle-dialogue-exception .moodle-exception-param label{font-weight:bold}.moodle-dialogue-exception .param-stacktrace label{background-color:#EEE;border:1px solid #ccc;border-bottom-width:0}.moodle-dialogue-exception .param-stacktrace pre{background-color:#fff;border:1px solid #ccc}.moodle-dialogue-exception .param-stacktrace .stacktrace-file{font-size:11.9px;color:navy}.moodle-dialogue-exception .param-stacktrace .stacktrace-line{font-size:11.9px;color:#b94a48}.moodle-dialogue-exception .param-stacktrace .stacktrace-call{font-size:90%;color:#333;border-bottom:1px solid #eee}.moodle-dialogue-base .moodle-dialogue .moodle-dialogue-content .moodle-dialogue-ft{padding:0;margin:.7em 1em;font-size:12px;text-align:right;background-color:#FFF}.moodle-dialogue-confirm .confirmation-message{margin:.5em 1em}.moodle-dialogue-confirm .confirmation-dialogue input{min-width:80px}.moodle-dialogue-exception .moodle-exception-message{margin:1em}.moodle-dialogue-exception .moodle-exception-param{margin-bottom:.5em}.moodle-dialogue-exception .moodle-exception-param label{width:150px}.moodle-dialogue-exception .param-stacktrace label{display:block;padding:4px 1em;margin:0}.moodle-dialogue-exception .param-stacktrace pre{display:block;height:200px;overflow:auto}.moodle-dialogue-exception .param-stacktrace .stacktrace-file{display:inline-block;margin:4px 0}.moodle-dialogue-exception .param-stacktrace .stacktrace-line{display:inline-block;width:50px;margin:4px 1em}.moodle-dialogue-exception .param-stacktrace .stacktrace-call{padding-bottom:4px;padding-left:25px;margin-bottom:4px}.moodle-dialogue .moodle-dialogue-bd .content-lightbox{top:0;left:0;width:100%;height:100%;padding:10% 0;text-align:center;background-color:white;opacity:.75;filter:alpha(opacity=75)}.moodle-dialogue .tooltiptext{max-height:300px}.moodle-dialogue-base .moodle-dialogue.moodle-dialogue-tooltip{z-index:3001}#page-question-edit.dir-rtl a.container-close{right:auto;left:6px}.chooserdialoguebody,.choosertitle{display:none}.moodle-dialogue.chooserdialogue .moodle-dialogue-content .moodle-dialogue-ft{margin:0}.chooserdialogue .moodle-dialogue-wrap .moodle-dialogue-bd{padding:0;background:#f2f2f2;-webkit-border-bottom-right-radius:10px;border-bottom-right-radius:10px;-webkit-border-bottom-left-radius:10px;border-bottom-left-radius:10px;-moz-border-radius-bottomright:10px;-moz-border-radius-bottomleft:10px}.choosercontainer #chooseform .submitbuttons{margin:.7em 0;text-align:center}.choosercontainer #chooseform .submitbuttons input{min-width:100px;margin:0 .5em}.choosercontainer #chooseform .options{position:relative;border-bottom:1px solid #bbb}.jsenabled .choosercontainer #chooseform .alloptions{max-width:20.3em;overflow-x:hidden;overflow-y:auto;-webkit-box-shadow:inset 0 0 30px 0 #ccc;-moz-box-shadow:inset 0 0 30px 0 #ccc;box-shadow:inset 0 0 30px 0 #ccc}.dir-rtl.jsenabled .choosercontainer #chooseform .alloptions{max-width:18.3em}.choosercontainer #chooseform .moduletypetitle,.choosercontainer #chooseform .option,.choosercontainer #chooseform .nonoption{padding:0 1.6em 0 1.6em;margin-bottom:0}.choosercontainer #chooseform .moduletypetitle{padding-top:1.2em;padding-bottom:.4em;text-transform:uppercase}.choosercontainer #chooseform .option .typename,.choosercontainer #chooseform .option span.modicon img.icon,.choosercontainer #chooseform .nonoption .typename,.choosercontainer #chooseform .nonoption span.modicon img.icon{padding:0 0 0 .5em}.dir-rtl .choosercontainer #chooseform .option .typename,.dir-rtl .choosercontainer #chooseform .option span.modicon img.icon,.dir-rtl .choosercontainer #chooseform .nonoption .typename,.dir-rtl .choosercontainer #chooseform .nonoption span.modicon img.icon{padding:0 .5em 0 0}.choosercontainer #chooseform .option span.modicon img.icon,.choosercontainer #chooseform .nonoption span.modicon img.icon{width:24px;height:24px}.choosercontainer #chooseform .option input[type=radio],.choosercontainer #chooseform .option span.typename,.choosercontainer #chooseform .option span.modicon{vertical-align:middle}.choosercontainer #chooseform .option label{display:block;padding:.3em 0 .1em 0;border-bottom:1px solid #fff}.choosercontainer #chooseform .nonoption{padding-top:.3em;padding-bottom:.1em;padding-left:2.7em}.dir-rtl .choosercontainer #chooseform .nonoption{padding-right:2.7em;padding-left:0}.choosercontainer #chooseform .subtype{padding:0 1.6em 0 3.2em;margin-bottom:0}.dir-rtl .choosercontainer #chooseform .subtype{padding:0 3.2em 0 1.6em}.choosercontainer #chooseform .subtype .typename{margin:0 0 0 .2em}.dir-rtl .choosercontainer #chooseform .subtype .typename{margin:0 .2em 0 0}.jsenabled .choosercontainer #chooseform .instruction,.jsenabled .choosercontainer #chooseform .typesummary{position:absolute;top:0;right:0;bottom:0;left:20.3em;display:none;padding:1.6em;margin:0;overflow-x:hidden;overflow-y:auto;line-height:2em;background-color:#fff}.dir-rtl.jsenabled .choosercontainer #chooseform .instruction,.dir-rtl.jsenabled .choosercontainer #chooseform .typesummary{right:18.5em;left:0;border-right:1px solid grey}.jsenabled .choosercontainer #chooseform .instruction,.choosercontainer #chooseform .selected .typesummary{display:block}.choosercontainer #chooseform .selected{background-color:#fff;-webkit-box-shadow:0 0 10px 0 #ccc;-moz-box-shadow:0 0 10px 0 #ccc;box-shadow:0 0 10px 0 #ccc}.section-modchooser-link img.smallicon{padding:3px}.formlistingradio{padding-right:10px;padding-bottom:25px}.formlistinginputradio{float:left}.formlistingmain{min-height:225px}.formlisting{position:relative;padding:1px 19px 14px;margin:15px 0;background-color:white;border:1px solid #DDD;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.formlistingmore{position:absolute;right:-1px;bottom:-1px;padding:3px 7px;font-size:12px;font-weight:bold;color:#9da0a4;cursor:pointer;background-color:whiteSmoke;border:1px solid #ddd;-webkit-border-radius:4px 0 4px 0;-moz-border-radius:4px 0 4px 0;border-radius:4px 0 4px 0}.formlistingall{padding:0;margin:15px 0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.formlistingrow{top:50%;left:50%;float:left;width:150px;min-height:34px;padding:6px;cursor:pointer;background-color:#f7f7f9;border-right:1px solid #e1e1e8;border-bottom:1px solid;border-left:1px solid #e1e1e8;border-color:#e1e1e8;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}body.jsenabled .formlistingradio{display:none}body.jsenabled .formlisting{display:block}table.collection{width:100%;margin-bottom:20px;border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}table.collection th,table.collection td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}table.collection th{font-weight:bold}table.collection thead th{vertical-align:bottom}table.collection caption+thead tr:first-child th,table.collection caption+thead tr:first-child td,table.collection colgroup+thead tr:first-child th,table.collection colgroup+thead tr:first-child td,table.collection thead:first-child tr:first-child th,table.collection thead:first-child tr:first-child td{border-top:0}table.collection tbody+tbody{border-top:2px solid #ddd}table.collection .table{background-color:#fff}table.collection th,table.collection td{border-left:1px solid #ddd}table.collection caption+thead tr:first-child th,table.collection caption+tbody tr:first-child th,table.collection caption+tbody tr:first-child td,table.collection colgroup+thead tr:first-child th,table.collection colgroup+tbody tr:first-child th,table.collection colgroup+tbody tr:first-child td,table.collection thead:first-child tr:first-child th,table.collection tbody:first-child tr:first-child th,table.collection tbody:first-child tr:first-child td{border-top:0}table.collection thead:first-child tr:first-child>th:first-child,table.collection tbody:first-child tr:first-child>td:first-child,table.collection tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}table.collection thead:first-child tr:first-child>th:last-child,table.collection tbody:first-child tr:first-child>td:last-child,table.collection tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}table.collection thead:last-child tr:last-child>th:first-child,table.collection tbody:last-child tr:last-child>td:first-child,table.collection tbody:last-child tr:last-child>th:first-child,table.collection tfoot:last-child tr:last-child>td:first-child,table.collection tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}table.collection thead:last-child tr:last-child>th:last-child,table.collection tbody:last-child tr:last-child>td:last-child,table.collection tbody:last-child tr:last-child>th:last-child,table.collection tfoot:last-child tr:last-child>td:last-child,table.collection tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}table.collection tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}table.collection tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}table.collection caption+thead tr:first-child th:first-child,table.collection caption+tbody tr:first-child td:first-child,table.collection colgroup+thead tr:first-child th:first-child,table.collection colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}table.collection caption+thead tr:first-child th:last-child,table.collection caption+tbody tr:first-child td:last-child,table.collection colgroup+thead tr:first-child th:last-child,table.collection colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}table.collection tbody>tr:nth-child(odd)>td,table.collection tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}table.collection .name{text-align:left;vertical-align:middle}table.collection .awards{width:10%;text-align:center;vertical-align:middle}table.collection .criteria{width:40%;text-align:left;vertical-align:top}table.collection .badgeimage,table.collection .status{width:15%;text-align:center;vertical-align:middle}table.collection .description{width:25%;text-align:left}table.collection .actions{width:11em;text-align:center;vertical-align:middle}a.criteria-action{float:right;padding:0 3px}table.issuedbadgebox{width:750px;background-color:#fff}table.badgeissuedimage{width:150px;text-align:center}table.badgeissuedinfo{width:600px}table.badgeissuedinfo .bvalue{text-align:left;vertical-align:middle}table.badgeissuedinfo .bfield{width:125px;font-style:italic;text-align:left}.dir-rtl table.badgeissuedinfo .bvalue,.dir-rtl table.badgeissuedinfo .bfield{text-align:right}ul.badges{margin:0;list-style:none}.badges li{position:relative;display:inline-block;width:150px;padding-bottom:2em;text-align:center;vertical-align:top}.badges li .badge-name{display:block;padding:5px}.badges li>img{position:absolute}.badges li .badge-image{top:0;left:10px;z-index:1;width:90px;height:90px}.badges li .badge-actions{position:relative}div.badge{position:relative;display:block}div.badge .expireimage{top:0;left:20px;width:100px;height:100px}.expireimage{position:absolute;top:0;left:30px;z-index:10;width:90px;height:90px;opacity:.85;filter:alpha(opacity=85)}.badge-profile{vertical-align:top}.connected{color:#468847}.notconnected{color:#b94a48}.connecting{color:#c09853}#page-badges-award .recipienttable tr td{vertical-align:top}#page-badges-award .recipienttable tr td.actions .actionbutton{width:100%;padding:.5em 0;margin:.3em 0}#page-badges-award .recipienttable tr td.existing,#page-badges-award .recipienttable tr td.potential{width:42%}.statustable{margin-bottom:0}.statusbox.active{background-color:#dff0d8}.statusbox.inactive{background-color:#fcf8e3}.activatebadge{margin:0;text-align:left;vertical-align:middle}.dir-rtl .activatebadge{text-align:right}img#persona_signin{cursor:pointer}.addcourse{float:right}.invisiblefieldset{display:inline;padding:0;margin:0;border-width:0}.breadcrumb-nav{float:left;margin-bottom:10px}.dir-rtl .breadcrumb-nav{float:right}.breadcrumb-button .singlebutton div{margin-right:0}.breadcrumb-nav .breadcrumb{margin:0}.moodle-actionmenu,.moodle-actionmenu>ul,.moodle-actionmenu>ul>li{display:inline-block}.moodle-actionmenu ul{padding:0;margin:0;list-style-type:none}.moodle-actionmenu .toggle-display,.moodle-actionmenu .menu-action-text{display:none}.jsenabled .moodle-actionmenu[data-enhance]{display:block}.jsenabled .moodle-actionmenu[data-enhance] .menu{display:none}.jsenabled .moodle-actionmenu[data-enhance] .toggle-display{display:inline;opacity:.5;filter:alpha(opacity=50)}.jsenabled .moodle-actionmenu[data-enhance] .toggle-display.textmenu{display:block;padding-left:4px;margin-left:4px}.jsenabled .moodle-actionmenu[data-enhance] .toggle-display.textmenu .iconsmall{padding:8px 4px 0 2px;margin:4px 4px 4px 0;vertical-align:text-bottom}.jsenabled .moodle-actionmenu[data-enhance] .toggle-display.textmenu .caret{margin-top:8px;margin-left:2px;border-top-color:#777}.jsenabled .moodle-actionmenu[data-enhance] .toggle-display.textmenu .caret:hover,.jsenabled .moodle-actionmenu[data-enhance] .toggle-display.textmenu .caret:active{border-top-color:#555}.jsenabled .moodle-actionmenu[data-enhanced] .toggle-display{opacity:1;filter:alpha(opacity=100)}.jsenabled .moodle-actionmenu[data-enhanced] .menu-action-text{display:inline}.moodle-actionmenu[data-enhanced].show{position:relative}.moodle-actionmenu[data-enhanced].show .menu{position:absolute;z-index:1000;display:block;text-align:left;background-color:#fff;border:1px solid #ccc;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;-webkit-box-shadow:5px 5px 20px 0 #666;-moz-box-shadow:5px 5px 20px 0 #666;box-shadow:5px 5px 20px 0 #666}.moodle-actionmenu[data-enhanced].show .menu a{display:block;padding:2px 1em 2px 28px;color:#333}.moodle-actionmenu[data-enhanced].show .menu a:hover,.moodle-actionmenu[data-enhanced].show .menu a:focus{color:#fff;background-color:#08c}.moodle-actionmenu[data-enhanced].show .menu a:first-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.moodle-actionmenu[data-enhanced].show .menu a:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.moodle-actionmenu[data-enhanced].show .menu a.hidden{display:none}.moodle-actionmenu[data-enhanced].show .menu img{vertical-align:middle}.moodle-actionmenu[data-enhanced].show .menu .iconsmall{margin:4px 4px 4px -24px}.moodle-actionmenu[data-enhanced].show .menu>li{display:block}.moodle-actionmenu[data-enhanced].show .menu.align-tl-bl{top:100%;left:0;margin-top:4px}.moodle-actionmenu[data-enhanced].show .menu.align-tr-bl{top:100%;right:100%}.moodle-actionmenu[data-enhanced].show .menu.align-bl-bl{bottom:100%;left:0}.moodle-actionmenu[data-enhanced].show .menu.align-br-bl{right:100%;bottom:100%}.moodle-actionmenu[data-enhanced].show .menu.align-tl-br{top:100%;left:100%}.moodle-actionmenu[data-enhanced].show .menu.align-tr-br{top:100%;right:0;margin-top:4px}.moodle-actionmenu[data-enhanced].show .menu.align-bl-br{bottom:100%;left:100%}.moodle-actionmenu[data-enhanced].show .menu.align-br-br{right:0;bottom:100%}.moodle-actionmenu[data-enhanced].show .menu.align-tl-tl{top:0;left:0}.moodle-actionmenu[data-enhanced].show .menu.align-tr-tl{top:0;right:100%;margin-right:4px}.moodle-actionmenu[data-enhanced].show .menu.align-bl-tl{bottom:100%;left:0;margin-bottom:4px}.moodle-actionmenu[data-enhanced].show .menu.align-br-tl{right:100%;bottom:100%}.moodle-actionmenu[data-enhanced].show .menu.align-tl-tr{top:0;left:100%;margin-left:4px}.moodle-actionmenu[data-enhanced].show .menu.align-tr-tr{top:0;right:0}.moodle-actionmenu[data-enhanced].show .menu.align-bl-tr{bottom:100%;left:100%}.moodle-actionmenu[data-enhanced].show .menu.align-br-tr{right:0;bottom:100%;margin-bottom:4px}.block .moodle-actionmenu{text-align:right}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu{right:auto;left:0;text-align:right}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu .iconsmall{margin-right:0;margin-left:8px}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-tl-bl{right:0;left:auto}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-tr-bl{right:auto;left:100%}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-bl-bl{right:0;left:auto}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-br-bl{right:auto;left:100%}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-tl-br{right:100%;left:auto}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-tr-br{right:auto;left:0}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-bl-br{right:100%;left:auto}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-br-br{right:auto;left:0}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-tl-tl{right:0;left:auto}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-tr-tl{right:auto;left:100%}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-bl-tl{right:0;left:auto}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-br-tl{right:auto;left:100%}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-tl-tr{right:100%;left:auto}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-tr-tr{right:auto;left:0}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-bl-tr{right:100%;left:auto}.dir-rtl .moodle-actionmenu[data-enhanced].show .menu.align-br-tr{right:auto;left:0}.dir-rtl .block .moodle-actionmenu{text-align:right}ul.dragdrop-keyboard-drag li{list-style-type:none}.block-control-actions .moodle-core-dragdrop-draghandle img{width:12px;height:12px}a.disabled:hover,a.disabled{font-style:italic;color:#808080;text-decoration:none;cursor:default}.formtable tbody th{font-weight:normal;text-align:right}.path-admin #assignrole{width:60%;margin-right:auto;margin-left:auto}.path-admin .admintable .leftalign{text-align:left}.environmenttable p.warn{color:#c09853;background-color:#fcf8e3}.environmenttable .error,.environmenttable span.warn,.environmenttable .ok{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.environmenttable .error:empty,.environmenttable span.warn:empty,.environmenttable .ok:empty{display:none}.environmenttable .error-important,.environmenttable span.warn-important,.environmenttable .ok-important{background-color:#b94a48}.environmenttable .error-important[href],.environmenttable span.warn-important[href],.environmenttable .ok-important[href]{background-color:#953b39}.environmenttable .error-warning,.environmenttable span.warn-warning,.environmenttable .ok-warning{background-color:#f89406}.environmenttable .error-warning[href],.environmenttable span.warn-warning[href],.environmenttable .ok-warning[href]{background-color:#c67605}.environmenttable .error-success,.environmenttable span.warn-success,.environmenttable .ok-success{background-color:#468847}.environmenttable .error-success[href],.environmenttable span.warn-success[href],.environmenttable .ok-success[href]{background-color:#356635}.environmenttable .error-info,.environmenttable span.warn-info,.environmenttable .ok-info{background-color:#3a87ad}.environmenttable .error-info[href],.environmenttable span.warn-info[href],.environmenttable .ok-info[href]{background-color:#2d6987}.environmenttable .error-inverse,.environmenttable span.warn-inverse,.environmenttable .ok-inverse{background-color:#333}.environmenttable .error-inverse[href],.environmenttable span.warn-inverse[href],.environmenttable .ok-inverse[href]{background-color:#1a1a1a}.environmenttable .error{background-color:#b94a48}.environmenttable span.warn{background-color:#f89406}.environmenttable .ok{background-color:#468847}.path-admin .admintable.environmenttable .name,.path-admin .admintable.environmenttable .info,.path-admin #assignrole .admintable .role,.path-admin #assignrole .admintable .userrole,.path-admin #assignrole .admintable .roleholder{white-space:nowrap}.path-admin .incompatibleblockstable td.c0{font-weight:bold}#page-admin-course-category .addcategory{padding:10px}#page-admin-course-index .editcourse{margin:20px auto}#page-admin-course-index .editcourse th,#page-admin-course-index .editcourse td{padding-right:10px;padding-left:10px}.timewarninghidden{display:none}.statusok,.statuswarning,.statusserious,.statuscritical{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.statusok:empty,.statuswarning:empty,.statusserious:empty,.statuscritical:empty{display:none}.statusok-important,.statuswarning-important,.statusserious-important,.statuscritical-important{background-color:#b94a48}.statusok-important[href],.statuswarning-important[href],.statusserious-important[href],.statuscritical-important[href]{background-color:#953b39}.statusok-warning,.statuswarning-warning,.statusserious-warning,.statuscritical-warning{background-color:#f89406}.statusok-warning[href],.statuswarning-warning[href],.statusserious-warning[href],.statuscritical-warning[href]{background-color:#c67605}.statusok-success,.statuswarning-success,.statusserious-success,.statuscritical-success{background-color:#468847}.statusok-success[href],.statuswarning-success[href],.statusserious-success[href],.statuscritical-success[href]{background-color:#356635}.statusok-info,.statuswarning-info,.statusserious-info,.statuscritical-info{background-color:#3a87ad}.statusok-info[href],.statuswarning-info[href],.statusserious-info[href],.statuscritical-info[href]{background-color:#2d6987}.statusok-inverse,.statuswarning-inverse,.statusserious-inverse,.statuscritical-inverse{background-color:#333}.statusok-inverse[href],.statuswarning-inverse[href],.statusserious-inverse[href],.statuscritical-inverse[href]{background-color:#1a1a1a}.statusok{background-color:#468847}.statuswarning{background-color:#c09853}.statusserious{background-color:#f89406}.statuscritical{background-color:#b94a48}#page-admin-report-capability-index #capabilitysearch{width:30em}#page-admin-report-backups-index .backup-error,#page-admin-report-backups-index .backup-unfinished{color:#b94a48}#page-admin-report-backups-index .backup-skipped,#page-admin-report-backups-index .backup-ok,#page-admin-report-backups-index .backup-notyetrun{color:#468847}#page-admin-report-backups-index .backup-warning{color:#c09853}#page-admin-qtypes .disabled,#page-admin-qbehaviours .disabled{color:#999}#page-admin-qtypes #qtypes div,#page-admin-qtypes #qtypes form,#page-admin-qbehaviours #qbehaviours div,#page-admin-qbehaviours #qbehaviours form{display:inline}#page-admin-qtypes #qtypes img.spacer,#page-admin-qbehaviours #qbehaviours img.spacer{width:16px}img.iconsmall{padding:.3em;margin:0}#page-admin-qbehaviours .cell.c3,#page-admin-qtypes .cell.c3{font-size:10.5px}#page-admin-lang .generalbox,#page-admin-course-index .singlebutton,#page-admin-course-index .addcategory,#page-course-index .buttons,#page-course-index-category .buttons,#page-admin-course-category .addcategory,#page-admin-stickyblocks .generalbox,#page-admin-maintenance .buttons,#page-admin-course-index .buttons,#page-admin-course-category .buttons,#page-admin-index .copyright,#page-admin-index .copyrightnotice,#page-admin-index .adminerror,#page-admin-index .availableupdatesinfo,#page-admin-index .adminerror .singlebutton,#page-admin-index .adminwarning .singlebutton,#page-admin-index #layout-table .singlebutton{margin-bottom:1em;text-align:center}.path-admin-roles .capabilitysearchui{margin-right:auto;margin-left:auto;text-align:left}#page-admin-roles-define .topfields{margin:1em 0 2em}#page-admin-roles-define .capdefault{background-color:#eee;border:1px solid #cecece}#page-filter-manage .backlink,.path-admin-roles .backlink{margin-top:1em}#page-admin-roles-explain #chooseuser h3,#page-admin-roles-usersroles .contextname{margin-top:0}#page-admin-roles-explain #chooseusersubmit{margin-top:0;text-align:center}#page-admin-roles-usersroles p{margin:0}#page-admin-roles-override .cell.c1,#page-admin-roles-assign .cell.c3,#page-admin-roles-assign .cell.c1{padding-top:.75em}#page-admin-roles-override .overridenotice,#page-admin-roles-define .definenotice{margin:1em 10% 2em 10%;text-align:left}#notice{width:60%;min-width:220px;margin:auto}#page-admin-index .releasenoteslink,#page-admin-index .adminwarning,#page-admin-index .maturitywarning,#page-admin-index .testsitewarning,#page-admin-index .maturityinfo{width:60%;min-width:220px;padding:8px 35px 8px 14px;margin:auto;margin-bottom:20px;color:#c09853;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}#page-admin-index .maturitywarning,#page-admin-index .testsitewarning,#page-admin-index .adminwarning.maturityinfo.maturity50{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}#page-admin-index .adminwarning.availableupdatesinfo,#page-admin-index .releasenoteslink{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo span{display:block}#page-admin-index .updateplugin div,#page-admin-plugins .updateplugin div{margin-bottom:.5em}#page-admin-index .updateplugin .updatepluginconfirmexternal,#page-admin-plugins .updateplugin .updatepluginconfirmexternal{padding:1em;background-color:#f2dede;border:1px solid #eed3d7}#page-admin-user-user_bulk #users .fgroup{white-space:nowrap}#page-admin-report-stats-index .graph{margin-bottom:1em;text-align:center}#page-admin-report-courseoverview-index .graph{margin-bottom:1em;text-align:center}#page-admin-lang .translator{border-style:solid;border-width:1px}.path-admin .roleassigntable{width:100%}.path-admin .roleassigntable td{padding:.2em .3em;vertical-align:top}.path-admin .roleassigntable p{margin:.2em 0;text-align:left}.path-admin .roleassigntable #existingcell,.path-admin .roleassigntable #potentialcell{width:42%}.path-admin .roleassigntable #existingcell p>label:first-child,.path-admin .roleassigntable #potentialcell p>label:first-child{font-weight:bold}.path-admin .roleassigntable #buttonscell{width:16%}.path-admin .roleassigntable #buttonscell #assignoptions{font-size:10.5px}.path-admin .roleassigntable #removeselect_wrapper,.path-admin .roleassigntable #addselect_wrapper{width:100%}.path-admin table.rolecap tr.rolecap th{font-weight:normal;text-align:left}.path-admin.dir-rtl table.rolecap tr.rolecap th{text-align:right}.path-admin .rolecap .hiddenrow{display:none}.path-admin #defineroletable .rolecap .inherit,.path-admin #defineroletable .rolecap .allow,.path-admin #defineroletable .rolecap .prevent,.path-admin #defineroletable .rolecap .prohibit{min-width:3.5em;padding:0;text-align:center}.path-admin .rolecap .cap-name,.path-admin .rolecap .note{display:block;font-size:10.5px;font-weight:normal;white-space:nowrap}.path-admin .rolecap label{display:block;padding:.5em;margin:0;text-align:center}.plugincheckwrapper{width:100%}.environmentbox{margin-top:1em}#mnetconfig table{margin-right:auto;margin-left:auto}.environmenttable .cell{padding:.15em .5em}.environmenttable img.iconhelp{padding-right:.3em}.dir-rtl .environmenttable img.iconhelp{padding-right:0;padding-left:.3em}#trustedhosts .generaltable{width:500px;margin-right:auto;margin-left:auto}#trustedhosts .standard{width:auto}#adminsettings legend{display:none}#adminsettings fieldset.error{margin:.2em 0 .5em 0}#adminsettings fieldset.error legend{display:block}.dir-rtl #admin-spelllanguagelist textarea,#page-admin-setting-editorsettingstinymce.dir-rtl .form-textarea textarea{text-align:left;direction:ltr}.adminsettingsflags{float:right}.dir-rtl .adminsettingsflags{float:left}.adminsettingsflags label{margin-right:7px}.dir-rtl .adminsettingsflags label{margin-left:7px}.form-description{clear:right}.dir-rtl .form-description{clear:left}.form-item .form-setting .form-htmlarea{display:inline;width:640px}.form-item .form-setting .form-htmlarea .htmlarea{display:block;width:640px}.form-item .form-setting .form-multicheckbox ul{padding:0;margin:7px 0 0 0;list-style:none}.form-item .form-setting .defaultsnext{display:inline;margin-right:.5em}.dir-rtl .form-item .form-setting .defaultsnext{margin-right:0;margin-left:.5em}.form-item .form-setting .locked-checkbox{display:inline;margin-right:.2em;margin-left:.5em}.dir-rtl .form-item .form-setting .locked-checkbox{display:inline;margin-right:.5em;margin-left:.2em}.form-item .form-setting .form-password .unmask,.form-item .form-setting .form-defaultinfo{display:inline-block}.form-item .pathok,.form-item .patherror{margin-left:.5em}#admin-devicedetectregex table{border:0}#admin-emoticons td input{width:8em}#admin-emoticons td.c0 input{width:4em}#adminthemeselector .selectedtheme td.c0{border:1px solid;border-right-width:0}#adminthemeselector .selectedtheme td.c1{border:1px solid;border-left-width:0}.admin_colourpicker,.admin_colourpicker_preview{display:none}.jsenabled .admin_colourpicker_preview{display:inline}.jsenabled .admin_colourpicker{display:block;width:410px;height:102px;margin-bottom:10px}.admin_colourpicker .loadingicon{margin-left:auto;vertical-align:middle}.admin_colourpicker .colourdialogue{float:left;border:1px solid #000}.admin_colourpicker .previewcolour{margin-left:301px;border:1px solid #000}.admin_colourpicker .currentcolour{margin-left:301px;border:1px solid #000;border-top-width:0}.dir-rtl .form-item .form-setting,.dir-rtl .form-item .form-label,.dir-rtl .form-item .form-description,.dir-rtl.path-admin .roleassigntable p{text-align:right}#page-admin-index #notice .checkforupdates{text-align:center}#plugins-check-info{margin:1em;text-align:center}#plugins-check .displayname .pluginicon{width:16px}#plugins-check .status-new .status{background-color:#dff0d8}#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo.maturity200 .info.release,#plugins-check .status-upgrade .status,#plugins-check .status-delete .status{background-color:#d9edf7}#plugins-control-panel .extension .source,#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo.maturity100 .info.release,#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo.maturity150 .info.release,.pluginupdateinfo.maturity100,.pluginupdateinfo.maturity150,#plugins-check .extension .source{background-color:#fcf8e3}#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo.maturity50 .info.release,.pluginupdateinfo.maturity50,#plugins-check .requires-failed,#plugins-check .missingfromdisk .displayname,#plugins-check .status-missing .status,#plugins-check .status-downgrade .status{background-color:#f2dede}#plugins-control-panel .statusmsg{padding:3px;background-color:#eee;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}#plugins-control-panel .status-missing .pluginname{background-color:#f2dede}#plugins-control-panel .status-missing .statusmsg{color:#b94a48}#plugins-control-panel .status-new .pluginname{background-color:#dff0d8}#plugins-control-panel .status-new .statusmsg{color:#468847}#plugins-control-panel .disabled .availability{background-color:#eee}#plugins-check .standard .source,#plugins-check .status-nodb .status,#plugins-check .status-uptodate .status,#plugins-check .requires-ok{color:#999}#plugins-check .requires ul{margin:0;font-size:10.5px}#plugins-check .status .pluginupdateinfo{padding:5px 10px;margin:10px;background-color:#d9edf7;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}#plugins-check .status .pluginupdateinfo span,#plugins-check .status .pluginupdateinfo a{padding-right:1em}#page-admin-index .upgradepluginsinfo{text-align:center}#page-admin-plugins .checkforupdates{margin:0 auto 1em;text-align:center}#plugins-control-panel .requiredby,#plugins-control-panel .pluginname .componentname{font-size:11.9px;color:#999}#plugins-control-panel .pluginname .componentname{margin-left:22px}#plugins-overview-filter .filter-item,#plugins-overview-panel .info{padding:0 10px}#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo .separator,#plugins-check .status .pluginupdateinfo .separator,#page-admin-plugins .separator{border-left:1px dotted #999}#plugins-control-panel .msg td{text-align:center}#plugins-overview-filter,#plugins-overview-panel{margin:1em auto;text-align:center}#plugins-overview-panel .info.updatable{margin-left:10px;font-weight:bold;background-color:#d9edf7;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}#plugins-overview-filter .filter-item.active{font-weight:bold}#plugins-control-panel .displayname img.icon{padding-top:0;padding-bottom:0}#plugins-control-panel .uninstall a{color:#b94a48}#plugins-control-panel .notes .pluginupdateinfo{padding:5px 10px;margin:10px;background-color:#d9edf7;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}#plugins-control-panel .notes .pluginupdateinfo span,#plugins-control-panel .notes .pluginupdateinfo a{padding-right:1em}.dir-rtl #plugins-check .pluginupdateinfo{text-align:center;direction:ltr}.dir-rtl #plugins-check .rootdir,.dir-rtl #plugins-check .requires-ok{text-align:left;direction:ltr}#page-admin-mnet-peers .box.deletedhosts{margin-bottom:1em;font-size:11.9px}#page-admin-mnet-peers .mform .certdetails{background-color:white}#page-admin-mnet-peers .mform .deletedhostinfo{padding:4px;margin-bottom:5px;background-color:#f2dede;border:2px solid #eed3d7}#core-cache-plugin-summaries table,#core-cache-store-summaries table{width:100%}#core-cache-lock-summary table,#core-cache-definition-summaries table,#core-cache-mode-mappings table{margin:0 auto}#core-cache-store-summaries .default-store td{font-style:italic;color:#333}#core-cache-rescan-definitions,#core-cache-mode-mappings .edit-link,#core-cache-lock-summary .new-instance{margin-top:.5em;text-align:center}.tinymcesubplugins img.icon{padding-top:0;padding-bottom:0}#page-admin-roles-assign div.box.generalbox{padding:8px 35px 8px 14px;margin-bottom:20px;color:#c09853;color:#b94a48;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;background-color:#f2dede;border:1px solid #fbeed5;border-color:#eed3d7;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.calendartable{width:100%}.calendartable th,.calendartable td{width:14%;text-align:center;vertical-align:top;border:0}.calendar_event_course{background-color:#ffd3bd}.calendar_event_global{background-color:#d6f8cd}.calendar_event_group{background-color:#fee7ae}.calendar_event_user{background-color:#dce7ec}.path-calendar .calendar-controls .previous,.path-calendar .calendar-controls .next,.path-calendar .calendar-controls .current{display:block;float:left;width:12%}.path-calendar .calendar-controls .previous{text-align:left}.path-calendar .calendar-controls .current{width:76%;text-align:center}.path-calendar .calendar-controls .next{text-align:right}.path-calendar .maincalendar{padding:0;vertical-align:top}.path-calendar .maincalendar .bottom{padding:5px 0 0 0;text-align:center}.path-calendar .maincalendar .heightcontainer{position:relative;height:100%}.path-calendar .maincalendar .calendarmonth{width:98%;margin:10px auto}.path-calendar .maincalendar .calendarmonth ul{margin:0}.path-calendar .maincalendar .calendarmonth ul li{margin-top:4px;list-style-type:none}.path-calendar .maincalendar .calendarmonth td{height:5em}.path-calendar .maincalendar .calendar-controls .previous,.path-calendar .maincalendar .calendar-controls .next{width:30%}.path-calendar .maincalendar .calendar-controls .current{width:39.95%}.path-calendar .maincalendar .controls{width:98%;margin:10px auto}.path-calendar .maincalendar .eventlist .event{width:100%;margin-bottom:10px;border-collapse:separate;border-spacing:0;border-style:solid;border-width:1px}.path-calendar .maincalendar .eventlist .event .topic .name{float:left}.dir-rtl.path-calendar .maincalendar .eventlist .event .topic .name,.path-calendar .maincalendar .eventlist .event .topic .date{float:right}.dir-rtl.path-calendar .maincalendar .eventlist .event .topic .date{float:left}.path-calendar .maincalendar .eventlist .event .subscription,.path-calendar .maincalendar .eventlist .event .course{float:left;clear:left}.dir-rtl.path-calendar .maincalendar .eventlist .event .subscription,.dir-rtl.path-calendar .maincalendar .eventlist .event .course{float:right;clear:right}.path-calendar .maincalendar .eventlist .event .side{width:32px}.path-calendar .maincalendar .eventlist .event .commands a{margin:0 3px}.path-calendar .maincalendar .header{overflow:hidden}.path-calendar .maincalendar .header .buttons{float:right}.dir-rtl.path-calendar .maincalendar .header .buttons{float:left}.path-calendar .filters table{width:100%;border-collapse:separate;border-spacing:2px}#page-calendar-export .indent{padding-left:20px}.path-calendar .cal_courses_flt label{margin-right:.45em}.dir-rtl.path-calendar .cal_courses_flt label{margin-right:0;margin-left:.45em}.block .minicalendar th,.block .minicalendar td{padding:2px;font-size:.8em}.block .minicalendar{max-width:280px;margin-right:auto;margin-left:auto}.block .minicalendar td.weekend{color:#A00}.block .calendar-controls .previous{display:block;float:left;width:12%;text-align:left}.block .calendar-controls .current{display:block;float:left;width:76%;text-align:center}.block .calendar-controls .next{display:block;float:left;width:12%;text-align:right}.block .calendar_filters ul{margin:0;list-style:none}.block .calendar_filters li{margin-bottom:.2em}.block .calendar_filters li span img{padding:0 .2em}.block .calendar_filters .eventname{padding-left:.2em}.dir-rtl .block .calendar_filters .eventname{padding-right:.2em;padding-left:0}.block .content h3.eventskey{margin-top:.5em}@media(min-width:768px){#page-calender-view .container fluid{min-width:1024px}}.section_add_menus{text-align:right}.dir-rtl .section_add_menus{text-align:left}.section_add_menus .horizontal div,.section_add_menus .horizontal form{display:inline}.section_add_menus optgroup{font-style:italic;font-weight:normal}.section_add_menus .urlselect{margin-left:.4em}.dir-rtl .section_add_menus .urlselect{margin-right:.4em;margin-left:0}.section_add_menus .urlselect select{margin-left:.2em}.dir-rtl .section_add_menus .urlselect select{margin-right:.2em;margin-left:0}.section_add_menus .urlselect img.iconhelp{padding:0;margin:0;vertical-align:text-bottom}.site-topic ul.section,.course-content ul.section{margin:1em}.section .spinner{width:16px;height:16px}.section .activity .spinner{position:absolute;left:100%;vertical-align:text-bottom}.section .activity .editing_move{position:absolute;top:0;left:0}.section .activity .mod-indent{padding-left:32px}.section .activity .actions{position:absolute;top:0;right:0}.section .activity .activityinstance .dimmed img.activityicon{opacity:.5;filter:alpha(opacity=50)}.section .filler{display:inline-block;width:16px;height:16px;padding:.3em}.section .activity.editor_displayed a.editing_title,.section .activity.editor_displayed .moodle-actionmenu{display:none}.section .activity.editor_displayed div.activityinstance{padding-right:initial}.section .activity.editor_displayed div.activityinstance input{padding-top:initial;padding-bottom:initial;margin-bottom:initial;vertical-align:text-bottom}.dir-rtl .section .activity .spinner{right:100%;left:auto}.dir-rtl .section .activity .mod-indent{padding-right:32px;padding-left:auto}.dir-rtl .section .activity .actions{right:auto;left:0}.dir-rtl.editing .section .activity .editing_move{right:0;left:auto}.dir-rtl.editing .section .activity.editor_displayed div.activityinstance{padding-left:initial}.activity img.activityicon{margin-right:6px;vertical-align:text-bottom}.dir-rtl .section .activity img.activityicon{margin-right:0;margin-left:6px}.section .activity .activityinstance,.section .activity .activityinstance div{display:inline-block}.editing .section .activity .activityinstance{display:table-cell;min-width:40%;min-height:2em;padding-right:200px}.dir-rtl.editing .section .activity .activityinstance{padding-right:0;padding-left:200px}.editing_show+.editing_assign,.editing_hide+.editing_assign{margin-left:20px}.section .activity .commands{display:inline;white-space:nowrap}.section .activity.modtype_label .commands{padding-left:.2em;margin-left:40%}.section .activity.modtype_label.label{padding:.2em;font-weight:normal}.section li.activity{padding:.2em;clear:both}.section .activity .activityinstance .groupinglabel{padding-left:30px}.dir-rtl .section .activity .activityinstance .groupinglabel{padding-right:30px}.section .activity .availabilityinfo,.section .activity .contentafterlink{margin-top:.5em;margin-left:30px}.dir-rtl .section .activity .availabilityinfo,.dir-rtl .section .activity .contentafterlink{margin-right:30px;margin-left:0}.section .activity .contentafterlink p{margin:.5em 0}.editing .section .activity:hover,.editing .section .activity.action-menu-shown{background-color:#eee}.course-content .current{background-color:#d9edf7}.course-content .section-summary{margin-top:5px;list-style:none;border:1px solid #DDD}.course-content .section-summary .section-title{margin:2px 5px 10px 5px}.course-content .section-summary .summarytext{margin:2px 5px 2px 5px}.course-content .section-summary .section-summary-activities .activity-count{display:inline-block;margin:3px;font-size:11.9px;color:#999;white-space:nowrap}.course-content .section-summary .summary{margin-top:5px}.course-content .single-section{margin-top:1em}.course-content .single-section .section-navigation{display:block;padding:.5em;margin-bottom:-0.5em}.course-content .single-section .section-navigation .title{clear:both;font-size:108%;font-weight:bold}.course-content .single-section .section-navigation .mdl-left{float:left;margin-right:1em;font-weight:normal}.dir-rtl .course-content .single-section .section-navigation .mdl-left{float:right}.course-content .single-section .section-navigation .mdl-left .larrow{margin-right:.1em}.course-content .single-section .section-navigation .mdl-right{float:right;margin-left:1em;font-weight:normal}.dir-rtl .course-content .single-section .section-navigation .mdl-right{float:left}.course-content .single-section .section-navigation .mdl-right .rarrow{margin-left:.1em}.course-content .single-section .section-navigation .mdl-bottom{margin-top:0}.course-content ul li.section.main{margin-top:0;border-bottom:2px solid #eee}.course-content ul li.section.hidden{opacity:.5}.course-content ul.topics li.section .content,.course-content ul.weeks li.section .content{padding:0;margin-right:20px;margin-left:20px}.course-content{margin-top:0}.course-content ul.topics li.section{padding-bottom:20px}.course-content ul.topics li.section .summary{margin-left:25px}.path-course-view .completionprogress{margin-left:25px}.path-course-view .completionprogress{position:relative;z-index:1000;display:block;float:right;height:20px}#page-site-index .subscribelink{text-align:right}#site-news-forum h2,#frontpage-course-list h2,#frontpage-category-names h2,#frontpage-category-combo h2{margin-bottom:9px}.path-course-view a.reduce-sections{padding-left:.2em}.path-course-view .subscribelink{text-align:right}.path-course-view .unread{margin-left:30px}.dir-rtl.path-course-view .unread{margin-right:30px}.path-course-view .block.drag .header{cursor:move}.path-course-view .completionprogress{text-align:right}.dir-rtl.path-course-view .completionprogress{text-align:left}.path-course-view .single-section .completionprogress{margin-right:5px}.path-course-view .section .summary{line-height:normal}.path-site li.activity>div,.path-course-view li.activity>div{position:relative;padding:0 16px 0 0}.dir-rtl.path-site li.activity>div,.dir-rtl.path-course-view li.activity>div{position:relative;padding:0 0 0 16px}.path-course-view li.activity span.autocompletion img{vertical-align:text-bottom}.path-course-view li.activity form.togglecompletion img{max-width:none}.path-course-view li.activity form.togglecompletion .ajaxworking{position:absolute;top:3px;right:22px;width:16px;height:16px;background:url([[pix:i/ajaxloader]]) no-repeat}.dir-rtl.path-course-view .completionprogress{float:none}.dir-rtl.path-course-view li.activity form.togglecompletion .ajaxworking{right:-22px}li.section.hidden span.commands a.editing_hide,li.section.hidden span.commands a.editing_show{cursor:default}ul.weeks h3.sectionname{white-space:nowrap}.editing ul.weeks h3.sectionname{white-space:normal}.single-section h3.sectionname{clear:both;text-align:center}.section img.movetarget{width:80px;height:16px}input.titleeditor{width:330px;vertical-align:text-bottom}span.editinstructions{position:absolute;top:0;z-index:9999;padding:.1em .4em;margin-top:-22px;margin-left:30px;font-size:11.9px;line-height:16px;color:#3a87ad;text-decoration:none;background-color:#d9edf7;border:1px solid #bce8f1;-webkit-box-shadow:2px 2px 5px 1px #ccc;-moz-box-shadow:2px 2px 5px 1px #ccc;box-shadow:2px 2px 5px 1px #ccc}#dndupload-status{position:absolute;z-index:9999;z-index:0;width:40%;padding:6px;margin:0 30%;color:#3a87ad;text-align:center;background:#d9edf7;border:1px solid #bce8f1;-webkit-border-bottom-right-radius:8px;border-bottom-right-radius:8px;-webkit-border-bottom-left-radius:8px;border-bottom-left-radius:8px;-moz-border-radius-bottomright:8px;-moz-border-radius-bottomleft:8px;-webkit-box-shadow:2px 2px 5px 1px #ccc;-moz-box-shadow:2px 2px 5px 1px #ccc;box-shadow:2px 2px 5px 1px #ccc}.dndupload-preview{padding:.3em;margin-top:.2em;color:#909090;list-style:none;border:1px dashed #909090}.dndupload-preview img.icon{padding:0;vertical-align:text-bottom}.dndupload-progress-outer{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.dndupload-progress-inner{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.dndupload-hidden{display:none}#page-course-pending .singlebutton,#page-course-index .singlebutton,#page-course-index-category .singlebutton,#page-course-editsection .singlebutton{text-align:center}#page-admin-course-manage #movecourses td img{margin:0 .22em;vertical-align:text-bottom}#page-admin-course-manage #movecourses td img.icon{padding:0}#coursesearch{margin-top:1em;text-align:center}#page-course-pending .pendingcourserequests{margin-bottom:1em}#page-course-pending .pendingcourserequests .singlebutton{display:inline}#page-course-pending .pendingcourserequests .cell{padding:0 5px}#page-course-pending .pendingcourserequests .cell.c6{white-space:nowrap}.coursebox{padding:5px;margin-bottom:15px;border:1px dotted #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.coursebox>.info>.coursename a{display:block;padding-left:21px;background-image:url([[pix:moodle|i/course]]);background-position:center left;background-repeat:no-repeat}.coursebox.remotehost>.info>.categoryname a{background-image:url([[pix:moodle|i/mnethost]])}.coursebox>.info>.coursename,.coursebox .content .teachers,.coursebox .content .courseimage,.coursebox .content .coursefile{float:left;width:40%;clear:left}.coursebox>.info>h3.coursename{margin:5px}.coursebox>.info>.coursename{padding:0;margin:5px}.coursebox .content .teachers li{padding:0;margin:0;list-style-type:none}.coursebox .enrolmenticons{float:right;padding:3px 0}.coursebox .moreinfo{float:right;padding:3px 0}.coursebox .enrolmenticons img,.coursebox .moreinfo img{margin:0 .2em}.coursebox .content{clear:both}.coursebox .content .summary,.coursebox .content .coursecat{float:right;width:55%}.coursebox .content .coursecat{clear:right;text-align:right}.coursebox.remotecoursebox .remotecourseinfo{float:left;width:40%}.coursebox .content .courseimage img{max-width:100px;max-height:100px}.coursebox .content .coursecat,.coursebox .content .summary,.coursebox .content .courseimage,.coursebox .content .coursefile,.coursebox .content .teachers,.coursebox.remotecoursebox .remotecourseinfo{padding:0;margin:3px 5px}.dir-rtl .coursebox>.info>.categoryname a{padding-right:21px;padding-left:0;background-position:center right}.dir-rtl .coursebox>.info>.categoryname,.dir-rtl .coursebox .teachers,.dir-rtl .coursebox .content .courseimage,.dir-rtl .coursebox .content .coursefile{float:right;clear:right}.dir-rtl .coursebox .enrolmenticons,.dir-rtl .coursebox .moreinfo{float:left}.dir-rtl .coursebox .summary,.dir-rtl .coursebox .coursecat{float:left}.dir-rtl .coursebox .coursecat{clear:left;text-align:left}.coursebox.collapsed{margin-bottom:0}.coursebox.collapsed>.content{display:none}.courses .coursebox.collapsed{padding:5px;border:1px solid #eee}.courses .coursebox.even{background-color:#f6f6f6}.courses .coursebox:hover,.course_category_tree .courses>.paging.paging-morelink:hover{background-color:#eee}.course_category_tree .category .numberofcourse{font-size:11.9px}.course_category_tree .controls{visibility:hidden}.course_category_tree .controls div{display:inline;cursor:pointer}.jsenabled .course_category_tree .controls{visibility:visible}.course_category_tree .controls{float:right;margin-bottom:5px;text-align:right}.course_category_tree .controls div{padding-right:2em;font-size:75%}.course_category_tree .category>.info>.categoryname{padding:2px 18px;margin:3px;background-image:url([[pix:moodle|t/collapsed_empty]]);background-position:center left;background-repeat:no-repeat}.dir-rtl .course_category_tree .category>.info>.categoryname{background-image:url([[pix:moodle|t/collapsed_empty_rtl]]);background-position:center right}.course_category_tree .category.with_children>.info>.categoryname{cursor:pointer;background-image:url([[pix:moodle|t/expanded]])}.course_category_tree .category.with_children.collapsed>.info>.categoryname{background-image:url([[pix:moodle|t/collapsed]])}.dir-rtl .course_category_tree .category.with_children.collapsed>.info>.categoryname{background-image:url([[pix:moodle|t/collapsed_rtl]])}.course_category_tree .category.collapsed>.content{display:none}.course_category_tree .category>.info{min-height:20px;min-height:0;padding:19px;padding:0;margin:3px 0;margin-bottom:20px;margin-bottom:3px;clear:both;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.course_category_tree .category>.info blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.course_category_tree.frontpage-category-names .category>.info{margin:0;background:0;border:0}.course_category_tree .category>.content{padding-left:16px}.dir-rtl .course_category_tree .category>.content{padding-right:16px;padding-left:0}.course_category_tree .subcategories>.paging,.courses>.paging{padding:5px;margin:0;text-align:center}.courses>.paging.paging-morelink,.course_category_tree .subcategories>.paging.paging-morelink{text-align:left}.course_category_tree .paging.paging-morelink a{font-size:11.9px}.dir-rtl .courses>.paging.paging-morelink,.dir-rtl .course_category_tree .paging.paging-morelink{text-align:right}#page-course-index-category .generalbox.info{padding:5px;margin-bottom:15px;border:1px dotted #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}#page-course-index-category .categorypicker{margin:10px 0 20px;text-align:center}.section .summary .iconsmall,.section .activity .iconsmall{width:16px;height:16px}.section .editing_title .iconsmall{width:12px;height:12px;padding:4px 8px 0 0;margin:8px 8px 0 0;vertical-align:text-bottom}.section .moodle-actionmenu .iconsmall{width:16px;height:16px;max-width:none!important;padding:4px;vertical-align:text-bottom}.section .moodle-actionmenu[data-enhanced] .menu img{width:12px;height:12px}#course-category-listings{margin-bottom:200px;background-color:#fff}#course-category-listings.columns-2>#course-listing>div{position:relative;left:-1px}#course-category-listings.columns-3>#course-listing>div{height:100%}#course-category-listings>div>div{min-height:300px;border:1px solid #e1e1e8}#course-category-listings>div>div>ul.ml>li:first-child>div{border-top:0}#course-category-listings h3{padding:.4rem .6rem .3rem;margin:0;background-color:#f5f5f5;border-bottom:1px solid #e1e1e8}#course-category-listings h4{padding:.6rem 1rem .5rem;margin:1rem 0 0}#course-category-listings .moodle-actionmenu{white-space:nowrap}#course-category-listings .moodle-actionmenu[data-enhance] .toggle-display img{width:auto}#course-category-listings .moodle-actionmenu[data-enhance] .toggle-display.textmenu{padding-right:4px}#course-category-listings .moodle-actionmenu[data-enhance] .toggle-display.textmenu .caret{margin-top:12px}#course-category-listings .listing-actions{padding:.4rem .3rem .3rem;line-height:2.2em;text-align:center}#course-category-listings .listing-actions>.moodle-actionmenu{display:inline-block}#course-category-listings .listing-actions>.moodle-actionmenu .menu a{padding-left:1rem}#course-category-listings .listing-actions .iconsmall{vertical-align:text-bottom}#course-category-listings .listing-actions .moodle-actionmenu:not([data-enhanced]) li{line-height:normal}#course-category-listings .listing-actions .moodle-actionmenu:not([data-enhanced])>.menubar a{display:inline-block;color:inherit}#course-category-listings .listing-actions .moodle-actionmenu:not([data-enhanced])>.menubar a>img{display:none}#course-category-listings .listing-actions .moodle-actionmenu:not([data-enhanced])>.menu .menu-action-text{display:inline-block}#course-category-listings ul.ml{margin:1rem 0;list-style:none}#course-category-listings ul.ml ul.ml{margin:0}#course-category-listings li{line-height:2.2em}#course-category-listings li>div:hover{background-color:#fafafa}#course-category-listings li .tree-icon{margin:2px 6px 0 0;vertical-align:text-top}#course-category-listings li[data-selected='1']>div{background-color:#ffffd8;border-top-color:#e1e1e8;border-bottom-color:#f5f5f5}#course-category-listings li[data-selected='1'] li:first-of-type>div,#course-category-listings li[data-selected='1'][data-expandable='0']+li>div{border-top-color:#e1e1e8}#course-category-listings li[data-selected='1']:last-of-type>div{border-bottom-color:#e1e1e8}#course-category-listings li .tree-icon{margin-left:0}#course-category-listings li li .tree-icon{margin-left:1em}#course-category-listings li li li .tree-icon{margin-left:2em}#course-category-listings li li li li .tree-icon{margin-left:3em}#course-category-listings li li li li li .tree-icon{margin-left:4em}#course-category-listings li li li li li li .tree-icon{margin-left:4.5em}#course-category-listings li li li li li li li .tree-icon{margin-left:5em}#course-category-listings li li li li li li li li .tree-icon{margin-left:5.5em}#course-category-listings li+li>div,#course-category-listings li:first-child>div{border-top-color:#f5f5f5}#course-category-listings .item-actions{display:inline-block;display:initial;margin-right:1em}#course-category-listings .item-actions img{margin:0 4px}#course-category-listings .item-actions .menu a{padding:4px 1em 4px 4px}#course-category-listings .item-actions .menu img{width:12px;max-width:none}#course-category-listings .listitem>div>.float-left{float:left}#course-category-listings .listitem>div>.float-right{float:right;text-align:right}#course-category-listings .listitem>div .item-actions .action-show{display:none}#course-category-listings .listitem>div .item-actions .action-hide{display:inline}#course-category-listings .listitem>div .without-actions{color:#333}#course-category-listings .listitem>div .idnumber{margin-right:2em;color:#a1a1a8}#course-category-listings .listitem[data-visible="0"]{color:#999}#course-category-listings .listitem[data-visible="0"] a.categoryname{color:#999}#course-category-listings .listitem[data-visible="0"]>div>a{color:#999}#course-category-listings .listitem[data-visible="0"]>div .item-actions .action-show{display:inline}#course-category-listings .listitem[data-visible="0"]>div .item-actions .action-hide{display:none}#course-category-listings .listitem[data-visible="0"]>ul .item-actions.category-item-actions .action-hide,#course-category-listings .listitem[data-visible="0"]>ul .item-actions.category-item-actions .action-show{display:none}#course-category-listings .listitem.highlight{background-color:transparent}#course-category-listings .listitem.highlight>div,#course-category-listings .listitem.highlight>div:hover,#course-category-listings .listitem.highlight[data-selected='1']>div{background-color:#dfa}#course-category-listings #course-listing .listitem .categoryname{display:inline-block;margin-left:1em;color:#a1a1a8}#course-category-listings #course-listing .listitem .coursename{display:inline-block}#course-category-listings #course-listing .listitem .drag-handle{display:inline-block;margin:0 6px 0 0}#course-category-listings #course-listing .listitem>div{padding-left:1rem}#course-category-listings #course-listing>.firstpage .listitem:first-child>div .item-actions .action-moveup,#course-category-listings #course-listing>.lastpage .listitem:last-child>div .item-actions .action-movedown{display:none}#course-category-listings #course-listing .bulk-action-checkbox{margin:-2px 6px 0 0;vertical-align:middle}#course-category-listings #category-listing .listitem.collapsed>ul.ml{display:none}#course-category-listings #category-listing .listitem>div>.ba-checkbox{width:2.2em;padding-top:2px;margin:-1px .5em 0 0;text-align:center;vertical-align:middle}#course-category-listings #category-listing .listitem.highlight>div>.ba-checkbox{background-color:#dfa}#course-category-listings #category-listing .listitem[data-selected='1']>div>.ba-checkbox{padding:0;margin:0 .5em 0 0;background-color:inherit}#course-category-listings #category-listing .listitem:first-child>div .item-actions .action-moveup,#course-category-listings #category-listing .listitem:last-child>div .item-actions .action-movedown{display:none}#course-category-listings #category-listing .course-count{display:inline-block;min-width:3.5em;margin-right:2rem;color:#a1a1a8}#course-category-listings #category-listing .course-count .smallicon{width:.8rem;height:.8rem;margin:0 .3rem;vertical-align:middle}#course-category-listings #category-listing .bulk-action-checkbox{margin-right:-3px;vertical-align:middle}#course-category-listings #category-listing .category-listing>ul>.listitem:first-child{position:relative}#course-category-listings #category-listing .category-bulk-actions{position:relative;margin:0 .5em .5em}#course-category-listings .detail-pair{margin:0 1rem;border-bottom:1px solid #e1e1e8}#course-category-listings .detail-pair>*{display:inline-block;line-height:2.2rem}#course-category-listings .detail-pair .pair-key{font-weight:bold;vertical-align:top}#course-category-listings .detail-pair .pair-key span{display:block;margin-right:1rem}#course-category-listings .detail-pair .pair-value select{max-width:100%}#course-category-listings .bulk-actions .detail-pair>*{display:block;width:100%}#course-category-listings .listing-pagination{text-align:center}#course-category-listings .listing-pagination .yui3-button{margin:.4rem .2rem .45rem;font-size:10.4px;background-color:#FFF;border:0}#course-category-listings .listing-pagination .yui3-button.active-page{background-color:#e5effd}#course-category-listings .listing-pagination-totals{text-align:center}#course-category-listings .listing-pagination-totals.dimmed{margin:.4rem 1rem .45rem;color:#999}#course-category-listings .select-a-category .notifymessage,#course-category-listings .select-a-category .alert{margin:1em}.dir-rtl #course-category-listings #category-listing,.dir-rtl #course-category-listings #course-listing{float:right;margin-left:0}.dir-rtl #course-category-listings .listitem>div>.float-left{float:right}.dir-rtl #course-category-listings .listitem>div>.float-right{float:left;text-align:left}.dir-rtl #course-category-listings li .tree-icon{margin:2px 0 0 6px}.dir-rtl #course-category-listings li .tree-icon{margin-right:0}.dir-rtl #course-category-listings li li .tree-icon{margin-right:1em}.dir-rtl #course-category-listings li li li .tree-icon{margin-right:2em}.dir-rtl #course-category-listings li li li li .tree-icon{margin-right:3em}.dir-rtl #course-category-listings li li li li li .tree-icon{margin-right:4em}.dir-rtl #course-category-listings li li li li li li .tree-icon{margin-right:4.5em}.dir-rtl #course-category-listings li li li li li li li .tree-icon{margin-right:5em}.dir-rtl #course-category-listings li li li li li li li li .tree-icon{margin-right:5.5em}.dir-rtl #course-category-listings #category-listing .listitem>div{margin-right:.5em;margin-left:0}.dir-rtl #course-category-listings #category-listing .listitem>div>.ba-checkbox{margin:-1px 0 0 .5em}.dir-rtl #course-category-listings #category-listing .listitem[data-selected='1']>div>.ba-checkbox{margin:0 0 0 .5em}.dir-rtl #course-category-listings #category-listing .course-count{margin-left:2rem}.dir-rtl #course-category-listings #category-listing .bulk-action-checkbox{margin-right:0;margin-left:-3px}.dir-rtl #course-category-listings #course-listing{padding-right:24px}.dir-rtl #course-category-listings #course-listing .listitem .idnumber{padding-right:2em;color:#a1a1a8}.dir-rtl #course-category-listings #course-listing .listitem .categoryname{display:inline-block;margin-right:1em;margin-left:0}.dir-rtl #course-category-listings #course-listing .listitem .drag-handle{margin:0 6px 0 6px}.dir-rtl #course-category-listings #course-listing .listitem>div{padding-left:1rem}.dir-rtl #course-category-listings #course-listing .bulk-action-checkbox{margin:-2px 0 0 6px;vertical-align:middle}.dir-rtl #course-category-listings .detail-pair .pair-key span{margin-right:0;margin-left:0}.coursecat-management-header{vertical-align:middle}.coursecat-management-header h2{display:inline-block;text-align:left}.coursecat-management-header>div{display:inline-block;float:right;margin:10px 0;margin-left:1em;line-height:40px}.coursecat-management-header select{max-width:300px;padding:.4em .5em .45em 1em;white-space:nowrap;vertical-align:baseline;cursor:pointer}.coursecat-management-header .moodle-actionmenu{white-space:nowrap}.coursecat-management-header .moodle-actionmenu[data-enhanced].show .menu a{padding-left:1em}.dir-rtl .coursecat-management-header h2{text-align:right}.dir-rtl .coursecat-management-header>div{float:left;margin-right:1em;margin-left:0}.course-being-dragged-proxy{padding:0 0 0 4em;color:#08c;vertical-align:middle;border:0}.course-being-dragged{opacity:.5;filter:alpha(opacity=50)}@media(min-width:1200px) and (max-width:1600px){#course-category-listings.columns-3{background-color:transparent;border:0}#course-category-listings.columns-3 #category-listing,#course-category-listings.columns-3 #course-listing{width:50%}#course-category-listings.columns-3 #category-listing>div,#course-category-listings.columns-3 #course-listing>div,#course-category-listings.columns-3 #course-detail>div{background-color:#FFF;border:1px solid #e1e1e8}#course-category-listings.columns-3 #course-detail{width:100%;margin-top:1em}}@media(max-width:1199px){#course-category-listings.columns-2,#course-category-listings.columns-3{background-color:transparent;border:0}#course-category-listings.columns-2 #category-listing,#course-category-listings.columns-3 #category-listing,#course-category-listings.columns-2 #course-listing,#course-category-listings.columns-3 #course-listing,#course-category-listings.columns-2 #course-detail,#course-category-listings.columns-3 #course-detail{width:100%;margin:0 0 1em}#course-category-listings.columns-2 #category-listing>div,#course-category-listings.columns-3 #category-listing>div,#course-category-listings.columns-2 #course-listing>div,#course-category-listings.columns-3 #course-listing>div,#course-category-listings.columns-2 #course-detail>div,#course-category-listings.columns-3 #course-detail>div{background-color:#FFF;border:1px solid #e1e1e8}}.filemanager,.filepicker,.file-picker{font-size:11px}.filemanager a,.file-picker a,.filemanager a:hover,.file-picker a:hover{color:#555;text-decoration:none}.filemanager input[type="text"],.file-picker input[type="text"]{width:265px}.filemanager .fp-license td,.file-picker .fp-setlicense td{max-width:265px}.filemanager .fp-license select,.file-picker .fp-setlicense select{max-width:100%}.fp-content-center{display:table-cell;width:100%;height:100%;vertical-align:middle}.fp-content-hidden{visibility:hidden}.yui3-panel-focused{outline:0}#filesskin .yui3-panel-content{display:inline-block;*display:inline;padding-bottom:20px;background:#f2f2f2;border:1px solid #fff;-webkit-border-radius:8px;-moz-border-radius:8px;border-radius:8px;*zoom:1;-webkit-box-shadow:5px 5px 20px 0 #666;-moz-box-shadow:5px 5px 20px 0 #666;box-shadow:5px 5px 20px 0 #666}#filesskin .yui3-widget-hd{padding:5px;font-size:12px;letter-spacing:1px;color:#333;text-align:center;text-shadow:1px 1px 1px #fff;background-color:#ebebeb;background-image:-moz-linear-gradient(top,#fff,#ccc);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#ccc));background-image:-webkit-linear-gradient(top,#fff,#ccc);background-image:-o-linear-gradient(top,#fff,#ccc);background-image:linear-gradient(to bottom,#fff,#ccc);background-repeat:repeat-x;border-bottom:1px solid #bbb;-webkit-border-radius:10px 10px 0 0;-moz-border-radius:10px 10px 0 0;border-radius:10px 10px 0 0;filter:dropshadow(color=#ffffff,offx=1,offy=1);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffcccccc',GradientType=0)}.fp-panel-button{display:inline-block;*display:inline;padding:3px 20px 2px 20px;margin:10px;text-align:center;background:#fff;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;*zoom:1;-webkit-box-shadow:2px 2px 3px .1px #999;-moz-box-shadow:2px 2px 3px .1px #999;box-shadow:2px 2px 3px .1px #999}.moodle-dialogue-base .filepicker .moodle-dialogue-wrap .moodle-dialogue-bd{padding:0}#filesskin .file-picker.fp-generallayout{position:relative;width:859px;background:#fff;border:1px solid #ccc;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px}.file-picker .fp-repo-area{display:inline-block;*display:inline;float:left;width:180px;height:525px;overflow:auto;border-right:1px solid #bbb;*zoom:1}.dir-rtl .file-picker .fp-repo-area{float:right;border-right:0;border-left:1px solid #bbb}.file-picker .fp-repo-items{float:left;width:693px}.dir-rtl .file-picker .fp-repo-items{float:right}.file-picker .fp-navbar{min-height:48px;background:#f2f2f2;border-bottom:1px solid #bbb}.file-picker .fp-navbar .fp-viewbar{margin:9px}.file-picker .fp-content{height:432px;overflow:auto;clear:both;background:#fff}.filepicker.moodle-dialogue-fullscreen .file-picker .fp-content{width:100%}.file-picker .fp-content-loading{display:table;width:100%;height:100%;text-align:center}.file-picker .fp-content .fp-object-container{width:98%;height:98%}.dir-rtl .file-picker .fp-list{text-align:right}.dir-rtl .file-picker .fp-toolbar{padding:9px}.dir-rtl .file-picker .fp-list{text-align:right}.dir-rtl .file-picker .fp-repo-name{display:inline}.dir-rtl .file-picker .fp-pathbar{display:block;text-align:right;border-top:0}.dir-rtl .file-picker div.bd{text-align:right}.dir-rtl #filemenu .yuimenuitemlabel{text-align:right}.dir-rtl .filepicker .yui-layout-unit-left{left:500px}.dir-rtl .filepicker .yui-layout-unit-center{left:0}.dir-rtl .filemanager-toolbar a{padding:0}.file-picker .fp-list{float:left;width:100%;padding:0;margin:0;list-style-type:none}.dir-rtl .file-picker .fp-list{float:left;text-align:right}.file-picker .fp-list .fp-repo a{display:block;padding:.5em .7em}.file-picker .fp-list .fp-repo.active{background:#f2f2f2}.file-picker .fp-list .fp-repo-icon{width:16px;height:16px;padding:0 7px 0 5px}.fp-toolbar{float:left}.dir-rtl .fp-toolbar{float:right}.fp-toolbar.empty{display:none}.dir-rtl .fp-toolbar div.disabled,.fp-toolbar .disabled{display:none}.fp-toolbar div{display:block;float:left;margin-right:9px}.dir-rtl .fp-toolbar div{display:block;float:right;margin-right:0;margin-left:9px}.fp-toolbar img{margin-right:5px;vertical-align:-15%}.fp-toolbar .fp-tb-search{width:235px;height:27px}.fp-toolbar .fp-tb-search input{width:200px;height:27px;padding:2px 6px 1px 27px;background:#fff url('[[pix:a/search]]') no-repeat 7px 7px;border:1px solid #bbb}.fp-viewbar{float:right;height:30px;background:white;border:1px solid #CCC;border-bottom:1px solid #b3b3b3;border-radius:4px}.fp-repo-items fp-viewbar{margin:9px}.dir-rtl .fp-toolbar img{vertical-align:-35%}.dir-rtl .fp-viewbar{float:left}.fp-viewbar a{display:block;float:left;width:40px;height:30px;border-right:1px solid #CCC}.fp-viewbar a:hover{background-color:#ebebeb;background-image:radial-gradient(ellipse at center,#fff 60%,#dfdfdf 100%)}.fp-viewbar a:active{background-color:#dfdfdf;background-image:radial-gradient(ellipse at center,#fff 40%,#dfdfdf 100%)}.fp-viewbar a.fp-vb-icons{border-radius:4px 0 0 4px}.fp-viewbar a.fp-vb-tree{border-right:0;border-radius:0 4px 4px 0}.fp-viewbar a img{margin:7px 12px}.fp-viewbar a.checked{background-color:#dfdfdf}.fp-viewbar.disabled a{cursor:default;background:0;opacity:.45}.file-picker .fp-clear-left{clear:left}.dir-rtl .filemanager-toolbar .fp-vb-icons a:hover{background:url('[[pix:theme|fp/view_icon_selected]]')}.dir-rtl .filemanager-toolbar .fp-vb-icons.checked a:hover{background:url('[[pix:theme|fp/view_icon_active]]') no-repeat 0 0}.dir-rtl .fp-vb-details a:hover{background:0;border:20px solid black}.dir-rtl .fp-vb-details.checked a:hover{background:0;border:40px solid black}.dir-rtl .fp-vb-tree a:hover{background:0;border:30px solid black}.dir-rtl .fp-vb-tree.checked a:hover{background:0;border:50px solid black}.file-picker .fp-pathbar{display:table-row}.fp-pathbar.empty{display:none}.fp-pathbar .fp-path-folder{width:27px;height:12px;margin-left:4px;background:url('[[pix:theme|fp/path_folder]]') no-repeat 0 0}.dir-rtl .fp-pathbar .fp-path-folder{width:auto;height:12px;margin-left:4px;background:url('[[pix:theme|fp/path_folder_rtl]]') no-repeat right top}.dir-rtl .fp-pathbar span{display:inline-block;*display:inline;float:right;margin-left:32px;*zoom:1}.fp-pathbar .fp-path-folder-name{margin-left:32px;line-height:20px}.dir-rtl .fp-pathbar .fp-path-folder-name{margin-right:32px;line-height:20px}.fp-iconview .fp-file{position:relative;float:left;margin:10px 10px 35px;text-align:center}.fp-iconview .fp-thumbnail{display:block;min-width:110px;min-height:110px;line-height:110px;text-align:center;border:1px solid #fff}.fp-iconview .fp-thumbnail img{padding:3px;vertical-align:middle;border:1px solid #ddd;-webkit-box-shadow:1px 1px 2px 0 #ccc;-moz-box-shadow:1px 1px 2px 0 #ccc;box-shadow:1px 1px 2px 0 #ccc}.fp-iconview .fp-thumbnail:hover{background:#fff;border:1px solid #ddd;-webkit-box-shadow:inset 0 0 10px 0 #ccc;-moz-box-shadow:inset 0 0 10px 0 #ccc;box-shadow:inset 0 0 10px 0 #ccc}.fp-iconview .fp-filename-field{position:absolute;height:33px;overflow:hidden;word-wrap:break-word}.fp-iconview .fp-filename-field:hover{z-index:1000;overflow:visible}.fp-iconview .fp-filename-field .fp-filename{min-width:112px;padding-top:5px;padding-bottom:12px;background:#fff}.dir-rtl .fp-iconview .fp-file{float:right}.file-picker .yui3-datatable table{width:100%;border:0 solid #bbb}#filesskin .file-picker .yui3-datatable-header{color:#555;background:#fff;border-bottom:1px solid #ccc;border-left:0 solid #fff}#filesskin .file-picker .yui3-datatable-odd .yui3-datatable-cell{background-color:#f6f6f6;border-left:0 solid #f6f6f6}#filesskin .file-picker .yui3-datatable-even .yui3-datatable-cell{background-color:#fff;border-left:0 solid #fff}.dir-rtl .file-picker .yui3-datatable-header{text-align:right}.file-picker .ygtvtn,.filemanager .ygtvtn{width:17px;height:22px;background:url('[[pix:moodle|y/tn]]') 0 0 no-repeat}.dir-rtl .filemanager .ygtvtn,.dir-rtl .file-picker .ygtvtn{width:17px;height:22px;background:url('[[pix:moodle|y/tn_rtl]]') 0 0 no-repeat}.file-picker .ygtvtm,.filemanager .ygtvtm{width:13px;height:12px;cursor:pointer;background:url('[[pix:moodle|y/tm]]') 0 10px no-repeat}.file-picker .ygtvtmh,.filemanager .ygtvtmh{width:13px;height:12px;cursor:pointer;background:url('[[pix:moodle|y/tm]]') 0 10px no-repeat}.file-picker .ygtvtp,.filemanager .ygtvtp{width:13px;height:12px;cursor:pointer;background:url('[[pix:moodle|y/tp]]') 0 10px no-repeat}.dir-rtl .file-picker .ygtvtp,.dir-rtl .filemanager .ygtvtp{background:url('[[pix:moodle|y/tp_rtl]]') 0 10px no-repeat}.file-picker .ygtvtph,.filemanager .ygtvtph{width:13px;height:22px;cursor:pointer;background:url('[[pix:moodle|y/tp]]') 0 10px no-repeat}.dir-rtl .file-picker .ygtvtph,.dir-rtl .filemanager .ygtvtph{background:url('[[pix:moodle|y/tp_rtl]]') 0 10px no-repeat}.file-picker .ygtvln,.filemanager .ygtvln{width:17px;height:22px;background:url('[[pix:moodle|y/ln]]') 0 0 no-repeat}.dir-rtl .file-picker .ygtvln,.dir-rtl .filemanager .ygtvln{background:url('[[pix:moodle|y/ln_rtl]]') 0 0 no-repeat}.file-picker .ygtvlm,.filemanager .ygtvlm{width:13px;height:12px;cursor:pointer;background:url('[[pix:moodle|y/lm]]') 0 10px no-repeat}.file-picker .ygtvlmh,.filemanager .ygtvlmh{width:13px;height:12px;cursor:pointer;background:url('[[pix:moodle|y/lm]]') 0 10px no-repeat}.file-picker .ygtvlp,.filemanager .ygtvlp{width:13px;height:12px;cursor:pointer;background:url('[[pix:moodle|y/lp]]') 0 10px no-repeat}.dir-rtl .file-picker .ygtvlp,.dir-rtl .filemanager .ygtvlp{background:url('[[pix:moodle|y/lp_rtl]]') 0 10px no-repeat}.file-picker .ygtvlph,.filemanager .ygtvlph{width:13px;height:12px;cursor:pointer;background:url('[[pix:moodle|y/lp]]') 0 10px no-repeat}.dir-rtl .file-picker .ygtvlph,.dir-rtl .filemanager .ygtvlph{background:url('[[pix:moodle|y/lp_rtl]]') 0 10px no-repeat}.file-picker .ygtvloading,.filemanager .ygtvloading{width:16px;height:22px;background:transparent url('[[pix:moodle|y/loading]]') 0 0 no-repeat}.file-picker .ygtvdepthcell,.filemanager .ygtvdepthcell{width:17px;height:32px;background:url('[[pix:moodle|y/vline]]') 0 0 no-repeat}.file-picker .ygtvblankdepthcell,.filemanager .ygtvblankdepthcell{width:17px;height:22px}a.ygtvspacer:hover{color:transparent;text-decoration:none}.ygtvlabel,.ygtvlabel:link,.ygtvlabel:visited,.ygtvlabel:hover{margin-left:2px;text-decoration:none;cursor:pointer;background-color:transparent}.file-picker .ygtvfocus,.filemanager .ygtvfocus{background-color:#eee}.fp-filename-icon{position:relative;display:block;margin-top:10px}.fp-icon{float:left;width:24px;height:24px;margin-top:-7px;margin-right:10px;line-height:24px;text-align:center}.dir-rtl .fp-icon{float:right;margin-right:0;margin-left:10px}.fp-icon img{max-width:24px;max-height:24px;vertical-align:middle}.fp-filename{padding-right:10px}.dir-rtl .fp-filename{padding-right:0;padding-left:10px}.file-picker .fp-login-form{display:table;width:100%;height:100%}.file-picker .fp-login-form table{margin:0 auto}.file-picker .fp-login-form p{margin-top:3em;text-align:center}.file-picker .fp-login-form .fp-login-input label{display:block;text-align:right}.file-picker .fp-login-form .fp-login-input .input{text-align:left}.file-picker .fp-login-form input[type="checkbox"]{width:15px;height:15px}.file-picker .fp-upload-form{display:table;width:100%;height:100%}.file-picker .fp-upload-form table{margin:0 auto}.file-picker.fp-dlg{text-align:center}.file-picker.fp-dlg .fp-dlg-text{padding:30px 20px 10px;font-size:12px}.file-picker.fp-dlg .fp-dlg-buttons{margin:0 20px}.file-picker.fp-msg{text-align:center}.file-picker.fp-msg .fp-msg-text{max-width:500px;max-height:300px;min-width:200px;padding:40px 20px 10px 20px;overflow:auto;font-size:12px}.file-picker.fp-msg.fp-msg-error .fp-msg-text{padding:40px 20px 10px 20px;font-size:12px}.file-picker .fp-content-error{display:table;width:100%;height:100%;text-align:center}.file-picker .fp-content-error .fp-error{display:table-cell;width:100%;height:100%;padding:40px 20px 10px 20px;font-size:12px;vertical-align:middle}.file-picker .fp-nextpage{clear:both}.file-picker .fp-nextpage .fp-nextpage-loading{display:none}.file-picker .fp-nextpage.loading .fp-nextpage-link{display:none}.file-picker .fp-nextpage.loading .fp-nextpage-loading{display:block;height:100px;padding-top:50px;text-align:center}.fp-select form{padding:20px 20px 0}.fp-select .fp-select-loading{margin-top:20px;text-align:center}.fp-select .fp-hr{width:auto;height:1px;margin:10px 0;clear:both;background-color:#fff;border-bottom:1px solid #bbb}.fp-select table{padding:0 0 10px}.fp-select table .mdl-right{min-width:84px}.fp-select .fp-reflist .mdl-right{vertical-align:top}.fp-select .fp-select-buttons{float:right}.fp-select .fp-info{display:block;padding:1px 20px 0;clear:both}.fp-select .fp-thumbnail{float:left;min-width:110px;min-height:110px;margin:10px 20px 0 0;line-height:110px;text-align:center;background:#fff;border:1px solid #ddd;-webkit-box-shadow:inset 0 0 10px 0 #ccc;-moz-box-shadow:inset 0 0 10px 0 #ccc;box-shadow:inset 0 0 10px 0 #ccc}.fp-select .fp-thumbnail img{padding:3px;margin:10px;vertical-align:middle;border:1px solid #ddd}.fp-select .fp-fileinfo{display:inline-block;*display:inline;margin-top:10px;*zoom:1}.file-picker.fp-select .fp-fileinfo{max-width:240px}.fp-select .fp-fileinfo div{padding-bottom:5px}.file-picker.fp-select .uneditable{display:none}.file-picker.fp-select .fp-select-loading{display:none}.file-picker.fp-select.loading .fp-select-loading{display:block}.file-picker.fp-select.loading form{display:none}.fp-select .fp-dimensions.fp-unknown{display:none}.filemanager-loading{display:none}.jsenabled .filemanager-loading{display:block;margin-top:100px}.filemanager.fm-loading .filemanager-toolbar,.filemanager.fm-loading .fp-pathbar,.filemanager.fm-loading .filemanager-container,.filemanager.fm-loaded .filemanager-loading,.filemanager.fm-maxfiles .fp-btn-add,.filemanager.fm-maxfiles .dndupload-message,.filemanager.fm-noitems .fp-btn-download,.filemanager .fm-empty-container,.filemanager.fm-noitems .filemanager-container .fp-content{display:none}.filemanager .filemanager-updating{display:none;text-align:center}.filemanager.fm-updating .filemanager-updating{display:block;margin-top:37px}.filemanager.fm-updating .fm-content-wrapper,.filemanager.fm-nomkdir .fp-btn-mkdir,.fitem.disabled .filemanager .filemanager-toolbar,.fitem.disabled .filemanager .fp-pathbar,.fitem.disabled .filemanager .fp-restrictions,.fitem.disabled .filemanager .fm-content-wrapper{display:none}.fp-restrictions{text-align:right}.filemanager .fp-navbar{background:#f2f2f2;border:1px solid #bbb;border-bottom:0}.filemanager-toolbar{padding:9px;overflow:hidden}.fp-pathbar{min-height:20px;padding:5px 8px 1px;border-top:1px solid #bbb}.file-picker .fp-toolbar{padding:9px}.fp-toolbar .fp-btn-add,.fp-toolbar .fp-btn-download,.fp-toolbar .fp-btn-mkdir,.fp-toolbar .fp-tb-help,.fp-toolbar .fp-tb-manage,.fp-toolbar .fp-tb-logout,.fp-toolbar .fp-tb-refresh{width:40px;height:30px;background:white;border:1px solid #CCC;border-bottom:1px solid #b3b3b3;border-radius:4px}.fp-toolbar a:hover{background-color:#ebebeb;background-image:radial-gradient(ellipse at center,#fff 60%,#dfdfdf 100%)}.fp-toolbar a:active{background-color:#dfdfdf;background-image:radial-gradient(ellipse at center,#fff 40%,#dfdfdf 100%)}.fp-btn-add a,.fp-btn-download a,.fp-btn-mkdir a,.fp-tb-help a,.fp-tb-manage a,.fp-tb-logout a,.fp-tb-refresh a{display:block;width:40px;height:30px;border-radius:4px}.fp-btn-add img,.fp-btn-download img,.fp-btn-mkdir img,.fp-tb-help img,.fp-tb-manage img,.fp-tb-logout img,.fp-tb-refresh img{margin:7px 12px}.filemanager .fp-pathbar.empty{display:none}.filepicker-filelist,.filemanager-container{position:relative;min-height:140px;overflow:auto;clear:both;background:#fff;border:1px solid #bbb}.filemanager .fp-content{max-height:472px;min-height:157px;overflow:auto}.filemanager-container,.filepicker-filelist{overflow:hidden}.fitem.disabled .filepicker-filelist,.fitem.disabled .filemanager-container{background-color:#ebebe4}.fitem.disabled .fp-btn-choose{color:#999}.fitem.disabled .filepicker-filelist .filepicker-filename{display:none}.fp-iconview .fp-reficons1{position:absolute;top:0;left:0;width:100%;height:100%}.fp-iconview .fp-reficons2{position:absolute;top:0;left:0;width:100%;height:100%}.fp-iconview .fp-file.fp-hasreferences .fp-reficons1{background:url('[[pix:theme|fp/link]]') no-repeat;background-position:bottom right}.fp-iconview .fp-file.fp-isreference .fp-reficons2{background:url('[[pix:theme|fp/alias]]') no-repeat;background-position:bottom left}.filemanager .fp-iconview .fp-file.fp-originalmissing .fp-thumbnail img{display:none}.filemanager .fp-iconview .fp-file.fp-originalmissing .fp-thumbnail{background:url([[pix:s/dead]]) no-repeat;background-position:center center}.filemanager .yui3-datatable table{width:100%;border:0 solid #bbb}.filemanager .yui3-datatable-header{color:#555!important;background:#fff!important;border-bottom:1px solid #ccc!important;border-left:0 solid #fff!important}.filemanager .yui3-datatable-odd .yui3-datatable-cell{background-color:#f6f6f6!important;border-left:0 solid #f6f6f6}.filemanager .yui3-datatable-even .yui3-datatable-cell{background-color:#fff!important;border-left:0 solid #fff}.filemanager .fp-filename-icon.fp-hasreferences .fp-reficons1{position:absolute;top:8px;left:17px;z-index:1000;width:100%;height:100%;background:url('[[pix:theme|fp/link_sm]]') no-repeat 0 0}.filemanager .fp-filename-icon.fp-isreference .fp-reficons2{position:absolute;top:9px;left:-6px;z-index:1001;width:100%;height:100%;background:url('[[pix:theme|fp/alias_sm]]') no-repeat 0 0}.filemanager .fp-contextmenu{display:none}.filemanager .fp-iconview .fp-folder.fp-hascontextmenu .fp-contextmenu{position:absolute;right:7px;bottom:5px;display:block}.filemanager .fp-treeview .fp-folder.fp-hascontextmenu .fp-contextmenu,.filemanager .fp-tableview .fp-folder.fp-hascontextmenu .fp-contextmenu{position:absolute;top:6px;left:14px;display:inline;margin-right:-20px}.dir-rtl .filemanager .fp-iconview .fp-folder.fp-hascontextmenu .fp-contextmenu{right:inherit;left:7px}.dir-rtl .filemanager .fp-treeview .fp-folder.fp-hascontextmenu .fp-contextmenu,.dir-rtl .filemanager .fp-tableview .fp-folder.fp-hascontextmenu .fp-contextmenu{right:16px;left:inherit;margin-right:0}.filepicker-filelist .filepicker-container,.filemanager.fm-noitems .fm-empty-container{position:absolute;top:10px;right:10px;bottom:10px;left:10px;display:block;padding-top:85px;text-align:center;border:2px dashed #bbb}.filepicker-filelist .dndupload-target,.filemanager-container .dndupload-target{position:absolute;top:10px;right:10px;bottom:10px;left:10px;padding-top:85px;text-align:center;background:#fff;border:2px dashed #fb7979;-webkit-box-shadow:0 0 0 10px #fff;-moz-box-shadow:0 0 0 10px #fff;box-shadow:0 0 0 10px #fff}.filepicker-filelist.dndupload-over .dndupload-target,.filemanager-container.dndupload-over .dndupload-target{position:absolute;top:10px;right:10px;bottom:10px;left:10px;padding-top:85px;text-align:center;background:#fff;border:2px dashed #6c8cd3}.dndupload-message{display:none}.dndsupported .dndupload-message{display:inline}.dnduploadnotsupported-message{display:none}.dndnotsupported .dnduploadnotsupported-message{display:inline}.dndupload-target{display:none}.dndsupported .dndupload-ready .dndupload-target{display:block}.dndupload-uploadinprogress{display:none;text-align:center}.dndupload-uploading .dndupload-uploadinprogress{display:block}.dndupload-arrow{position:absolute;top:5px;width:100%;height:80px;margin-left:-28px;background:url([[pix:theme|fp/dnd_arrow]]) center no-repeat}.fitem.disabled .filepicker-container,.fitem.disabled .fm-empty-container{display:none}.dndupload-progressbars{display:none;padding:10px}.dndupload-inprogress .dndupload-progressbars{display:block}.dndupload-inprogress .fp-content{display:none}.filemanager.fm-noitems .dndupload-inprogress .fm-empty-container{display:none}.filepicker-filelist.dndupload-inprogress .filepicker-container{display:none}.filepicker-filelist.dndupload-inprogress a{display:none}.filemanager.fp-select .fp-select-loading{display:none}.filemanager.fp-select.loading .fp-select-loading{display:block}.filemanager.fp-select.loading form{display:none}.filemanager.fp-select.fp-folder .fp-license,.filemanager.fp-select.fp-folder .fp-author,.filemanager.fp-select.fp-file .fp-file-unzip,.filemanager.fp-select.fp-folder .fp-file-unzip,.filemanager.fp-select.fp-file .fp-file-zip,.filemanager.fp-select.fp-zip .fp-file-zip{display:none}.filemanager.fp-select .fp-file-setmain,.filemanager.fp-select .fp-file-setmain-help{display:none}.filemanager.fp-select.fp-cansetmain .fp-file-setmain,.filemanager.fp-select.fp-cansetmain .fp-file-setmain-help{display:inline-block;*display:inline;*zoom:1}.filemanager .fp-mainfile .fp-filename{font-weight:bold}.filemanager.fp-select.fp-folder .fp-file-download{display:none}.fm-operation{font-weight:bold}.filemanager.fp-select .fp-original.fp-unknown,.filemanager.fp-select .fp-original .fp-originloading{display:none}.filemanager.fp-select .fp-original.fp-loading .fp-originloading{display:inline}.filemanager.fp-select .fp-reflist.fp-unknown,.filemanager.fp-select .fp-reflist .fp-reflistloading{display:none}.filemanager.fp-select .fp-refcount{max-width:265px}.filemanager.fp-select .fp-reflist.fp-loading .fp-reflistloading{display:inline}.filemanager.fp-select .fp-reflist .fp-value{max-width:265px;max-height:75px;padding:8px 7px;margin:0;overflow:auto;background:#f9f9f9;border:1px solid #bbb}.filemanager.fp-select .fp-reflist .fp-value li{padding-bottom:7px}.filemanager.fp-mkdir-dlg{text-align:center}.filemanager.fp-mkdir-dlg .fp-mkdir-dlg-text{margin:20px;text-align:left}.dir-rtl .filemanager .fp-mkdir-dlg p{text-align:right}.filemanager.fp-dlg{text-align:center}.filemanager.fp-dlg .fp-dlg-text{max-width:340px;max-height:300px;min-width:200px;padding:0 10px;margin:40px 20px 20px;overflow:auto;font-size:12px;line-height:22px}.file-picker div.bd{text-align:left}.dir-rtl .file-picker div.bd,.dir-rtl .file-picker .fp-pathbar,.dir-rtl .file-picker .fp-list,.dir-rtl #filemenu .yuimenuitemlabel,.dir-rtl .filemanager-container .yui3-skin-sam .yui3-datatable-header{text-align:right}.dir-rtl .filepicker .yui-layout-unit-left{left:500px}.dir-rtl .filepicker .yui-layout-unit-center{left:0}.message-discussion-noframes h1{font-size:1em}.message-discussion-noframes #userinfo .commands,.message .noframesjslink,.message .link{font-size:11.9px}.message .heading{font-size:1em;font-weight:bold}.message .author{font-weight:bold}.message .time{font-style:italic}#page-message-user .commands span{font-size:.7em}#page-message-user .name{font-size:1.1em;font-weight:bold}table.message_search_results td{border-color:#ddd}.message .time,.message.me .author{color:#999}.message.other .author{color:#88c}#page-message-messages{padding:10px}#page-message-send .notifysuccess{padding:1px}#page-message-send td.fixeditor{text-align:center}.message .note{padding:10px}table.message .searchresults td{padding:5px}.message .contactselector{float:left;width:24%}.message .contactselector .contact{text-align:left}.message .contactselector .messageselecteduser{font-weight:bold}.message .contactselector .paging{position:relative;z-index:1}.message .messagearea{float:right;width:74%;min-height:200px;padding-left:1%;border-left:1px solid #d3d3d3}.message .messagearea .messagehistorytype{padding-bottom:20px;clear:both}.message .messagearea .messagehistory .message_user_pictures{margin-right:auto;margin-left:auto}.message .messagearea .messagehistory .message_user_pictures #user1{width:200px;vertical-align:top}.message .messagearea .messagehisto