Merge branch 'wip-mdl-33455' of git://github.com/rajeshtaneja/moodle
authorAparup Banerjee <aparup@moodle.com>
Tue, 5 Jun 2012 07:15:26 +0000 (15:15 +0800)
committerAparup Banerjee <aparup@moodle.com>
Tue, 5 Jun 2012 07:15:26 +0000 (15:15 +0800)
59 files changed:
admin/index.php
admin/oauth2callback.php
admin/registration/confirmregistration.php
admin/registration/forms.php
admin/registration/hubselector.php [deleted file]
admin/registration/index.php
admin/registration/register.php
admin/registration/renderer.php
admin/registration/renewregistration.php
admin/renderer.php
admin/settings/server.php
admin/settings/top.php
backup/moodle2/restore_stepslib.php
files/renderer.php
grade/edit/tree/grade.php
install.php
lang/en/admin.php
lang/en/hub.php
lang/en/repository.php
lang/en/webservice.php
lib/completionlib.php
lib/configonlylib.php
lib/cronlib.php
lib/db/access.php
lib/evalmath/evalmath.class.php
lib/filebrowser/file_info.php
lib/filebrowser/file_info_stored.php
lib/filestorage/stored_file.php
lib/form/filemanager.js
lib/moodlelib.php
lib/oauthlib.php
lib/phpunit/lib.php
lib/tablelib.php
lib/tests/configonlylib_test.php [new file with mode: 0644]
lib/tests/mathslib_test.php
lib/tests/moodlelib_test.php
mod/assign/feedback/comments/locallib.php
mod/assign/feedbackplugin.php
mod/assign/gradingtable.php
mod/assign/locallib.php
mod/book/tool/print/index.php
mod/forum/lang/en/forum.php
mod/forum/lib.php
mod/forum/unsubscribeall.php
mod/quiz/report/grading/report.php
phpunit.xml.dist
portfolio/googledocs/lib.php
portfolio/picasa/lib.php
rating/index.php
repository/dropbox/lang/en/repository_dropbox.php
repository/filepicker.js
repository/googledocs/lib.php
repository/lib.php
repository/picasa/lib.php
repository/recent/lib.php
repository/repository_ajax.php
repository/upload/lib.php
theme/base/style/filemanager.css
version.php

index bf3eea5..d4a7d4e 100644 (file)
@@ -44,11 +44,6 @@ if (!function_exists('iconv')) {
     echo 'Moodle requires the iconv PHP extension. Please install or enable the iconv extension.';
     die();
 }
-if (iconv('UTF-8', 'UTF-8//IGNORE', 'abc') !== 'abc') {
-    // known to be broken in mid-2011 MAMP installations
-    echo 'Broken iconv PHP extension detected, installation/upgrade can not continue.';
-    die();
-}
 
 define('NO_OUTPUT_BUFFERING', true);
 
@@ -434,6 +429,10 @@ $availableupdates = $updateschecker->get_update_info('core',
     array('minmaturity' => $CFG->updateminmaturity, 'notifybuilds' => $CFG->updatenotifybuilds));
 $availableupdatesfetch = $updateschecker->get_last_timefetched();
 
+$buggyiconvnomb = (!function_exists('mb_convert_encoding') and @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
+//check if the site is registered on Moodle.org
+$registered = $DB->count_records('registration_hubs', array('huburl' => HUB_MOODLEORGHUBURL, 'confirmed' => 1));
+
 admin_externalpage_setup('adminnotifications');
 
 if ($fetchupdates) {
@@ -444,4 +443,5 @@ if ($fetchupdates) {
 
 $output = $PAGE->get_renderer('core', 'admin');
 echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed,
-        $cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch);
+        $cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb,
+        $registered);
index 364c002..c032a9c 100644 (file)
@@ -33,6 +33,14 @@ require_once(dirname(dirname(__FILE__)).'/config.php');
 // The authorization code generated by the authorization server.
 $code = required_param('code', PARAM_RAW);
 // The state parameter we've given (used in moodle as a redirect url).
-$state = required_param('state', PARAM_URL);
+$state = required_param('state', PARAM_LOCALURL);
 
-redirect(new moodle_url($state, array('code' => $code)));
+$redirecturl = new moodle_url($state);
+$params = $redirecturl->params();
+
+if (isset($params['sesskey']) and confirm_sesskey($params['sesskey'])) {
+    $redirecturl->param('oauth2code', $code);
+    redirect($redirecturl);
+} else {
+    print_error('invalidsesskey');
+}
index 12afb50..e7c8288 100644 (file)
@@ -44,7 +44,7 @@ $hubname = optional_param('hubname', '', PARAM_TEXT);
 $token = optional_param('token', '', PARAM_TEXT);
 $error = optional_param('error', '', PARAM_ALPHANUM);
 
-admin_externalpage_setup('registrationindex');
+admin_externalpage_setup('registrationhubs');
 
 if (!empty($error) and $error == 'urlalreadyexist') {
     throw new moodle_exception('urlalreadyregistered', 'hub',
index 48c2cd9..0126722 100644 (file)
@@ -236,6 +236,7 @@ class site_registration_form extends moodleform {
         $geolocation = get_config('hub', 'site_geolocation_' . $cleanhuburl);
         $contactable = get_config('hub', 'site_contactable_' . $cleanhuburl);
         $emailalert = get_config('hub', 'site_emailalert_' . $cleanhuburl);
+        $emailalert = ($emailalert === 0) ? 0 : 1;
         $coursesnumber = get_config('hub', 'site_coursesnumber_' . $cleanhuburl);
         $usersnumber = get_config('hub', 'site_usersnumber_' . $cleanhuburl);
         $roleassignmentsnumber = get_config('hub', 'site_roleassignmentsnumber_' . $cleanhuburl);
@@ -279,9 +280,6 @@ class site_registration_form extends moodleform {
         $mform->setType('description', PARAM_TEXT);
         $mform->addHelpButton('description', 'sitedesc', 'hub');
 
-        $mform->addElement('static', 'urlstring', get_string('siteurl', 'hub'), $CFG->wwwroot);
-        $mform->addHelpButton('urlstring', 'siteurl', 'hub');
-
         $languages = get_string_manager()->get_list_of_languages();
         collatorlib::asort($languages);
         $mform->addElement('select', 'language', get_string('sitelang', 'hub'),
@@ -290,16 +288,6 @@ class site_registration_form extends moodleform {
         $mform->addHelpButton('language', 'sitelang', 'hub');
         $mform->setDefault('language', $language);
 
-        $mform->addElement('static', 'versionstring', get_string('siteversion', 'hub'), $CFG->version);
-        $mform->addElement('hidden', 'moodleversion', $CFG->version);
-        $mform->setType('moodleversion', PARAM_INT);
-        $mform->addHelpButton('versionstring', 'siteversion', 'hub');
-
-        $mform->addElement('static', 'releasestring', get_string('siterelease', 'hub'), $CFG->release);
-        $mform->addElement('hidden', 'moodlerelease', $CFG->release);
-        $mform->setType('moodlerelease', PARAM_TEXT);
-        $mform->addHelpButton('releasestring', 'siterelease', 'hub');
-
         $mform->addElement('textarea', 'address', get_string('postaladdress', 'hub'),
                 array('rows' => 4, 'cols' => 41));
         $mform->setType('address', PARAM_TEXT);
@@ -360,6 +348,20 @@ class site_registration_form extends moodleform {
         //TODO site logo
         $mform->addElement('hidden', 'imageurl', ''); //TODO: temporary
         $mform->setType('imageurl', PARAM_URL);
+
+        $mform->addElement('static', 'urlstring', get_string('siteurl', 'hub'), $CFG->wwwroot);
+        $mform->addHelpButton('urlstring', 'siteurl', 'hub');
+
+        $mform->addElement('static', 'versionstring', get_string('siteversion', 'hub'), $CFG->version);
+        $mform->addElement('hidden', 'moodleversion', $CFG->version);
+        $mform->setType('moodleversion', PARAM_INT);
+        $mform->addHelpButton('versionstring', 'siteversion', 'hub');
+
+        $mform->addElement('static', 'releasestring', get_string('siterelease', 'hub'), $CFG->release);
+        $mform->addElement('hidden', 'moodlerelease', $CFG->release);
+        $mform->setType('moodlerelease', PARAM_TEXT);
+        $mform->addHelpButton('releasestring', 'siterelease', 'hub');
+
         /// Display statistic that are going to be retrieve by the hub
         $coursecount = $DB->count_records('course') - 1;
         $usercount = $DB->count_records('user', array('deleted' => 0));
diff --git a/admin/registration/hubselector.php b/admin/registration/hubselector.php
deleted file mode 100644 (file)
index 6bb215f..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-<?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/>.
-
-/*
- * @package    moodle
- * @subpackage registration
- * @author     Jerome Mouneyrac <jerome@mouneyrac.com>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
- * @copyright  (C) 1999 onwards Martin Dougiamas  http://dougiamas.com
- *
- * Thsi page displays a hub selector or a hub URL + password. Then it will redirect to
- * the site registration form (with the selected hub as parameter)
-*/
-
-require('../../config.php');
-
-require_once($CFG->libdir.'/adminlib.php');
-require_once($CFG->dirroot.'/' . $CFG->admin . '/registration/forms.php');
-
-admin_externalpage_setup('registrationselector');
-
-$hubselectorform = new hub_selector_form();
-$fromform = $hubselectorform->get_data();
-
-//// Redirect to the registration form if an URL has been choosen ////
-
-$selectedhuburl = optional_param('publichub', false, PARAM_URL);
-$unlistedhuburl = optional_param('unlistedurl', false, PARAM_TEXT);
-$password = optional_param('password', '', PARAM_RAW);
-
-if (!empty($unlistedhuburl)) {
-    if (clean_param($unlistedhuburl, PARAM_URL) !== '') {
-        $huburl = $unlistedhuburl;
-    }
-} else if (!empty($selectedhuburl)) {
-    $huburl = $selectedhuburl;
-}
-
-
-//redirect
-if (!empty($huburl) and confirm_sesskey()) {
-    $hubname = optional_param(clean_param($huburl, PARAM_ALPHANUMEXT), '', PARAM_TEXT);
-    $params = array('sesskey' => sesskey(), 'huburl' => $huburl,
-            'password' => $password, 'hubname' => $hubname);
-    redirect(new moodle_url($CFG->wwwroot."/" . $CFG->admin . "/registration/register.php",
-            $params));
-}
-
-
-//// OUTPUT ////
-
-echo $OUTPUT->header();
-echo $OUTPUT->heading(get_string('registeron', 'hub'), 3, 'main');
-$hubselectorform->display();
-echo $OUTPUT->footer();
\ No newline at end of file
index 02e5cde..4c841ae 100644 (file)
@@ -22,8 +22,9 @@
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
  * @copyright  (C) 1999 onwards Martin Dougiamas  http://dougiamas.com
  *
- * On this page the administrator select if he wants to register on Moodle.org or
- * a specific hub
+ * On this page the administrator selects which hub he wants to register,
+ * except for MOOCH. Admins can register with MOOCH with the top admin menu "Registration" link.
+ * On this page the administrator can also unregister from any hubs, including MOOCH.
  */
 
 require('../../config.php');
@@ -34,7 +35,7 @@ require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/forms.php');
 require_once($CFG->dirroot . '/course/publish/lib.php');
 require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
 
-admin_externalpage_setup('registrationindex');
+admin_externalpage_setup('registrationhubs');
 
 $renderer = $PAGE->get_renderer('core', 'register');
 
@@ -126,13 +127,15 @@ if (empty($cancel) and $unregistration and $confirm and confirm_sesskey()) {
     }
 }
 
-echo $OUTPUT->header();
-
-//do not check sesskey if confirm = false because this script is linked into email message
-if (!empty($errormessage)) {
-    echo $OUTPUT->notification(get_string('unregistrationerror', 'hub', $errormessage));
-}
 if (empty($cancel) and $unregistration and !$confirm) {
+
+    echo $OUTPUT->header();
+
+    //do not check sesskey if confirm = false because this script is linked into email message
+    if (!empty($errormessage)) {
+        echo $OUTPUT->notification(get_string('unregistrationerror', 'hub', $errormessage));
+    }
+
     $hub = $registrationmanager->get_registeredhub($huburl);
     echo $OUTPUT->heading(get_string('unregisterfrom', 'hub', $hub->hubname), 3, 'main');
     if ($cleanregdata) {
@@ -142,6 +145,7 @@ if (empty($cancel) and $unregistration and !$confirm) {
         $siteunregistrationform = new site_unregistration_form('',
                         array('huburl' => $huburl, 'hubname' => $hub->hubname));
     }
+
     $siteunregistrationform->display();
 } else {
     $registeredonmoodleorg = false;
@@ -150,8 +154,49 @@ if (empty($cancel) and $unregistration and !$confirm) {
         $registeredonmoodleorg = true;
     }
 
-    echo $OUTPUT->heading(get_string('registeron', 'hub'), 3, 'main');
-    echo $renderer->registrationselector($registeredonmoodleorg);
+    // load the hub selector form
+    $hubselectorform = new hub_selector_form();
+    $fromform = $hubselectorform->get_data();
+    $selectedhuburl = optional_param('publichub', false, PARAM_URL);
+    $unlistedhuburl = optional_param('unlistedurl', false, PARAM_TEXT);
+    $password = optional_param('password', '', PARAM_RAW);
+
+    if (!empty($unlistedhuburl)) {
+        if (clean_param($unlistedhuburl, PARAM_URL) !== '') {
+            $huburl = $unlistedhuburl;
+        }
+    } else if (!empty($selectedhuburl)) {
+        $huburl = $selectedhuburl;
+    }
+
+    // a hub has been selected, redirect to the hub registration page
+    if (empty($cancel) and !empty($huburl) and confirm_sesskey()) {
+        $hubname = optional_param(clean_param($huburl, PARAM_ALPHANUMEXT), '', PARAM_TEXT);
+        $params = array('sesskey' => sesskey(), 'huburl' => $huburl,
+            'password' => $password, 'hubname' => $hubname);
+        redirect(new moodle_url($CFG->wwwroot . "/" . $CFG->admin . "/registration/register.php",
+                        $params));
+    }
+
+    echo $OUTPUT->header();
+
+    //check if the site is registered on Moodle.org and display a message about registering on MOOCH
+    $registered = $DB->count_records('registration_hubs', array('huburl' => HUB_MOODLEORGHUBURL, 'confirmed' => 1));
+    if (empty($registered)) {
+        $warningmsg = get_string('registermoochtips', 'hub');
+        $warningmsg .= $renderer->single_button(new moodle_url('register.php', array('huburl' => HUB_MOODLEORGHUBURL
+                    , 'hubname' => 'Moodle.org')), get_string('register', 'admin'));
+        echo $renderer->box($warningmsg, 'buttons mdl-align generalbox adminwarning');
+    }
+
+    //do not check sesskey if confirm = false because this script is linked into email message
+    if (!empty($errormessage)) {
+        echo $OUTPUT->notification(get_string('unregistrationerror', 'hub', $errormessage));
+    }
+
+    echo $OUTPUT->heading(get_string('registerwith', 'hub'));
+
+    $hubselectorform->display();
 
     if (extension_loaded('xmlrpc')) {
         $hubs = $registrationmanager->get_registered_on_hubs();
index eac6400..7a6bc92 100644 (file)
@@ -27,7 +27,7 @@
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
  * @copyright  (C) 1999 onwards Martin Dougiamas  http://dougiamas.com
  *
- * This page displays the site registration form.
+ * This page displays the site registration form for Moodle.org/MOOCH or for a different hub.
  * It handles redirection to the hub to continue the registration workflow process.
  * It also handles update operation by web service.
  */
@@ -39,15 +39,17 @@ require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/forms.php');
 require_once($CFG->dirroot . '/webservice/lib.php');
 require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
 
-admin_externalpage_setup('registrationindex');
-
 $huburl = required_param('huburl', PARAM_URL);
 $huburl = rtrim($huburl, "/");
+
+if ($huburl == HUB_MOODLEORGHUBURL) { // register to Moodle.org
+    admin_externalpage_setup('registrationmoodleorg');
+} else { //register to a hub
+    admin_externalpage_setup('registrationhub');
+}
+
 $password = optional_param('password', '', PARAM_TEXT);
 $hubname = optional_param('hubname', '', PARAM_TEXT);
-if (!confirm_sesskey()) {
-    throw new moodle_exception('missingparameter');
-}
 
 $registrationmanager = new registration_manager();
 
@@ -145,5 +147,12 @@ if (!empty($error)) {
     echo $error;
 }
 
+//some Moodle.org resitration explanation
+if ($huburl == HUB_MOODLEORGHUBURL) {
+    echo $OUTPUT->heading(get_string('registerwithmoodleorg', 'admin'));
+    $renderer = $PAGE->get_renderer('core', 'register');
+    echo $renderer->moodleorg_registration_message();
+}
+
 $siteregistrationform->display();
 echo $OUTPUT->footer();
index fdec5fd..d5ca165 100644 (file)
  */
 class core_register_renderer extends plugin_renderer_base {
 
+    /**
+     * Display Moodle.org registration message about benefit to register on Moodle.org
+     *
+     * @return string
+     */
+    public function moodleorg_registration_message() {
+        $moodleorgurl = html_writer::link('http://moodle.org', 'Moodle.org');
+        $moodleorgstatsurl = html_writer::link('http://moodle.org/stats', get_string('statsmoodleorg', 'admin'));
+        $moochurl = html_writer::link(HUB_MOODLEORGHUBURL, 'MOOCH');
+        $moodleorgregmsg = get_string('registermoodleorg', 'admin', $moodleorgurl);
+        $items = array(get_string('registermoodleorgli1', 'admin'),
+            get_string('registermoodleorgli2', 'admin', $moodleorgstatsurl),
+            get_string('registermoodleorgli3', 'admin', $moochurl));
+        $moodleorgregmsg .= html_writer::alist($items);
+        return $moodleorgregmsg;
+    }
+
     /**
      * Display a box message confirming a site registration (add or update)
      * @param string $confirmationmessage
@@ -42,57 +59,6 @@ class core_register_renderer extends plugin_renderer_base {
         return $this->output->box($message);
     }
 
-    /**
-     * Display the page to register on Moodle.org or on a specific hub
-     */
-    public function registrationselector($updatemoodleorg = false) {
-        global $CFG;
-        $table = new html_table();
-        $table->head = array(get_string('moodleorg', 'hub'), get_string('specifichub', 'hub'));
-        $table->size = array('50%', '50%');
-        //$table->attributes['class'] = 'registerindextable';
-        //Moodle.org information cell
-        $moodleorgcell = get_string('moodleorgregistrationdetail', 'hub');
-        $moodleorgcell .= html_writer::empty_tag('br') . html_writer::empty_tag('br');
-        $moodleorgcell = html_writer::tag('div', $moodleorgcell, array('class' => 'justifytext'));
-
-        //Specific hub information cell
-        $specifichubcell = get_string('specifichubregistrationdetail', 'hub');
-        $specifichubcell .= html_writer::empty_tag('br') . html_writer::empty_tag('br');
-        $specifichubcell = html_writer::tag('div', $specifichubcell, array('class' => 'justifytext'));
-
-        //add information cells
-        $cells = array($moodleorgcell, $specifichubcell);
-        $row = new html_table_row($cells);
-        $table->data[] = $row;
-
-        //Moodle.org button cell
-        $registeronmoodleorgurl = new moodle_url("/" . $CFG->admin . "/registration/register.php",
-                        array('sesskey' => sesskey(), 'huburl' => HUB_MOODLEORGHUBURL
-                            , 'hubname' => 'Moodle.org'));
-        $registeronmoodleorgbutton = new single_button($registeronmoodleorgurl,
-                        $updatemoodleorg ? get_string('updatesite', 'hub', 'Moodle.org') : get_string('registeronmoodleorg', 'hub'));
-        $registeronmoodleorgbutton->class = 'centeredbutton';
-        $registeronmoodleorgbuttonhtml = $this->output->render($registeronmoodleorgbutton);
-        $moodleorgcell = $registeronmoodleorgbuttonhtml;
-
-        //Specific hub button cell
-        $registeronspecifichuburl = new moodle_url("/" . $CFG->admin . "/registration/hubselector.php",
-                        array('sesskey' => sesskey()));
-        $registeronspecifichubbutton = new single_button($registeronspecifichuburl,
-                        get_string('registeronspecifichub', 'hub'));
-        $registeronspecifichubbutton->class = 'centeredbutton';
-        $registeronspecifichubbuttonhtml = $this->output->render($registeronspecifichubbutton);
-        $specifichubcell = $registeronspecifichubbuttonhtml;
-
-        //add button cells
-        $cells = array($moodleorgcell, $specifichubcell);
-        $row = new html_table_row($cells);
-        $table->data[] = $row;
-
-        return html_writer::table($table);
-    }
-
     /**
      * Display the listing of registered on hub
      */
index ec9fce2..dd15463 100644 (file)
@@ -39,7 +39,7 @@ $url = optional_param('url', '', PARAM_URL);
 $hubname = optional_param('hubname', '', PARAM_TEXT);
 $token = optional_param('token', '', PARAM_TEXT);
 
-admin_externalpage_setup('registrationindex');
+admin_externalpage_setup('registrationhubs');
 
 //check that we are waiting a confirmation from this hub, and check that the token is correct
 $registrationmanager = new registration_manager();
index 9b689a6..c064ca6 100644 (file)
@@ -242,13 +242,15 @@ class core_admin_renderer extends plugin_renderer_base {
      * @param bool $cronoverdue warn cron not running
      * @param bool $dbproblems warn db has problems
      * @param bool $maintenancemode warn in maintenance mode
+     * @param bool $buggyiconvnomb warn iconv problems
      * @param array|null $availableupdates array of available_update_info objects or null
      * @param int|null $availableupdatesfetch timestamp of the most recent updates fetch or null (unknown)
      *
      * @return string HTML to output.
      */
     public function admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed,
-            $cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch) {
+            $cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch,
+            $buggyiconvnomb, $registered) {
         global $CFG;
         $output = '';
 
@@ -257,9 +259,11 @@ class core_admin_renderer extends plugin_renderer_base {
         $output .= empty($CFG->disableupdatenotifications) ? $this->available_updates($availableupdates, $availableupdatesfetch) : '';
         $output .= $this->insecure_dataroot_warning($insecuredataroot);
         $output .= $this->display_errors_warning($errorsdisplayed);
+        $output .= $this->buggy_iconv_warning($buggyiconvnomb);
         $output .= $this->cron_overdue_warning($cronoverdue);
         $output .= $this->db_problems($dbproblems);
         $output .= $this->maintenance_mode_warning($maintenancemode);
+        $output .= $this->registration_warning($registered);
 
         //////////////////////////////////////////////////////////////////////////////////////////////////
         ////  IT IS ILLEGAL AND A VIOLATION OF THE GPL TO HIDE, REMOVE OR MODIFY THIS COPYRIGHT NOTICE ///
@@ -381,6 +385,19 @@ class core_admin_renderer extends plugin_renderer_base {
         return $this->warning(get_string('displayerrorswarning', 'admin'));
     }
 
+    /**
+     * Render an appropriate message if iconv is buggy and mbstring missing.
+     * @param bool $buggyiconvnomb
+     * @return string HTML to output.
+     */
+    protected function buggy_iconv_warning($buggyiconvnomb) {
+        if (!$buggyiconvnomb) {
+            return '';
+        }
+
+        return $this->warning(get_string('warningiconvbuggy', 'admin'));
+    }
+
     /**
      * Render an appropriate message if cron has not been run recently.
      * @param bool $cronoverdue
@@ -512,6 +529,27 @@ class core_admin_renderer extends plugin_renderer_base {
         return $updateinfo;
     }
 
+    /**
+     * Display a warning about not being registered on Moodle.org if necesary.
+     *
+     * @param boolean $registered true if the site is registered on Moodle.org
+     * @return string HTML to output.
+     */
+    protected function registration_warning($registered) {
+
+        if (!$registered) {
+
+            $registerbutton = $this->single_button(new moodle_url('registration/register.php',
+                    array('huburl' =>  HUB_MOODLEORGHUBURL, 'hubname' => 'Moodle.org')),
+                    get_string('register', 'admin'));
+
+            return $this->warning( get_string('registrationwarning', 'admin')
+                    . '&nbsp;' . $this->help_icon('registration', 'admin') . $registerbutton );
+        }
+
+        return '';
+    }
+
     /**
      * Helper method to render the information about the available Moodle update
      *
index 0188b6d..461f06c 100644 (file)
@@ -219,7 +219,8 @@ $temp->add(new admin_setting_configselect('memcachedpconn', new lang_string('mem
 $ADMIN->add('server', $temp);
 
 
-$ADMIN->add('server', new admin_externalpage('adminregistration', new lang_string('registration','admin'), "$CFG->wwwroot/$CFG->admin/registration/index.php"));
+$ADMIN->add('server', new admin_externalpage('adminregistration', new lang_string('hubs', 'admin'),
+    "$CFG->wwwroot/$CFG->admin/registration/index.php"));
 
 // "update notifications" settingpage
 if (empty($CFG->disableupdatenotifications)) {
index 4c1295e..147a4e5 100644 (file)
@@ -10,12 +10,12 @@ $hassiteconfig = has_capability('moodle/site:config', $systemcontext);
 
 $ADMIN->add('root', new admin_externalpage('adminnotifications', new lang_string('notifications'), "$CFG->wwwroot/$CFG->admin/index.php"));
 
-$ADMIN->add('root', new admin_externalpage('registrationindex', new lang_string('registration','admin'),
-        "$CFG->wwwroot/$CFG->admin/registration/index.php"));
-$ADMIN->add('root', new admin_externalpage('registration', new lang_string('registeron','hub'),
+$ADMIN->add('root', new admin_externalpage('registrationmoodleorg', new lang_string('registration', 'admin'),
+        "$CFG->wwwroot/$CFG->admin/registration/register.php?huburl=" . HUB_MOODLEORGHUBURL . "&hubname=Moodle.org"));
+$ADMIN->add('root', new admin_externalpage('registrationhub', new lang_string('registerwith', 'hub'),
         "$CFG->wwwroot/$CFG->admin/registration/register.php", 'moodle/site:config', true));
-$ADMIN->add('root', new admin_externalpage('registrationselector', new lang_string('registeron','hub'),
-        "$CFG->wwwroot/$CFG->admin/registration/hubselector.php", 'moodle/site:config', true));
+$ADMIN->add('root', new admin_externalpage('registrationhubs', new lang_string('hubs', 'admin'),
+        "$CFG->wwwroot/$CFG->admin/registration/index.php", 'moodle/site:config', true));
 $ADMIN->add('root', new admin_externalpage('siteregistrationconfirmed',
         new lang_string('registrationconfirmed', 'hub'),
         $CFG->wwwroot."/".$CFG->admin."/registration/confirmregistration.php", 'moodle/site:config', true));
index 04bd38f..e6fc1d1 100644 (file)
@@ -1108,7 +1108,7 @@ class restore_section_structure_step extends restore_structure_step {
 
         // Annotate the section mapping, with restorefiles option if needed
         $this->set_mapping('course_section', $oldid, $newitemid, $restorefiles);
-        $this->set_mapping('course_sectionnumber', $oldsection, $section->section, $restorefiles);
+        $this->set_mapping('course_sectionnumber', $oldsection, $section->section);
 
         // set the new course_section id in the task
         $this->task->set_sectionid($newitemid);
@@ -1129,10 +1129,19 @@ class restore_section_structure_step extends restore_structure_step {
     public function process_availability($data) {
         global $DB;
         $data = (object)$data;
+
         $data->coursesectionid = $this->task->get_sectionid();
+
         // NOTE: Other values in $data need updating, but these (cm,
-        // grade items) have not yet been restored.
-        $DB->insert_record('course_sections_availability', $data);
+        // grade items) have not yet been restored, so are done later.
+
+        $newid = $DB->insert_record('course_sections_availability', $data);
+
+        // We do not need to map between old and new id but storing a mapping
+        // means it gets added to the backup_ids table to record which ones
+        // need updating. The mapping is stored with $newid => $newid for
+        // convenience.
+        $this->set_mapping('course_sections_availability', $newid, $newid);
     }
 
     protected function after_execute() {
@@ -1145,16 +1154,20 @@ class restore_section_structure_step extends restore_structure_step {
 
         $sectionid = $this->get_task()->get_sectionid();
 
-        // Get data object for current section availability (if any)
-        // TODO: This can be processing already existing records, we need to be able to know which ones
-        //       are the just restored ones, perhaps creating 'course_sections_availability' mappings for them.
-        // TODO: Also, this must avoid duplicates, so if one course module or one grade item already is being
-        //       used for some availability rule... we need to handle that carefully.
+        // Get data object for current section availability (if any).
         $data = $DB->get_record('course_sections_availability',
                 array('coursesectionid' => $sectionid), 'id, sourcecmid, gradeitemid', IGNORE_MISSING);
 
-        // Update mappings
+        // If it exists, update mappings.
         if ($data) {
+            // Only update mappings for entries which are created by this restore.
+            // Otherwise, when you restore to an existing course, it will mess up
+            // existing section availability entries.
+            if (!$this->get_mappingid('course_sections_availability', $data->id, false)) {
+                return;
+            }
+
+            // Update source cmid / grade id to new value.
             $data->sourcecmid = $this->get_mappingid('course_module', $data->sourcecmid);
             if (!$data->sourcecmid) {
                 $data->sourcecmid = null;
@@ -2574,7 +2587,7 @@ class restore_module_structure_step extends restore_structure_step {
                 'course' => $this->get_courseid(),
                 'section' => 1);
             $data->section = $DB->insert_record('course_sections', $sectionrec); // section 1
-            $this->set_mapping('course_sectionnumber', $oldsection, $sectionrec->section, $restorefiles);
+            $this->set_mapping('course_sectionnumber', $oldsection, 1); // Assign unmatching sections to section 1.
         }
         $data->groupingid= $this->get_mappingid('grouping', $data->groupingid);      // grouping
         if (!$CFG->enablegroupmembersonly) {                                         // observe groupsmemberonly
index 3728a23..2f5f5d4 100644 (file)
@@ -301,10 +301,9 @@ class core_files_renderer extends plugin_renderer_base {
      */
     private function fm_js_template_mkdir() {
         $rv = '
-<div class="fp-mkdir-dlg">
-    <p>New folder name:</p>
-    <input type="text"><br/>
-    <a class="{!}fp-dlg-butcreate fp-panel-button" href="#">'.get_string('create').'</a>
+<div class="filemanager fp-mkdir-dlg">
+    <div class="fp-mkdir-dlg-text">'.get_string('newfoldername','repository').'<br/><input type="text" /></div>
+    <a class="{!}fp-dlg-butcreate fp-panel-button" href="#">'.get_string('makeafolder').'</a>
     <a class="{!}fp-dlg-butcancel fp-panel-button" href="#">'.get_string('cancel').'</a>
 </div>';
         return preg_replace('/\{\!\}/', '', $rv);
@@ -382,15 +381,15 @@ class core_files_renderer extends plugin_renderer_base {
             <tr class="{!}fp-saveas"><td class="mdl-right"><label>'.get_string('name', 'moodle').'</label>:</td>
             <td class="mdl-left"><input type="text"/></td></tr>
             <tr class="{!}fp-author"><td class="mdl-right"><label>'.get_string('author', 'repository').'</label>:</td>
-            <td class="mdl-left"><input type="text" /></td></tr>
+            <td class="mdl-left"><input type="text"/></td></tr>
             <tr class="{!}fp-license"><td class="mdl-right"><label>'.get_string('chooselicense', 'repository').'</label>:</td>
             <td class="mdl-left"><select></select></td></tr>
             <tr class="{!}fp-path"><td class="mdl-right"><label>'.get_string('path', 'moodle').'</label>:</td>
             <td class="mdl-left"><select></select></td></tr>
             <tr class="{!}fp-original"><td class="mdl-right"><label>'.get_string('original', 'repository').'</label>:</td>
-            <td class="mdl-left"><span class="fp-originloading">'.$icon_progress.' '.$strloading.'</span><span class="fp-value"/></td></tr>
+            <td class="mdl-left"><span class="fp-originloading">'.$icon_progress.' '.$strloading.'</span><span class="fp-value"></span></td></tr>
             <tr class="{!}fp-reflist"><td class="mdl-right"><label>'.get_string('referenceslist', 'repository').'</label>:</td>
-            <td class="mdl-left"><p class="{!}fp-refcount"/><span class="fp-reflistloading">'.$icon_progress.' '.$strloading.'</span><ul class="fp-value"/></td></tr>
+            <td class="mdl-left"><p class="{!}fp-refcount"></p><span class="fp-reflistloading">'.$icon_progress.' '.$strloading.'</span><ul class="fp-value"></ul></td></tr>
         </table>
     </form>
     <p class="{!}fp-thumbnail"></p>
@@ -401,10 +400,10 @@ class core_files_renderer extends plugin_renderer_base {
         </p>
     </form>
     <div class="fp-fileinfo">
-        <div class="{!}fp-datemodified">'.get_string('lastmodified', 'moodle').': <span class="fp-value"/></div>
-        <div class="{!}fp-datecreated">'.get_string('datecreated', 'repository').': <span class="fp-value"/></div>
-        <div class="{!}fp-size">'.get_string('size', 'repository').': <span class="fp-value"/></div>
-        <div class="{!}fp-dimensions">'.get_string('dimensions', 'repository').': <span class="fp-value"/></div>
+        <div class="{!}fp-datemodified">'.get_string('lastmodified', 'moodle').': <span class="fp-value"></span></div>
+        <div class="{!}fp-datecreated">'.get_string('datecreated', 'repository').': <span class="fp-value"></span></div>
+        <div class="{!}fp-size">'.get_string('size', 'repository').': <span class="fp-value"></span></div>
+        <div class="{!}fp-dimensions">'.get_string('dimensions', 'repository').': <span class="fp-value"></span></div>
     </div>
 </div>';
         return preg_replace('/\{\!\}/', '', $rv);
@@ -515,7 +514,7 @@ class core_files_renderer extends plugin_renderer_base {
 <div class="file-picker fp-generallayout">
     <div class="fp-repo-area">
         <ul class="fp-list">
-            <li class="{!}fp-repo"><a href="#"><img class="{!}fp-repo-icon" width="16" height="16" />&nbsp;<span class="{!}fp-repo-name" /span></a></li>
+            <li class="{!}fp-repo"><a href="#"><img class="{!}fp-repo-icon" width="16" height="16" />&nbsp;<span class="{!}fp-repo-name"></span></a></li>
         </ul>
     </div>
     <div class="fp-repo-items">
@@ -523,7 +522,7 @@ class core_files_renderer extends plugin_renderer_base {
             <div>
                 <div class="{!}fp-toolbar">
                     <div class="{!}fp-tb-back"><a href="#">'.get_string('back', 'repository').'</a></div>
-                    <div class="{!}fp-tb-search fp-search"><form/></div>
+                    <div class="{!}fp-tb-search"><form></form></div>
                     <div class="{!}fp-tb-refresh"><a href="#"><img src="'.$this->pix_url('a/refresh').'" /></a></div>
                     <div class="{!}fp-tb-logout"><img src="'.$this->pix_url('a/logout').'" /><a href="#"></a></div>
                     <div class="{!}fp-tb-manage"><a href="#"><img src="'.$this->pix_url('a/setting').'" /> '.get_string('manageurl', 'repository').'</a></div>
@@ -534,7 +533,7 @@ class core_files_renderer extends plugin_renderer_base {
                     <a class="{!}fp-vb-details" href="#"></a>
                     <a class="{!}fp-vb-tree" href="#"></a>
                 </div>
-                <div class="fp-clear-right"></div>
+                <div class="fp-clear-left"></div>
             </div>
             <div class="fp-pathbar">
                  <span class="{!}fp-path-folder"><a class="{!}fp-path-folder-name" href="#"></a></span>
@@ -690,12 +689,12 @@ class core_files_renderer extends plugin_renderer_base {
     </form>
     <p class="{!}fp-thumbnail"></p>
     <div class="fp-fileinfo">
-        <div class="{!}fp-datemodified">'.get_string('lastmodified', 'moodle').': <span class="fp-value"/></div>
-        <div class="{!}fp-datecreated">'.get_string('datecreated', 'repository').': <span class="fp-value"/></div>
-        <div class="{!}fp-size">'.get_string('size', 'repository').': <span class="fp-value"/></div>
-        <div class="{!}fp-license">'.get_string('license', 'moodle').': <span class="fp-value"/></div>
-        <div class="{!}fp-author">'.get_string('author', 'repository').': <span class="fp-value"/></div>
-        <div class="{!}fp-dimensions">'.get_string('dimensions', 'repository').': <span class="fp-value"/></div>
+        <div class="{!}fp-datemodified">'.get_string('lastmodified', 'moodle').': <span class="fp-value"></span></div>
+        <div class="{!}fp-datecreated">'.get_string('datecreated', 'repository').': <span class="fp-value"></span></div>
+        <div class="{!}fp-size">'.get_string('size', 'repository').': <span class="fp-value"></span></div>
+        <div class="{!}fp-license">'.get_string('license', 'moodle').': <span class="fp-value"></span></div>
+        <div class="{!}fp-author">'.get_string('author', 'repository').': <span class="fp-value"></span></div>
+        <div class="{!}fp-dimensions">'.get_string('dimensions', 'repository').': <span class="fp-value"></span></div>
     </div>
 </div>';
         return preg_replace('/\{\!\}/', '', $rv);
@@ -736,7 +735,7 @@ class core_files_renderer extends plugin_renderer_base {
                     <td class="mdl-left"><input type="text"/></td></tr>
                 <tr class="{!}fp-setlicense">
                     <td class="mdl-right"><label>'.get_string('chooselicense', 'repository').'</label>:</td>
-                    <td class="mdl-left"><select/></td></tr>
+                    <td class="mdl-left"><select></select></td></tr>
             </table>
         </form>
         <div><button class="{!}fp-upload-btn">'.get_string('upload', 'repository').'</button></div>
@@ -771,7 +770,7 @@ class core_files_renderer extends plugin_renderer_base {
      */
     private function fp_js_template_error() {
         $rv = '
-<div class="fp-content-error" ><div class="{!}fp-error" /></div>';
+<div class="fp-content-error" ><div class="{!}fp-error"></div></div>';
         return preg_replace('/\{\!\}/', '', $rv);
     }
 
@@ -817,7 +816,7 @@ class core_files_renderer extends plugin_renderer_base {
     <p class="{!}fp-dlg-text"></p>
     <a class="{!}fp-dlg-butoverwrite fp-panel-button" href="#">'.get_string('overwrite', 'repository').'</a>
     <a class="{!}fp-dlg-butcancel fp-panel-button" href="#">'.get_string('cancel').'</a>
-    <a class="{!}fp-dlg-butrename fp-panel-button" href="#"/>
+    <a class="{!}fp-dlg-butrename fp-panel-button" href="#"></a>
 </div>';
         return preg_replace('/\{\!\}/', '', $rv);
     }
@@ -860,11 +859,11 @@ class core_files_renderer extends plugin_renderer_base {
                     <td align="right"><label></label></td>
                     <td align="left"><select></select></td></tr>
                 <tr class="{!}fp-login-input">
-                    <td class="label"><label /></td>
+                    <td class="label"><label></label></td>
                     <td class="input"><input/></td></tr>
                 <tr class="{!}fp-login-radiogroup">
-                    <td align="right" width="30%" valign="top"><label /></td>
-                    <td align="left" valign="top"><p class="{!}fp-login-radio"><input /> <label /></p></td></tr>
+                    <td align="right" width="30%" valign="top"><label></label></td>
+                    <td align="left" valign="top"><p class="{!}fp-login-radio"><input /> <label></label></p></td></tr>
             </table>
             <p><button class="{!}fp-login-submit">'.get_string('submit', 'repository').'</button></p>
         </form>
@@ -896,7 +895,7 @@ class core_files_renderer extends plugin_renderer_base {
      * Default contents is one text input field with name="s"
      */
     public function repository_default_searchform() {
-        $str = '<input class="search-entry" name="s" value="Search" />';
+        $str = '<div class="fp-def-search"><input name="s" value='.get_string('search', 'repository').' /></div>';
         return $str;
     }
 }
index 0a0c2c5..d44b2ca 100644 (file)
@@ -171,7 +171,7 @@ if ($mform->is_cancelled()) {
 // form processing
 } else if ($data = $mform->get_data(false)) {
 
-    if (is_array($data->feedback)) {
+    if (isset($data->feedback) && is_array($data->feedback)) {
         $data->feedbackformat = $data->feedback['format'];
         $data->feedback = $data->feedback['text'];
     }
index 341a147..e50e3bc 100644 (file)
@@ -73,11 +73,6 @@ if (!function_exists('iconv')) {
     echo 'Moodle requires the iconv PHP extension. Please install or enable the iconv extension.';
     die();
 }
-if (iconv('UTF-8', 'UTF-8//IGNORE', 'abc') !== 'abc') {
-    // known to be broken in mid-2011 MAMP installations
-    echo 'Broken iconv PHP extension detected, installation can not continue.';
-    die;
-}
 
 if (PHP_INT_SIZE > 4) {
     // most probably 64bit PHP - we need a lot more memory
index 6dbb859..42dbcf3 100644 (file)
@@ -473,7 +473,7 @@ $string['enabledevicedetection'] = 'Enable device detection';
 $string['enablegravatar'] = 'Enable Gravatar';
 $string['enablegravatar_help'] = 'When enabled Moodle will attempt to fetch a user profile picture from Gravatar if the user has not uploaded an image.';
 $string['enablegroupmembersonly'] = 'Enable group members only';
-$string['enablemobilewebservice'] = 'Enable mobile web service';
+$string['enablemobilewebservice'] = 'Enable web services for mobile devices';
 $string['enablerecordcache'] = 'Enable record cache';
 $string['enablerssfeeds'] = 'Enable RSS feeds';
 $string['enablesafebrowserintegration'] = 'Enable Safe Exam Browser integration';
@@ -568,6 +568,7 @@ $string['htmleditorsettings'] = 'HTML editor settings';
 $string['htmlsettings'] = 'HTML settings';
 $string['http'] = 'HTTP';
 $string['httpsecurity'] = 'HTTP security';
+$string['hubs'] = 'Hubs';
 $string['change'] = 'change';
 $string['checkboxno'] = 'No';
 $string['checkboxyes'] = 'Yes';
@@ -846,7 +847,15 @@ $string['rcache'] = 'Record cache';
 $string['rcachettl'] = 'Record cache TTL';
 $string['recaptchaprivatekey'] = 'ReCAPTCHA private key';
 $string['recaptchapublickey'] = 'ReCAPTCHA public key';
+$string['register'] = 'Register your site';
+$string['registermoodleorg'] = 'When you register your site with {$a}';
+$string['registermoodleorgli1'] = 'You are added to a low-volume mailing list for important notifications such as security alerts and new releases of Moodle.';
+$string['registermoodleorgli2'] = 'Statistics about your site will be added to the {$a} of the worldwide Moodle community.';
+$string['registermoodleorgli3'] = 'Your site is also registered with the Moodle.org Open Community Hub ({$a}), allowing users with the publish courses capability (by default only managers) the option of publishing courses to MOOCH.';
+$string['registerwithmoodleorg'] = 'Register with Moodle.org';
 $string['registration'] = 'Registration';
+$string['registration_help'] = 'It is recommended to register on Moodle.org to receive security email alerts, to contribute to the Moodle growth and statistics, or to be able to share courses on MOOCH.';
+$string['registrationwarning'] = 'Your site is not yet registered.';
 $string['releasenoteslink'] = 'For information about this version of Moodle, please see the online <a target="_blank" href="{$a}">Release Notes</a>';
 $string['rememberusername'] = 'Remember username';
 $string['rememberusername_desc'] = 'Enable if you want to store permanent cookies with usernames during user login. Permanent cookies may be considered a privacy issue if used without consent.';
@@ -925,6 +934,7 @@ $string['splrequired'] = 'The SPL PHP extension is now required by Moodle.';
 $string['stats'] = 'Statistics';
 $string['statsfirstrun'] = 'Maximum processing interval';
 $string['statsmaxruntime'] = 'Maximum runtime';
+$string['statsmoodleorg'] = 'statistics';
 $string['statsruntimedays'] = 'Days to process';
 $string['statsruntimestart'] = 'Run at';
 $string['statsuserthreshold'] = 'User threshold';
@@ -1031,6 +1041,7 @@ $string['usetags'] = 'Enable tags functionality';
 $string['validateerror'] = 'This value was not valid:';
 $string['verifychangedemail'] = 'Restrict domains when changing email';
 $string['warningcurrentsetting'] = 'Invalid current value: {$a}';
+$string['warningiconvbuggy'] = 'Your version of the iconv library does not support the //IGNORE modifier. You should install the mbstring extension which can be used instead for cleaning strings containing invalid UTF-8 characters.';
 $string['webproxy'] = 'Web proxy';
 $string['webproxyinfo'] = 'Fill in following options if your Moodle server can not access internet directly. Internet access is required for download of environment data, language packs, RSS feeds, timezones, etc.<br /><em>PHP cURL extension is highly recommended.</em>';
 $string['xmlrpcrecommended'] = 'The xmlrpc extension is needed for hub communication, and useful for web services and Moodle networking';
index 42abfad..4b8cd53 100644 (file)
@@ -118,12 +118,6 @@ $string['licence_link'] = 'licenses';
 $string['logourl'] = 'Logo URL';
 $string['modulenumberaverage'] = 'Average number of course modules ({$a})';
 $string['moodleorg'] = 'Moodle.org';
-$string['moodleorgregistrationdetail'] = 'The main community hub is called MOOCH, at hub.moodle.org.  By registering your site with MOOCH you will contribute to the statistics of the worldwide Moodle community.  You can also join a low-volume mailing list providing early notifications of security fixes and new releases of Moodle.';
-$string['moodleorgregistrationdetail2'] = 'This option allows you to register your Moodle site with MOOCH, at hub.moodle.org.  Registration is free.
-The main benefit of registering is that you will be added to a low-volume mailing list for important notifications such as security alerts and new releases of Moodle.
-By default, your information will be kept private, and will never be sold or passed on to anyone else.  The only reason for collecting this information is for support purposes, and to help build up a statistical picture of the Moodle community as a whole.
-If you choose, you can allow your site name, country and URL to be added to the public list of Moodle Sites.
-All new registrations are verified manually before they are added to the list, but once you are added you can update your registration (and your entry on the public list) at any time.';
 $string['mustselectsubject'] = 'You must select a subject';
 $string['name'] = 'Name';
 $string['name_help'] = 'This name will be showing in the course listing.';
@@ -165,11 +159,10 @@ $string['registeredcourses'] = 'Registered courses';
 $string['registeredsites'] = 'Registered sites';
 $string['registrationinfo'] = 'Registration information';
 $string['registeredmoodleorg'] = 'Moodle.org ({$a})';
-$string['registeredon'] = 'Registered with';
+$string['registeredon'] = 'Hubs with which you are registered';
+$string['registermoochtips'] = 'To be registered with Moodle.org Open Community Hub (MOOCH), your site must be registered with Moodle.org.';
 $string['registersite'] = 'Register with {$a}';
-$string['registeron'] = 'Register your site';
-$string['registeronmoodleorg'] = 'Register with Moodle.org (MOOCH)';
-$string['registeronspecifichub'] = 'Register with a specific hub';
+$string['registerwith'] = 'Register with a hub';
 $string['registrationconfirmed'] = 'Site registration confirmed';
 $string['registrationconfirmedon'] = 'You are now registered on the hub {$a}. You are now able to publish courses to this hub, using the "Publish" link in course administration menus.';
 $string['registrationupdated'] = 'Registration has been updated.';
@@ -237,7 +230,6 @@ $string['siteversion'] = 'Moodle version';
 $string['siteversion_help'] = 'The Moodle version of this site.';
 $string['subject'] = 'Subject';
 $string['subject_help'] = 'Select the main subject area which the course covers.';
-$string['specifichub'] = 'Specific hub';
 $string['specifichubregistrationdetail'] = 'You can also register your site with other community hubs.';
 $string['statistics'] = 'Statistics privacy';
 $string['status'] = 'Hub listing';
index 42c8658..c0ca916 100644 (file)
@@ -145,6 +145,7 @@ $string['manage'] = 'Manage repositories';
 $string['manageurl'] = 'Manage';
 $string['manageuserrepository'] = 'Manage individual repository';
 $string['moving'] = 'Moving';
+$string['newfoldername'] = 'New folder name:';
 $string['noenter'] = 'Nothing entered';
 $string['nofilesattached'] = 'No files attached';
 $string['nofilesavailable'] = 'No files available';
index 2b72efe..f92c829 100644 (file)
@@ -122,8 +122,8 @@ $string['mobilewsenabled'] = 'Enabled';
 $string['nofunctions'] = 'This service has no functions.';
 $string['norequiredcapability'] = 'No required capability';
 $string['notoken'] = 'The token list is empty.';
-$string['onesystemcontrolling'] = 'One system controlling Moodle with a token';
-$string['onesystemcontrollingdescription'] = 'The following steps help you to set up the Moodle web service for a system to control Moodle. These steps also help to set up the recommended token (security keys) authentication method.';
+$string['onesystemcontrolling'] = 'Allow an external system to control Moodle';
+$string['onesystemcontrollingdescription'] = 'The following steps help you to set up the Moodle web services to allow an external system to interact with Moodle. This includes setting up a token (security key) authentication method.';
 $string['operation'] = 'Operation';
 $string['optional'] = 'Optional';
 $string['passwordisexpired'] = 'Password is expired.';
index 2034af1..4df3bc0 100644 (file)
@@ -992,172 +992,72 @@ class completion_info {
      * @return bool
      */
     public function is_tracked_user($userid) {
-        global $DB;
-
-        $tracked = $this->generate_tracked_user_sql();
-
-        $sql  = "SELECT u.id ";
-        $sql .= $tracked->sql;
-        $sql .= ' AND u.id = :userid';
-
-        $params = $tracked->data;
-        $params['userid'] = (int)$userid;
-        return $DB->record_exists_sql($sql, $params);
+        return is_enrolled(context_course::instance($this->course->id), $userid, '', true);
     }
 
     /**
-     * Return number of users whose progress is tracked in this course
+     * Returns the number of users whose progress is tracked in this course.
      *
-     * Optionally supply a search's where clause, or a group id
+     * Optionally supply a search's where clause, or a group id.
      *
-     * @param string $where Where clause sql
-     * @param array $where_params Where clause params
+     * @param string $where Where clause sql (use 'u.whatever' for user table fields)
+     * @param array $whereparams Where clause params
      * @param int $groupid Group id
-     * @return int
+     * @return int Number of tracked users
      */
-    public function get_num_tracked_users($where = '', $where_params = array(), $groupid = 0) {
+    public function get_num_tracked_users($where = '', $whereparams = array(), $groupid = 0) {
         global $DB;
 
-        $tracked = $this->generate_tracked_user_sql($groupid);
-
-        $sql  = "SELECT COUNT(u.id) ";
-        $sql .= $tracked->sql;
-
+        list($enrolledsql, $enrolledparams) = get_enrolled_sql(
+                context_course::instance($this->course->id), '', $groupid, true);
+        $sql  = 'SELECT COUNT(eu.id) FROM (' . $enrolledsql . ') eu JOIN {user} u ON u.id = eu.id';
         if ($where) {
-            $sql .= " AND $where";
+            $sql .= " WHERE $where";
         }
 
-        $params = array_merge($tracked->data, $where_params);
+        $params = array_merge($enrolledparams, $whereparams);
         return $DB->count_records_sql($sql, $params);
     }
 
     /**
-     * Return array of users whose progress is tracked in this course
+     * Return array of users whose progress is tracked in this course.
      *
-     * Optionally supply a search's where caluse, group id, sorting, paging
+     * Optionally supply a search's where clause, group id, sorting, paging.
      *
-     * @param string $where Where clause sql (optional)
-     * @param array $where_params Where clause params (optional)
-     * @param integer $groupid Group ID to restrict to (optional)
+     * @param string $where Where clause sql, referring to 'u.' fields (optional)
+     * @param array $whereparams Where clause params (optional)
+     * @param int $groupid Group ID to restrict to (optional)
      * @param string $sort Order by clause (optional)
-     * @param integer $limitfrom Result start (optional)
-     * @param integer $limitnum Result max size (optional)
+     * @param int $limitfrom Result start (optional)
+     * @param int $limitnum Result max size (optional)
      * @param context $extracontext If set, includes extra user information fields
      *   as appropriate to display for current user in this context
-     * @return array
+     * @return array Array of user objects with standard user fields
      */
-    public function get_tracked_users($where = '', $where_params = array(), $groupid = 0,
+    public function get_tracked_users($where = '', $whereparams = array(), $groupid = 0,
              $sort = '', $limitfrom = '', $limitnum = '', context $extracontext = null) {
 
         global $DB;
 
-        $tracked = $this->generate_tracked_user_sql($groupid);
-        $params = $tracked->data;
+        list($enrolledsql, $params) = get_enrolled_sql(
+                context_course::instance($this->course->id), '', $groupid, true);
 
-        $sql = "
-            SELECT
-                u.id,
-                u.firstname,
-                u.lastname,
-                u.idnumber
-        ";
+        $sql = 'SELECT u.id, u.firstname, u.lastname, u.idnumber';
         if ($extracontext) {
             $sql .= get_extra_user_fields_sql($extracontext, 'u', '', array('idnumber'));
         }
-
-        $sql .= $tracked->sql;
+        $sql .= ' FROM (' . $enrolledsql . ') eu JOIN {user} u ON u.id = eu.id';
 
         if ($where) {
             $sql .= " AND $where";
-            $params = array_merge($params, $where_params);
+            $params = array_merge($params, $whereparams);
         }
 
         if ($sort) {
             $sql .= " ORDER BY $sort";
         }
 
-        $users = $DB->get_records_sql($sql, $params, $limitfrom, $limitnum);
-        return $users ? $users : array(); // In case it returns false
-    }
-
-    /**
-     * Generate the SQL for finding tracked users in this course
-     *
-     * Returns an object containing the sql fragment and an array of
-     * bound data params.
-     *
-     * @param integer $groupid
-     * @return stdClass With two properties, sql (string), and data (array)
-     */
-    public function generate_tracked_user_sql($groupid = 0) {
-        global $CFG;
-
-        $return = new stdClass();
-        $return->sql = '';
-        $return->data = array();
-
-        if (!empty($CFG->gradebookroles)) {
-            $roles = ' AND ra.roleid IN ('.$CFG->gradebookroles.')';
-        } else {
-            // This causes it to default to everyone (if there is no student role)
-            $roles = '';
-        }
-
-        // Build context sql
-        $context = get_context_instance(CONTEXT_COURSE, $this->course->id);
-        $parentcontexts = substr($context->path, 1); // kill leading slash
-        $parentcontexts = str_replace('/', ',', $parentcontexts);
-        if ($parentcontexts !== '') {
-            $parentcontexts = ' OR ra.contextid IN ('.$parentcontexts.' )';
-        }
-
-        $groupjoin   = '';
-        $groupselect = '';
-        if ($groupid) {
-            $groupjoin   = "JOIN {groups_members} gm
-                              ON gm.userid = u.id";
-            $groupselect = " AND gm.groupid = :groupid ";
-
-            $return->data['groupid'] = $groupid;
-        }
-
-        $return->sql = "
-            FROM
-                {user} u
-            INNER JOIN
-                {role_assignments} ra
-             ON ra.userid = u.id
-            INNER JOIN
-                {role} r
-             ON r.id = ra.roleid
-            INNER JOIN
-                {user_enrolments} ue
-             ON ue.userid = u.id
-            INNER JOIN
-                {enrol} e
-             ON e.id = ue.enrolid
-            INNER JOIN
-                {course} c
-             ON c.id = e.courseid
-            $groupjoin
-            WHERE
-                (ra.contextid = :contextid $parentcontexts)
-            AND c.id = :courseid
-            AND ue.status = 0
-            AND e.status = 0
-            AND ue.timestart < :now1
-            AND (ue.timeend > :now2 OR ue.timeend = 0)
-                $groupselect
-                $roles
-        ";
-
-        $now = time();
-        $return->data['now1'] = $now;
-        $return->data['now2'] = $now;
-        $return->data['contextid'] = $context->id;
-        $return->data['courseid'] = $this->course->id;
-
-        return $return;
+        return $DB->get_records_sql($sql, $params, $limitfrom, $limitnum);
     }
 
     /**
index 791d246..031ac61 100644 (file)
  * @return mixed
  */
 function min_optional_param($name, $default, $type) {
-    $value = $default;
     if (isset($_GET[$name])) {
         $value = $_GET[$name];
 
     } else if (isset($_GET['amp;'.$name])) {
         // very, very, very ugly hack, unfortunately $OUTPUT->pix_url() is not used properly in javascript code :-(
         $value = $_GET['amp;'.$name];
+
+    } else if (isset($_POST[$name])) {
+        $value = $_POST[$name];
+
+    } else {
+        return $default;
     }
 
     return min_clean_param($value, $type);
@@ -50,15 +55,16 @@ function min_optional_param($name, $default, $type) {
 
 /**
  * Minimalistic parameter cleaning function.
- * Can not use optional param because moodlelib.php is not loaded yet
- * @param string $name
- * @param mixed $default
+ *
+ * Note: Can not use optional param because moodlelib.php is not loaded yet.
+ *
+ * @param string $value
  * @param string $type
  * @return mixed
  */
 function min_clean_param($value, $type) {
     switch($type) {
-        case 'RAW':      $value = iconv('UTF-8', 'UTF-8//IGNORE', $value);
+        case 'RAW':      $value = min_fix_utf8((string)$value);
                          break;
         case 'INT':      $value = (int)$value;
                          break;
@@ -74,6 +80,49 @@ function min_clean_param($value, $type) {
     return $value;
 }
 
+/**
+ * Minimalistic UTF-8 sanitisation.
+ *
+ * Note: This duplicates fix_utf8() intentionally for now.
+ *
+ * @param string $value
+ * @return string
+ */
+function min_fix_utf8($value) {
+    // Lower error reporting because glibc throws bogus notices.
+    $olderror = error_reporting();
+    if ($olderror & E_NOTICE) {
+        error_reporting($olderror ^ E_NOTICE);
+    }
+
+    static $buggyiconv = null;
+    if ($buggyiconv === null) {
+        $buggyiconv = (!function_exists('iconv') or iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
+    }
+
+    if ($buggyiconv) {
+        if (function_exists('mb_convert_encoding')) {
+            $subst = mb_substitute_character();
+            mb_substitute_character('');
+            $result = mb_convert_encoding($value, 'utf-8', 'utf-8');
+            mb_substitute_character($subst);
+
+        } else {
+            // Warn admins on admin/index.php page.
+            $result = $value;
+        }
+
+    } else {
+        $result = iconv('UTF-8', 'UTF-8//IGNORE', $value);
+    }
+
+    if ($olderror & E_NOTICE) {
+        error_reporting($olderror);
+    }
+
+    return $result;
+}
+
 /**
  * This method tries to enable output compression if possible.
  * This function must be called before any output or headers.
@@ -112,7 +161,9 @@ function min_enable_zlib_compression() {
 
 /**
  * Returns the slashargument part of the URL.
- * Note: ".php" is NOT allowed in slasharguments!
+ *
+ * Note: ".php" is NOT allowed in slasharguments,
+ *       it is intended for ASCII characters only.
  *
  * @return string
  */
index f89adbd..b79057d 100644 (file)
@@ -174,9 +174,8 @@ function cron_run() {
 
     // Send login failures notification - brute force protection in moodle is weak,
     // we should at least send notices early in each cron execution
-    if (!empty($CFG->notifyloginfailures)) {
-        notify_login_failures();
-        mtrace(' Notified login failured');
+    if (notify_login_failures()) {
+        mtrace(' Notified login failures');
     }
 
 
@@ -603,16 +602,27 @@ function cron_bc_hack_plugin_functions($plugintype, $plugins) {
  * Note that this function must be only executed from the cron script
  * It uses the cache_flags system to store temporary records, deleting them
  * by name before finishing
+ *
+ * @return bool True if executed, false if not
  */
 function notify_login_failures() {
     global $CFG, $DB, $OUTPUT;
 
+    if (empty($CFG->notifyloginfailures)) {
+        return false;
+    }
+
     $recip = get_users_from_config($CFG->notifyloginfailures, 'moodle/site:config');
 
     if (empty($CFG->lastnotifyfailure)) {
         $CFG->lastnotifyfailure=0;
     }
 
+    // If it has been less than an hour, or if there are no recipients, don't execute.
+    if (((time() - HOURSECS) < $CFG->lastnotifyfailure) || !is_array($recip) || count($recip) <= 0) {
+        return false;
+    }
+
     // we need to deal with the threshold stuff first.
     if (empty($CFG->notifyloginthreshold)) {
         $CFG->notifyloginthreshold = 10; // default to something sensible.
@@ -685,10 +695,8 @@ function notify_login_failures() {
     }
     $rs->close();
 
-    // If we haven't run in the last hour and
-    // we have something useful to report and we
-    // are actually supposed to be reporting to somebody
-    if ((time() - HOURSECS) > $CFG->lastnotifyfailure && $count > 0 && is_array($recip) && count($recip) > 0) {
+    // If we have something useful to report.
+    if ($count > 0) {
         $site = get_site();
         $subject = get_string('notifyloginfailuressubject', '', format_string($site->fullname));
         // Calculate the complete body of notification (start + messages + end)
@@ -710,4 +718,6 @@ function notify_login_failures() {
 
     // Finally, delete all the temp records we have created in cache_flags
     $DB->delete_records_select('cache_flags', "flagtype IN ('login_failure_by_ip', 'login_failure_by_info')");
+
+    return true;
 }
index 76ebc66..173659e 100644 (file)
@@ -1679,6 +1679,7 @@ $capabilities = array(
         'contextlevel' => CONTEXT_BLOCK,
         'archetypes' => array(
             'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
         )
     ),
 
index aa5539f..9d9c7d6 100644 (file)
@@ -107,7 +107,7 @@ class EvalMath {
         'sin','sinh','arcsin','asin','arcsinh','asinh',
         'cos','cosh','arccos','acos','arccosh','acosh',
         'tan','tanh','arctan','atan','arctanh','atanh',
-        'sqrt','abs','ln','log','exp','floor','ceil','round');
+        'sqrt','abs','ln','log','exp','floor','ceil');
 
     var $fc = array( // calc functions emulation
         'average'=>array(-1), 'max'=>array(-1),  'min'=>array(-1),
index e53640b..2771e04 100644 (file)
@@ -303,15 +303,11 @@ abstract class file_info {
     /**
      * Copy content of this file to local storage, overriding current file if needed.
      *
-     * @param int $contextid context ID
-     * @param string $component component
-     * @param string $filearea file area
-     * @param int $itemid item ID
-     * @param string $filepath file path
-     * @param string $filename file name
-     * @return boolean success
+     * @param array|stdClass $filerecord contains contextid, component, filearea,
+     *    itemid, filepath, filename and optionally other attributes of the new file
+     * @return bool success
      */
-    public function copy_to_storage($contextid, $component, $filearea, $itemid, $filepath, $filename) {
+    public function copy_to_storage($filerecord) {
         return false;
     }
 
index 2f3ea57..6eb760f 100644 (file)
@@ -519,25 +519,21 @@ class file_info_stored extends file_info {
     /**
      * Copy content of this file to local storage, overriding current file if needed.
      *
-     * @param int $contextid context ID
-     * @param string $component file component
-     * @param string $filearea file area
-     * @param int $itemid item ID
-     * @param string $filepath file path
-     * @param string $filename file name
+     * @param array|stdClass $filerecord contains contextid, component, filearea,
+     *    itemid, filepath, filename and optionally other attributes of the new file
      * @return bool success
      */
-    public function copy_to_storage($contextid, $component, $filearea, $itemid, $filepath, $filename) {
+    public function copy_to_storage($filerecord) {
         if (!$this->is_readable() or $this->is_directory()) {
             return false;
         }
+        $filerecord = (array)$filerecord;
 
         $fs = get_file_storage();
-        if ($existing = $fs->get_file($contextid, $component, $filearea, $itemid, $filepath, $filename)) {
+        if ($existing = $fs->get_file($filerecord['contextid'], $filerecord['component'], $filerecord['filearea'], $filerecord['itemid'], $filerecord['filepath'], $filerecord['filename'])) {
             $existing->delete();
         }
-        $file_record = array('contextid'=>$contextid, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid, 'filepath'=>$filepath, 'filename'=>$filename);
-        $fs->create_file_from_storedfile($file_record, $this->lf);
+        $fs->create_file_from_storedfile($filerecord, $this->lf);
 
         return true;
     }
index c936716..75ab483 100644 (file)
@@ -161,7 +161,7 @@ class stored_file {
                 throw new file_exception('storedfilecannotread', '', $pathname);
             }
         }
-        $mimetype = $this->fs->mimetype($pathname);
+        $mimetype = $this->fs->mimetype($pathname, $this->file_record->filename);
         $this->file_record->mimetype = $mimetype;
 
         $DB->update_record('files', $this->file_record);
index 6627c2a..3b2bd3e 100644 (file)
@@ -100,9 +100,8 @@ M.form_filemanager.init = function(Y, options) {
                 this.pathbar.removeChild(this.pathnode);
             }
             // initialize 'select file' panel
-            this.selectnode = Y.Node.create(M.form_filemanager.templates.fileselectlayout);
+            this.selectnode = Y.Node.createWithFilesSkin(M.form_filemanager.templates.fileselectlayout);
             this.selectnode.generateID();
-            Y.one(document.body).appendChild(this.selectnode);
             this.selectui = new Y.Panel({
                 srcNode      : this.selectnode,
                 zIndex       : 600000,
@@ -234,27 +233,27 @@ M.form_filemanager.init = function(Y, options) {
                 header = M.str.moodle.info;
             }
             if (!this.msg_dlg) {
-                var node = Y.Node.create(M.form_filemanager.templates.message);
-                this.filemanager.appendChild(node);
+                this.msg_dlg_node = Y.Node.createWithFilesSkin(M.form_filemanager.templates.message);
+                var nodeid = this.msg_dlg_node.generateID();
 
                 this.msg_dlg = new Y.Panel({
-                    srcNode      : node,
+                    srcNode      : this.msg_dlg_node,
                     zIndex       : 800000,
                     centered     : true,
                     modal        : true,
                     visible      : false,
                     render       : true
                 });
-                this.msg_dlg.plug(Y.Plugin.Drag,{handles:['.yui3-widget-hd']});
-                node.one('.fp-msg-butok').on('click', function(e) {
+                this.msg_dlg.plug(Y.Plugin.Drag,{handles:['#'+nodeid+' .yui3-widget-hd']});
+                this.msg_dlg_node.one('.fp-msg-butok').on('click', function(e) {
                     e.preventDefault();
                     this.msg_dlg.hide();
                 }, this);
             }
 
             this.msg_dlg.set('headerContent', header);
-            this.filemanager.one('.fp-msg').removeClass('fp-msg-info').removeClass('fp-msg-error').addClass('fp-msg-'+type)
-            this.filemanager.one('.fp-msg .fp-msg-text').setContent(msg);
+            this.msg_dlg_node.removeClass('fp-msg-info').removeClass('fp-msg-error').addClass('fp-msg-'+type)
+            this.msg_dlg_node.one('.fp-msg-text').setContent(msg);
             this.msg_dlg.show();
         },
         setup_buttons: function() {
@@ -302,8 +301,7 @@ M.form_filemanager.init = function(Y, options) {
                         });
                     }
                     if (!this.mkdir_dialog) {
-                        var node = Y.Node.create(M.form_filemanager.templates.mkdir);
-                        this.filemanager.appendChild(node);
+                        var node = Y.Node.createWithFilesSkin(M.form_filemanager.templates.mkdir);
                         this.mkdir_dialog = new Y.Panel({
                             srcNode      : node,
                             zIndex       : 800000,
@@ -679,10 +677,9 @@ M.form_filemanager.init = function(Y, options) {
         show_confirm_dialog: function(dialog_options) {
             // instead of M.util.show_confirm_dialog(e, dialog_options);
             if (!this.confirm_dlg) {
-                this.confirm_dlg_node = Y.Node.create(M.form_filemanager.templates.confirmdialog);
+                this.confirm_dlg_node = Y.Node.createWithFilesSkin(M.form_filemanager.templates.confirmdialog);
                 var node = this.confirm_dlg_node;
                 node.generateID();
-                Y.one(document.body).appendChild(node);
                 this.confirm_dlg = new Y.Panel({
                     srcNode      : node,
                     zIndex       : 800000,
@@ -867,7 +864,7 @@ M.form_filemanager.init = function(Y, options) {
             this.selectui.fileinfo = node;
             selectnode.one('.fp-saveas input').set('value', node.fullname);
             var foldername = this.get_parent_folder_name(node);
-            selectnode.all('.fp-author input').set('value', node.author);
+            selectnode.all('.fp-author input').set('value', node.author ? node.author : '');
             selectnode.all('.fp-license select option[selected]').set('selected', false);
             selectnode.all('.fp-license select option[value='+node.license+']').set('selected', true);
             selectnode.all('.fp-path select option[selected]').set('selected', false);
index 23ee2f5..9fdc96d 100644 (file)
@@ -1127,15 +1127,39 @@ function fix_utf8($value) {
             // shortcut
             return $value;
         }
-        // lower error reporting because glibc throws bogus notices
+
+        // Lower error reporting because glibc throws bogus notices.
         $olderror = error_reporting();
         if ($olderror & E_NOTICE) {
             error_reporting($olderror ^ E_NOTICE);
         }
-        $result = iconv('UTF-8', 'UTF-8//IGNORE', $value);
+
+        // Note: this duplicates min_fix_utf8() intentionally.
+        static $buggyiconv = null;
+        if ($buggyiconv === null) {
+            $buggyiconv = (!function_exists('iconv') or iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
+        }
+
+        if ($buggyiconv) {
+            if (function_exists('mb_convert_encoding')) {
+                $subst = mb_substitute_character();
+                mb_substitute_character('');
+                $result = mb_convert_encoding($value, 'utf-8', 'utf-8');
+                mb_substitute_character($subst);
+
+            } else {
+                // Warn admins on admin/index.php page.
+                $result = $value;
+            }
+
+        } else {
+            $result = iconv('UTF-8', 'UTF-8//IGNORE', $value);
+        }
+
         if ($olderror & E_NOTICE) {
             error_reporting($olderror);
         }
+
         return $result;
 
     } else if (is_array($value)) {
index b4aa15b..587ba19 100644 (file)
@@ -368,8 +368,8 @@ abstract class oauth2_client extends curl {
     private $clientid = '';
     /** var string The client secret. */
     private $clientsecret = '';
-    /** var string URL to return to after authenticating */
-    private $returnurl = '';
+    /** var moodle_url URL to return to after authenticating */
+    private $returnurl = null;
     /** var string scope of the authentication request */
     private $scope = '';
     /** var stdClass access token object */
@@ -392,10 +392,10 @@ abstract class oauth2_client extends curl {
      *
      * @param string $clientid
      * @param string $clientsecret
-     * @param string $returnurl
+     * @param moodle_url $returnurl
      * @param string $scope
      */
-    public function __construct($clientid, $clientsecret, $returnurl, $scope) {
+    public function __construct($clientid, $clientsecret, moodle_url $returnurl, $scope) {
         parent::__construct();
         $this->clientid = $clientid;
         $this->clientsecret = $clientsecret;
@@ -425,7 +425,7 @@ abstract class oauth2_client extends curl {
 
         // If we've been passed then authorization code generated by the
         // authorization server try and upgrade the token to an access token.
-        $code = optional_param('code', null, PARAM_RAW);
+        $code = optional_param('oauth2code', null, PARAM_RAW);
         if ($code && $this->upgrade_token($code)) {
             return true;
         }
@@ -456,7 +456,7 @@ abstract class oauth2_client extends curl {
                         array('client_id' => $this->clientid,
                               'response_type' => 'code',
                               'redirect_uri' => $callbackurl->out(false),
-                              'state' => $this->returnurl,
+                              'state' => $this->returnurl->out_as_local_url(false),
                               'scope' => $this->scope,
                           ));
 
index 9cd8585..a700157 100644 (file)
@@ -34,4 +34,5 @@ require_once(__DIR__.'/classes/database_driver_testcase.php');
 require_once(__DIR__.'/classes/arraydataset.php');
 require_once(__DIR__.'/classes/advanced_testcase.php');
 require_once(__DIR__.'/classes/unittestcase.php');
+require_once(__DIR__.'/classes/hint_resultprinter.php'); // Loaded here because phpunit.xml does not support relative links for printerFile
 
index e991bea..b810564 100644 (file)
@@ -131,17 +131,6 @@ class flexible_table {
         );
     }
 
-    /**
-     * Backwards-compatible constructor, so that legacy code subclassing
-     * flexible_table does not break.
-     * @deprecated since Moodle 2.0. Will be removed in Moodle 2.1.
-     */
-    function flexible_table($uniqueid) {
-        debugging('Please update your code to user PHP5-style parent::__construct(...), ' .
-                'not parent::flexible_table(...).');
-        $this->__construct($uniqueid);
-    }
-
     /**
      * Call this to pass the download type. Use :
      *         $download = optional_param('download', '', PARAM_ALPHA);
diff --git a/lib/tests/configonlylib_test.php b/lib/tests/configonlylib_test.php
new file mode 100644 (file)
index 0000000..dc97baa
--- /dev/null
@@ -0,0 +1,144 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Unit tests for config only library functions-
+ *
+ * @package    core
+ * @category   phpunit
+ * @copyright  2012 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+// Global CFG not used here intentionally to make sure it is not required inside the lib.
+require_once(__DIR__ . '/../configonlylib.php');
+
+
+/**
+ * Unit tests for config only library functions.
+ *
+ * @package    core
+ * @category   phpunit
+ * @copyright  2012 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class core_configonlylib_testcase extends advanced_testcase {
+
+    /**
+     * Test cleaning of invalid utf-8 entities.
+     */
+    public function test_min_fix_utf8() {
+        $this->assertSame('abc', min_fix_utf8('abc'));
+        $this->assertSame("žlutý koníček přeskočil potůček \n\t\r\0", min_fix_utf8("žlutý koníček přeskočil potůček \n\t\r\0"));
+        $this->assertSame('aš', min_fix_utf8('a'.chr(130).'š'), 'This fails with buggy iconv() when mbstring extenstion is not available as fallback.');
+    }
+
+    /**
+     * Test minimalistic parameter cleaning.
+     */
+    public function test_min_clean_param() {
+        $this->assertSame('foo', min_clean_param('foo', 'RAW'));
+        $this->assertSame('aš', min_clean_param('a'.chr(130).'š', 'RAW'));
+
+        $this->assertSame(1, min_clean_param('1', 'INT'));
+        $this->assertSame(1, min_clean_param('1aa', 'INT'));
+
+        $this->assertSame('1abc-d_f', min_clean_param('/.1ačž"b?;c-d{}\\_f.', 'SAFEDIR'));
+        $this->assertSame(1, min_clean_param('1aa', 'INT'));
+
+        $this->assertSame('/a/b/./c5', min_clean_param('/a*?$//b/.../c5', 'SAFEPATH'));
+        $this->assertSame(1, min_clean_param('1aa', 'INT'));
+    }
+
+    /**
+     * Test minimalistic getting of page parameters.
+     */
+    public function test_min_optional_param() {
+        $this->resetAfterTest();
+
+        $_GET['foo'] = 'bar';
+        $_GET['num'] = '1';
+        $_GET['xnum'] = '1aa';
+
+        $_POST['foo'] = 'rebar';
+        $_POST['oof'] = 'rab';
+
+        $this->assertSame('bar', min_optional_param('foo', null, 'RAW'));
+        $this->assertSame(null, min_optional_param('foo2', null, 'RAW'));
+        $this->assertSame('rab', min_optional_param('oof', null, 'RAW'));
+
+        $this->assertSame(1, min_optional_param('num', null, 'INT'));
+        $this->assertSame(1, min_optional_param('xnum', null, 'INT'));
+    }
+
+    /**
+     * Test fail-safe minimalistic slashargument processing.
+     */
+    public function min_get_slash_argument() {
+        global $CFG;
+
+        $this->resetAfterTest();
+        $this->assertEquals('http://www.example.com/moode', $CFG->wwwroot);
+
+        $_SERVER = array();
+        $_SERVER['SERVER_SOFTWARE'] = 'Apache/2.2.22 (Unix)';
+        $_SERVER['QUERY_STRING'] = 'theme=standard&component=core&rev=5&image=u/f1';
+        $_SEREVR['REQUEST_URI'] = '/moodle/theme/image.php?theme=standard&component=core&rev=5&image=u/f1';
+        $_SERVER['SCRIPT_NAME'] = '/moodle/theme/image.php';
+        $this->assertSame('', min_get_slash_argument());
+
+        $_SERVER = array();
+        $_SERVER['SERVER_SOFTWARE'] = 'Apache/2.2.22 (Unix)';
+        $_SERVER['QUERY_STRING'] = '';
+        $_SEREVR['REQUEST_URI'] = '/moodle/theme/image.php/standard/core/5/u/f1';
+        $_SERVER['PATH_INFO'] = '/standard/core/5/u/f1';
+        $_SERVER['SCRIPT_NAME'] = '/moodle/theme/image.php';
+        $_GET = array();
+        $this->assertSame('/standard/core/5/u/f1', min_get_slash_argument());
+
+        // IIS no url rewriting
+        $_SERVER = array();
+        $_SERVER['SERVER_SOFTWARE'] = 'Microsoft-IIS/7.0';
+        $_SERVER['QUERY_STRING'] = '';
+        $_SEREVR['REQUEST_URI'] = '/moodle/theme/image.php/standard/core/5/u/f1';
+        $_SERVER['PATH_INFO'] = '/standard/core/5/u/f1';
+        $_SERVER['SCRIPT_NAME'] = '/moodle/theme/image.php';
+        $_GET = array();
+        $this->assertSame('/standard/core/5/u/f1', min_get_slash_argument());
+
+        // IIS with url rewriting
+        $_SERVER = array();
+        $_SERVER['SERVER_SOFTWARE'] = 'Microsoft-IIS/7.0';
+        $_SERVER['QUERY_STRING'] = 'file=/standard/core/5/u/f1';
+        $_SEREVR['REQUEST_URI'] = '/moodle/theme/image.php/standard/core/5/u/f1';
+        $_SERVER['PATH_INFO'] = '/';
+        $_SERVER['SCRIPT_NAME'] = '/moodle/theme/image.php';
+        $_GET = array();
+        $_GET['file'] = '/standard/core/5/u/f1';
+        $this->assertSame('/standard/core/5/u/f1', min_get_slash_argument());
+
+        $_SERVER = array();
+        $_SERVER['SERVER_SOFTWARE'] = 'Weird server';
+        $_SERVER['QUERY_STRING'] = '';
+        $_SEREVR['REQUEST_URI'] = '/moodle/theme/image.php/standard/core/5/u/f1';
+        $_SERVER['PATH_INFO'] = '/moodle/theme/image.php/standard/core/5/u/f1';
+        $_SERVER['SCRIPT_NAME'] = '/moodle/theme/image.php';
+        $_GET = array();
+        $this->assertSame('/standard/core/5/u/f1', min_get_slash_argument());
+    }
+}
index 4c56eed..1df41fe 100644 (file)
@@ -142,6 +142,9 @@ class mathsslib_testcase extends basic_testcase {
     }
 
     public function test_rounding_function() {
+        // Rounding to the default number of decimal places
+        // The default == 0
+
         $formula = new calc_formula('=round(2.5)');
         $this->assertEquals($formula->evaluate(), 3);
 
@@ -196,6 +199,19 @@ class mathsslib_testcase extends basic_testcase {
         $formula = new calc_formula('=floor(-2.5)');
         $this->assertEquals($formula->evaluate(), -3);
 
+        // Rounding to an explicit number of decimal places
+
+        $formula = new calc_formula('=round(2.5, 1)');
+        $this->assertEquals($formula->evaluate(), 2.5);
+
+        $formula = new calc_formula('=round(2.5, 0)');
+        $this->assertEquals($formula->evaluate(), 3);
+
+        $formula = new calc_formula('=round(1.2345, 2)');
+        $this->assertEquals($formula->evaluate(), 1.23);
+
+        $formula = new calc_formula('=round(123.456, -1)');
+        $this->assertEquals($formula->evaluate(), 120);
     }
 
     public function test_scientific_notation() {
index 6189919..5ce3a2c 100644 (file)
@@ -301,6 +301,7 @@ class moodlelib_testcase extends advanced_testcase {
         $this->assertSame(1.1, fix_utf8(1.1));
         $this->assertSame(true, fix_utf8(true));
         $this->assertSame('', fix_utf8(''));
+        $this->assertSame('abc', fix_utf8('abc'));
         $array = array('do', 're', 'mi');
         $this->assertSame($array, fix_utf8($array));
         $object = new stdClass();
@@ -312,7 +313,7 @@ class moodlelib_testcase extends advanced_testcase {
         $this->assertSame("žlutý koníček přeskočil potůček \n\t\r\0", fix_utf8("žlutý koníček přeskočil potůček \n\t\r\0"));
 
         // invalid utf8 string
-        $this->assertSame('aaabbb', fix_utf8('aaa'.chr(130).'bbb'));
+        $this->assertSame('aš', fix_utf8('a'.chr(130).'š'), 'This fails with buggy iconv() when mbstring extenstion is not available as fallback.');
     }
 
     function test_optional_param() {
index dadd2a8..237a00d 100644 (file)
@@ -53,6 +53,77 @@ class assign_feedback_comments extends assign_feedback_plugin {
         return $DB->get_record('assignfeedback_comments', array('grade'=>$gradeid));
     }
 
+    /**
+     * Get quickgrading form elements as html
+     *
+     * @param int $userid The user id in the table this quickgrading element relates to
+     * @param mixed $grade - The grade data - may be null if there are no grades for this user (yet)
+     * @return mixed - A html string containing the html form elements required for quickgrading
+     */
+    public function get_quickgrading_html($userid, $grade) {
+        $commenttext = '';
+        if ($grade) {
+            $feedbackcomments = $this->get_feedback_comments($grade->id);
+            if ($feedbackcomments) {
+                $commenttext = $feedbackcomments->commenttext;
+            }
+        }
+
+        return html_writer::tag('textarea', $commenttext, array('name'=>'quickgrade_comments_' . $userid,
+                                                                'class'=>'quickgrade'));
+    }
+
+    /**
+     * Has the plugin quickgrading form element been modified in the current form submission?
+     *
+     * @param int $userid The user id in the table this quickgrading element relates to
+     * @param stdClass $grade The grade
+     * @return boolean - true if the quickgrading form element has been modified
+     */
+    public function is_quickgrading_modified($userid, $grade) {
+        $commenttext = '';
+        if ($grade) {
+            $feedbackcomments = $this->get_feedback_comments($grade->id);
+            if ($feedbackcomments) {
+                $commenttext = $feedbackcomments->commenttext;
+            }
+        }
+        return optional_param('quickgrade_comments_' . $userid, '', PARAM_TEXT) != $commenttext;
+    }
+
+
+    /**
+     * Override to indicate a plugin supports quickgrading
+     *
+     * @return boolean - True if the plugin supports quickgrading
+     */
+    public function supports_quickgrading() {
+        return true;
+    }
+
+    /**
+     * Save quickgrading changes
+     *
+     * @param int $userid The user id in the table this quickgrading element relates to
+     * @param stdClass $grade The grade
+     * @return boolean - true if the grade changes were saved correctly
+     */
+    public function save_quickgrading_changes($userid, $grade) {
+        global $DB;
+        $feedbackcomment = $this->get_feedback_comments($grade->id);
+        if ($feedbackcomment) {
+            $feedbackcomment->commenttext = optional_param('quickgrade_comments_' . $userid, '', PARAM_TEXT);
+            return $DB->update_record('assignfeedback_comments', $feedbackcomment);
+        } else {
+            $feedbackcomment = new stdClass();
+            $feedbackcomment->commenttext = optional_param('quickgrade_comments_' . $userid, '', PARAM_TEXT);
+            $feedbackcomment->commentformat = FORMAT_HTML;
+            $feedbackcomment->grade = $grade->id;
+            $feedbackcomment->assignment = $this->assignment->get_instance()->id;
+            return $DB->insert_record('assignfeedback_comments', $feedbackcomment) > 0;
+        }
+    }
+
     /**
      * Get form elements for the grading page
      *
index 198900b..6677e6a 100644 (file)
@@ -81,4 +81,46 @@ abstract class assign_feedback_plugin extends assign_plugin {
         return '';
     }
 
+    /**
+     * Override to indicate a plugin supports quickgrading
+     *
+     * @return boolean - True if the plugin supports quickgrading
+     */
+    public function supports_quickgrading() {
+        return false;
+    }
+
+    /**
+     * Get quickgrading form elements as html
+     *
+     * @param int $userid The user id in the table this quickgrading element relates to
+     * @param mixed $grade grade or null - The grade data. May be null if there are no grades for this user (yet)
+     * @return mixed - A html string containing the html form elements required for quickgrading or false to indicate this plugin does not support quickgrading
+     */
+    public function get_quickgrading_html($userid, $grade) {
+        return false;
+    }
+
+    /**
+     * Has the plugin quickgrading form element been modified in the current form submission?
+     *
+     * @param int $userid The user id in the table this quickgrading element relates to
+     * @param stdClass $grade The grade
+     * @return boolean - true if the quickgrading form element has been modified
+     */
+    public function is_quickgrading_modified($userid, $grade) {
+        return false;
+    }
+
+    /**
+     * Save quickgrading changes
+     *
+     * @param int $userid The user id in the table this quickgrading element relates to
+     * @param stdClass $grade The grade
+     * @return boolean - true if the grade changes were saved correctly
+     */
+    public function save_quickgrading_changes($userid, $grade) {
+        return false;
+    }
+
 }
index 7d2bddc..db4432d 100644 (file)
@@ -253,7 +253,7 @@ class assign_grading_table extends table_sql implements renderable {
             $options = make_grades_menu(-$outcome->scaleid);
 
             $options[0] = get_string('nooutcome', 'grades');
-            if ($this->quickgrading&& !($outcome->grades[$row->userid]->locked)) {
+            if ($this->quickgrading && !($outcome->grades[$row->userid]->locked)) {
                 $select = '<select name="outcome_' . $index . '_' . $row->userid . '" class="quickgrade">';
                 foreach ($options as $optionindex => $optionvalue) {
                     $selected = '';
@@ -519,6 +519,7 @@ class assign_grading_table extends table_sql implements renderable {
     private function format_plugin_summary_with_link(assign_plugin $plugin, stdClass $item, $returnaction, $returnparams) {
         $link = '';
         $showviewlink = false;
+
         $summary = $plugin->view_summary($item, $showviewlink);
         $separator = '';
         if ($showviewlink) {
@@ -550,6 +551,7 @@ class assign_grading_table extends table_sql implements renderable {
     function other_cols($colname, $row){
         if (($pos = strpos($colname, 'assignsubmission_')) !== false) {
             $plugin = $this->assignment->get_submission_plugin_by_type(substr($colname, strlen('assignsubmission_')));
+
             if ($plugin->is_visible() && $plugin->is_enabled()) {
                 if ($row->submissionid) {
                     $submission = new stdClass();
@@ -558,7 +560,6 @@ class assign_grading_table extends table_sql implements renderable {
                     $submission->timemodified = $row->timesubmitted;
                     $submission->assignment = $this->assignment->get_instance()->id;
                     $submission->userid = $row->userid;
-
                     return $this->format_plugin_summary_with_link($plugin, $submission, 'grading', array());
                 }
             }
@@ -567,6 +568,7 @@ class assign_grading_table extends table_sql implements renderable {
         if (($pos = strpos($colname, 'feedback_')) !== false) {
             $plugin = $this->assignment->get_feedback_plugin_by_type(substr($colname, strlen('assignfeedback_')));
             if ($plugin->is_visible() && $plugin->is_enabled()) {
+                $grade = null;
                 if ($row->gradeid) {
                     $grade = new stdClass();
                     $grade->id = $row->gradeid;
@@ -576,7 +578,10 @@ class assign_grading_table extends table_sql implements renderable {
                     $grade->userid = $row->userid;
                     $grade->grade = $row->grade;
                     $grade->mailed = $row->mailed;
-
+                }
+                if ($this->quickgrading && $plugin->supports_quickgrading()) {
+                    return $plugin->get_quickgrading_html($row->userid, $grade);
+                } else if ($grade) {
                     return $this->format_plugin_summary_with_link($plugin, $grade, 'grading', array());
                 }
             }
index 2211bb8..2ab70d6 100644 (file)
@@ -1126,7 +1126,7 @@ class assign {
         // Simple array we'll use for caching modules.
         $modcache = array();
 
-        // Email students about new feedback
+        // Message students about new feedback
         foreach ($submissions as $submission) {
 
             mtrace("Processing assignment submission $submission->id ...");
@@ -2377,7 +2377,7 @@ class assign {
     }
 
     /**
-     * email someone about something (static so it can be called from cron)
+     * Message someone about something (static so it can be called from cron)
      *
      * @param stdClass $userfrom
      * @param stdClass $userto
@@ -2426,7 +2426,7 @@ class assign {
     }
 
     /**
-     * email someone about something
+     * Message someone about something
      *
      * @param stdClass $userfrom
      * @param stdClass $userto
@@ -2440,13 +2440,13 @@ class assign {
     }
 
     /**
-     * Email student upon successful submission
+     * Notify student upon successful submission
      *
      * @global moodle_database $DB
      * @param stdClass $submission
      * @return void
      */
-    private function email_student_submission_receipt(stdClass $submission) {
+    private function notify_student_submission_receipt(stdClass $submission) {
         global $DB;
 
         $adminconfig = $this->get_admin_config();
@@ -2459,13 +2459,13 @@ class assign {
     }
 
     /**
-     * Email graders upon student submissions
+     * Send notifications to graders upon student submissions
      *
      * @global moodle_database $DB
      * @param stdClass $submission
      * @return void
      */
-    private function email_graders(stdClass $submission) {
+    private function notify_graders(stdClass $submission) {
         global $DB;
 
         $late = $this->get_instance()->duedate && ($this->get_instance()->duedate < time());
@@ -2505,8 +2505,8 @@ class assign {
             $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
             $this->update_submission($submission);
             $this->add_to_log('submit for grading', $this->format_submission_for_log($submission));
-            $this->email_graders($submission);
-            $this->email_student_submission_receipt($submission);
+            $this->notify_graders($submission);
+            $this->notify_student_submission_receipt($submission);
         }
     }
 
@@ -2531,17 +2531,20 @@ class assign {
 
         $users = array();
         // first check all the last modified values
-        // Using POST is really unfortunate. A better solution needs to be found here. As we are looking for grades students we could
+        $currentgroup = groups_get_activity_group($this->get_course_module(), true);
+        $participants = $this->list_participants($currentgroup, true);
+
         // gets a list of possible users and look for values based upon that.
-        foreach ($_POST as $key => $value) {
-            if (preg_match('#^grademodified_(\d+)$#', $key, $matches)) {
+        foreach ($participants as $userid => $unused) {
+            $modified = optional_param('grademodified_' . $userid, -1, PARAM_INT);
+            if ($modified >= 0) {
                 // gather the userid, updated grade and last modified value
                 $record = new stdClass();
-                $record->userid = (int)$matches[1];
-                $record->grade = required_param('quickgrade_' . $record->userid, PARAM_INT);
-                $record->lastmodified = clean_param($value, PARAM_INT);
-                $record->gradinginfo = grade_get_grades($this->get_course()->id, 'mod', 'assign', $this->get_instance()->id, array($record->userid));
-                $users[$record->userid] = $record;
+                $record->userid = $userid;
+                $record->grade = required_param('quickgrade_' . $userid, PARAM_INT);
+                $record->lastmodified = $modified;
+                $record->gradinginfo = grade_get_grades($this->get_course()->id, 'mod', 'assign', $this->get_instance()->id, array($userid));
+                $users[$userid] = $record;
             }
         }
         if (empty($users)) {
@@ -2561,6 +2564,7 @@ class assign {
         $modifiedusers = array();
         foreach ($currentgrades as $current) {
             $modified = $users[(int)$current->userid];
+            $grade = $this->get_user_grade($userid, false);
 
             // check to see if the outcomes were modified
             if ($CFG->enableoutcomes) {
@@ -2575,6 +2579,20 @@ class assign {
                 }
             }
 
+            // let plugins participate
+            foreach ($this->feedbackplugins as $plugin) {
+                if ($plugin->is_visible() && $plugin->is_enabled() && $plugin->supports_quickgrading()) {
+                    if ($plugin->is_quickgrading_modified($modified->userid, $grade)) {
+                        if ((int)$current->lastmodified > (int)$modified->lastmodified) {
+                            return get_string('errorrecordmodified', 'assign');
+                        } else {
+                            $modifiedusers[$modified->userid] = $modified;
+                            continue;
+                        }
+                    }
+                }
+            }
+
 
             if (($current->grade < 0 || $current->grade === NULL) &&
                 ($modified->grade < 0 || $modified->grade === NULL)) {
@@ -2602,6 +2620,13 @@ class assign {
 
             $this->update_grade($grade);
 
+            // save plugins data
+            foreach ($this->feedbackplugins as $plugin) {
+                if ($plugin->is_visible() && $plugin->is_enabled() && $plugin->supports_quickgrading()) {
+                    $plugin->save_quickgrading_changes($userid, $grade);
+                }
+            }
+
             // save outcomes
             if ($CFG->enableoutcomes) {
                 $data = array();
@@ -2738,8 +2763,8 @@ class assign {
             $this->add_to_log('submit', $this->format_submission_for_log($submission));
 
             if (!$this->get_instance()->submissiondrafts) {
-                $this->email_student_submission_receipt($submission);
-                $this->email_graders($submission);
+                $this->notify_student_submission_receipt($submission);
+                $this->notify_graders($submission);
             }
             return true;
         }
index 5205435..334bd31 100644 (file)
@@ -114,6 +114,7 @@ if ($chapter) {
 } else {
     add_to_log($course->id, 'book', 'print', 'tool/print/index.php?id='.$cm->id, $book->id, $cm->id);
     $allchapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum');
+    $book->intro = file_rewrite_pluginfile_urls($book->intro, 'pluginfile.php', $context->id, 'mod_book', 'intro', null);
 
     // page header
     ?>
index cb084ed..745ed34 100644 (file)
@@ -290,9 +290,9 @@ $string['notrackforum'] = 'Don\'t track unread posts';
 $string['noviewdiscussionspermission'] = 'You do not have the permission to view discussions in this forum';
 $string['nowallsubscribed'] = 'All forums in {$a} are subscribed.';
 $string['nowallunsubscribed'] = 'All forums in {$a} are not subscribed.';
-$string['nownotsubscribed'] = '{$a->name} will NOT receive copies of \'{$a->forum}\' by email.';
+$string['nownotsubscribed'] = '{$a->name} will NOT be notified of new posts in \'{$a->forum}\'';
 $string['nownottracking'] = '{$a->name} is no longer tracking \'{$a->forum}\'.';
-$string['nowsubscribed'] = '{$a->name} will receive copies of \'{$a->forum}\' by email.';
+$string['nowsubscribed'] = '{$a->name} will be notified of new posts in \'{$a->forum}\'';
 $string['nowtracking'] = '{$a->name} is now tracking \'{$a->forum}\'.';
 $string['numposts'] = '{$a} posts';
 $string['olderdiscussions'] = 'Older discussions';
@@ -376,7 +376,7 @@ $string['startedby'] = 'Started by';
 $string['subject'] = 'Subject';
 $string['subscribe'] = 'Subscribe to this forum';
 $string['subscribeall'] = 'Subscribe everyone to this forum';
-$string['subscribeenrolledonly'] = 'Sorry, only enrolled users are allowed to subscribe to receive forum postings by email.';
+$string['subscribeenrolledonly'] = 'Sorry, only enrolled users are allowed to subscribe to forum post notifications.';
 $string['subscribed'] = 'Subscribed';
 $string['subscribenone'] = 'Unsubscribe everyone from this forum';
 $string['subscribers'] = 'Subscribers';
@@ -422,8 +422,8 @@ $string['unreadpostsone'] = '1 unread post';
 $string['unsubscribe'] = 'Unsubscribe from this forum';
 $string['unsubscribeall'] = 'Unsubscribe from all forums';
 $string['unsubscribeallconfirm'] = 'You are subscribed to {$a} forums now. Do you really want to unsubscribe from all forums and disable forum auto-subscribe?';
-$string['unsubscribealldone'] = 'All your forum subscriptions were removed, you might still receive notifications from forums with forced subscription. If you do not want to receive any emails from this server please go to your profile and disable email address there.';
-$string['unsubscribeallempty'] = 'Sorry, you are not subscribed to any forums. If you do not want to receive any emails from this server please go to your profile and disable email address there.';
+$string['unsubscribealldone'] = 'All optional forum subscriptions were removed. You will still receive notifications from forums with forced subscription. To manage forum notifications go to Messaging in My Profile Settings.';
+$string['unsubscribeallempty'] = 'You are not subscribed to any forums. To disable all notifications from this server go to Messaging in My Profile Settings.';
 $string['unsubscribed'] = 'Unsubscribed';
 $string['unsubscribeshort'] = 'Unsubscribe';
 $string['usermarksread'] = 'Manual message read marking';
index 9bcc409..8ec3069 100644 (file)
@@ -4611,6 +4611,63 @@ function forum_get_subscribed_forums($course) {
     }
 }
 
+/**
+ * Returns an array of forums that the current user is subscribed to and is allowed to unsubscribe from
+ *
+ * @return array An array of unsubscribable forums
+ */
+function forum_get_optional_subscribed_forums() {
+    global $USER, $DB;
+
+    // Get courses that $USER is enrolled in and can see
+    $courses = enrol_get_my_courses();
+    if (empty($courses)) {
+        return array();
+    }
+
+    $courseids = array();
+    foreach($courses as $course) {
+        $courseids[] = $course->id;
+    }
+    list($coursesql, $courseparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED, 'c');
+
+    // get all forums from the user's courses that they are subscribed to and which are not set to forced
+    $sql = "SELECT f.id, cm.id as cm, cm.visible
+              FROM {forum} f
+                   JOIN {course_modules} cm ON cm.instance = f.id
+                   JOIN {modules} m ON m.name = :modulename AND m.id = cm.module
+                   LEFT JOIN {forum_subscriptions} fs ON (fs.forum = f.id AND fs.userid = :userid)
+             WHERE f.forcesubscribe <> :forcesubscribe AND fs.id IS NOT NULL
+                   AND cm.course $coursesql";
+    $params = array_merge($courseparams, array('modulename'=>'forum', 'userid'=>$USER->id, 'forcesubscribe'=>FORUM_FORCESUBSCRIBE));
+    if (!$forums = $DB->get_records_sql($sql, $params)) {
+        return array();
+    }
+
+    $unsubscribableforums = array(); // Array to return
+
+    foreach($forums as $forum) {
+
+        if (empty($forum->visible)) {
+            // the forum is hidden
+            $context = context_module::instance($forum->cm);
+            if (!has_capability('moodle/course:viewhiddenactivities', $context)) {
+                // the user can't see the hidden forum
+                continue;
+            }
+        }
+
+        // subscribe.php only requires 'mod/forum:managesubscriptions' when
+        // unsubscribing a user other than yourself so we don't require it here either
+
+        // A check for whether the forum has subscription set to forced is built into the SQL above
+
+        $unsubscribableforums[] = $forum;
+    }
+
+    return $unsubscribableforums;
+}
+
 /**
  * Adds user to the subscriber list
  *
index a425c6b..f66ad26 100644 (file)
@@ -47,15 +47,20 @@ echo $OUTPUT->header();
 echo $OUTPUT->heading($strunsubscribeall);
 
 if (data_submitted() and $confirm and confirm_sesskey()) {
-    $DB->delete_records('forum_subscriptions', array('userid'=>$USER->id));
+    $forums = forum_get_optional_subscribed_forums();
+
+    foreach($forums as $forum) {
+        forum_unsubscribe($USER->id, $forum->id);
+    }
     $DB->set_field('user', 'autosubscribe', 0, array('id'=>$USER->id));
+
     echo $OUTPUT->box(get_string('unsubscribealldone', 'forum'));
     echo $OUTPUT->continue_button($return);
     echo $OUTPUT->footer();
     die;
 
 } else {
-    $a = $DB->count_records('forum_subscriptions', array('userid'=>$USER->id));
+    $a = count(forum_get_optional_subscribed_forums());
 
     if ($a) {
         $msg = get_string('unsubscribeallconfirm', 'forum', $a);
index 1e7e7c0..9fb94bb 100644 (file)
@@ -194,7 +194,7 @@ class quiz_grading_report extends quiz_default_report {
                 SELECT quiza.*, u.firstname, u.lastname, u.idnumber
                 FROM {quiz_attempts} quiza
                 JOIN {user} u ON u.id = quiza.userid
-                WHERE quiza.uniqueid $asql AND quiza.state == ? AND quiza.quiz = ?",
+                WHERE quiza.uniqueid $asql AND quiza.state = ? AND quiza.quiz = ?",
                 $params);
 
         $attempts = array();
index 63f8ba9..7b33e94 100644 (file)
@@ -16,7 +16,6 @@
         strict="false"
         verbose="false"
         printerClass="Hint_ResultPrinter"
-        printerFile="lib/phpunit/classes/hint_resultprinter.php"
         >
 
     <php>
index 9820246..02ce159 100644 (file)
@@ -124,7 +124,7 @@ class portfolio_plugin_googledocs extends portfolio_plugin_push_base {
         $clientid = $this->get_config('clientid');
         $secret = $this->get_config('secret');
 
-        $this->googleoauth = new google_oauth($clientid, $secret, $returnurl->out(false), google_docs::REALM);
+        $this->googleoauth = new google_oauth($clientid, $secret, $returnurl, google_docs::REALM);
     }
 
     public function instance_sanity_check() {
index d637b54..70200c1 100644 (file)
@@ -124,7 +124,7 @@ class portfolio_plugin_picasa extends portfolio_plugin_push_base {
         $clientid = $this->get_config('clientid');
         $secret = $this->get_config('secret');
 
-        $this->googleoauth = new google_oauth($clientid, $secret, $returnurl->out(false), google_picasa::REALM);
+        $this->googleoauth = new google_oauth($clientid, $secret, $returnurl, google_picasa::REALM);
     }
 
     public function instance_sanity_check() {
index db41d98..ddfc224 100644 (file)
@@ -38,10 +38,16 @@ $popup      = optional_param('popup', 0, PARAM_INT); //==1 if in a popup window?
 list($context, $course, $cm) = get_context_info_array($contextid);
 require_login($course, false, $cm);
 
-$url = new moodle_url('/rating/index.php', array('contextid'=>$contextid,'itemid'=>$itemid,'scaleid'=>$scaleid));
-if ($sort !== 0) {
+$url = new moodle_url('/rating/index.php', array('contextid'=>$contextid,'component'=>$component,'itemid'=>$itemid,'scaleid'=>$scaleid));
+if (!empty($ratingarea)) {
+    $url->param('ratingarea', $ratingarea);
+}
+if (!empty($sort)) {
     $url->param('sort', $sort);
 }
+if (!empty($popup)) {
+    $url->param('popup', $popup);
+}
 $PAGE->set_url($url);
 $PAGE->set_context($context);
 
@@ -84,10 +90,9 @@ if (!$ratings) {
     $msg = get_string('noratings','rating');
     echo html_writer::tag('div', $msg, array('class'=>'mdl-align'));
 } else {
-    $sorturl  = new moodle_url('/index.php', array('contextid' => $contextid, 'itemid' => $itemid, 'scaleid' => $scaleid));
-    if ($popup) {
-        $sorturl->param('popup', $popup);
-    }
+    // To get the sort URL, copy the current URL and remove any previous sort
+    $sorturl = new moodle_url($url);
+    $sorturl->remove_params('sort');
 
     $table = new html_table;
     $table->cellpadding = 3;
index 58f79e1..4cda0af 100644 (file)
@@ -30,5 +30,5 @@ $string['pluginname'] = 'Dropbox';
 $string['apikey'] = 'Dropbox API key';
 $string['dropbox'] = 'Dropbox';
 $string['secret'] = 'Dropbox secret';
-$string['instruction'] = 'You can get your API Key and secret from <a href="http://www.dropbox.com/developers/apps">Dropbox developers</a>';
+$string['instruction'] = 'You can get your API Key and secret from <a href="http://www.dropbox.com/developers/apps">Dropbox developers</a>. When setting up your key please select "Full Dropbox" as the "Access level".';
 $string['dropbox:view'] = 'View a Dropbox folder';
index 3c79232..335f4c9 100644 (file)
@@ -443,6 +443,17 @@ YUI.add('moodle-core_filepicker', function(Y) {
         }
 
     }
+
+    /**
+     * creates a node and adds it to the div with id #filesskin. This is needed for CSS to be able
+     * to overwrite YUI skin styles (instead of using !important that does not work in IE)
+     */
+    Y.Node.createWithFilesSkin = function(node) {
+        if (!Y.one('#filesskin')) {
+            Y.one(document.body).appendChild(Y.Node.create('<div/>').set('id', 'filesskin'));
+        }
+        return Y.one('#filesskin').appendChild(Y.Node.create(node));
+    }
 }, '@VERSION@', {
     requires:['base', 'node', 'yui2-treeview', 'panel', 'cookie', 'datatable', 'datatable-sort']
 });
@@ -692,10 +703,9 @@ M.core_filepicker.init = function(Y, options) {
                 this.selectui.hide();
             }
             if (!this.process_dlg) {
-                this.process_dlg_node = Y.Node.create(M.core_filepicker.templates.processexistingfile);
+                this.process_dlg_node = Y.Node.createWithFilesSkin(M.core_filepicker.templates.processexistingfile);
                 var node = this.process_dlg_node;
                 node.generateID();
-                Y.one(document.body).appendChild(node);
                 this.process_dlg = new Y.Panel({
                     srcNode      : node,
                     headerContent: M.str.repository.fileexistsdialogheader,
@@ -736,9 +746,8 @@ M.core_filepicker.init = function(Y, options) {
                 header = M.str.moodle.info;
             }
             if (!this.msg_dlg) {
-                this.msg_dlg_node = Y.Node.create(M.core_filepicker.templates.message);
+                this.msg_dlg_node = Y.Node.createWithFilesSkin(M.core_filepicker.templates.message);
                 this.msg_dlg_node.generateID();
-                Y.one(document.body).appendChild(this.msg_dlg_node);
 
                 this.msg_dlg = new Y.Panel({
                     srcNode      : this.msg_dlg_node,
@@ -1215,10 +1224,8 @@ M.core_filepicker.init = function(Y, options) {
         },
         render: function() {
             var client_id = this.options.client_id;
-            this.fpnode = Y.Node.create(M.core_filepicker.templates.generallayout).
+            this.fpnode = Y.Node.createWithFilesSkin(M.core_filepicker.templates.generallayout).
                 set('id', 'filepicker-'+client_id);
-            this.selectnode = Y.Node.create(M.core_filepicker.templates.selectlayout);
-            Y.one(document.body).appendChild(this.fpnode);
             this.mainui = new Y.Panel({
                 srcNode      : this.fpnode,
                 headerContent: M.str.repository.filepicker,
@@ -1239,9 +1246,8 @@ M.core_filepicker.init = function(Y, options) {
                 this.mainui.set('y', 0);
             }
             // create panel for selecting a file (initially hidden)
-            this.selectnode = Y.Node.create(M.core_filepicker.templates.selectlayout).
+            this.selectnode = Y.Node.createWithFilesSkin(M.core_filepicker.templates.selectlayout).
                 set('id', 'filepicker-select-'+client_id);
-            Y.one(document.body).appendChild(this.selectnode);
             this.selectui = new Y.Panel({
                 srcNode      : this.selectnode,
                 zIndex       : 600000,
index 6ccb33b..df0f23e 100644 (file)
@@ -39,12 +39,14 @@ class repository_googledocs extends repository {
     public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) {
         parent::__construct($repositoryid, $context, $options);
 
-        $returnurl = new moodle_url('/repository/repository_callback.php',
-            array('callback' => 'yes', 'repo_id' =>$this->id));
+        $returnurl = new moodle_url('/repository/repository_callback.php');
+        $returnurl->param('callback', 'yes');
+        $returnurl->param('repo_id', $this->id);
+        $returnurl->param('sesskey', sesskey());
 
         $clientid = get_config('googledocs', 'clientid');
         $secret = get_config('googledocs', 'secret');
-        $this->googleoauth = new google_oauth($clientid, $secret, $returnurl->out(false), google_docs::REALM);
+        $this->googleoauth = new google_oauth($clientid, $secret, $returnurl, google_docs::REALM);
 
         $this->check_login();
     }
index 3abca8d..5f72baf 100644 (file)
@@ -648,13 +648,14 @@ abstract class repository {
      * This function is used to copy a moodle file to draft area
      *
      * @param string $encoded The metainfo of file, it is base64 encoded php serialized data
-     * @param int $draftitemid itemid
-     * @param string $new_filepath the new path in draft area
-     * @param string $new_filename The intended name of file
+     * @param stdClass|array $filerecord contains itemid, filepath, filename and optionally other
+     *      attributes of the new file
+     * @param int $maxbytes maximum allowed size of file, -1 if unlimited. If size of file exceeds
+     *      the limit, the file_exception is thrown.
      * @return array The information of file
      */
-    public function copy_to_area($encoded, $draftitemid, $new_filepath, $new_filename) {
-        global $USER, $DB;
+    public function copy_to_area($encoded, $filerecord, $maxbytes = -1) {
+        global $USER;
         $fs = get_file_storage();
         $browser = get_file_browser();
 
@@ -662,9 +663,17 @@ abstract class repository {
             throw new coding_exception('Only repository used to browse moodle files can use repository::copy_to_area()');
         }
 
-
         $params = unserialize(base64_decode($encoded));
-        $user_context = get_context_instance(CONTEXT_USER, $USER->id);
+        $user_context = context_user::instance($USER->id);
+
+        $filerecord = (array)$filerecord;
+        // make sure the new file will be created in user draft area
+        $filerecord['component'] = 'user';
+        $filerecord['filearea'] = 'draft';
+        $filerecord['contextid'] = $user_context->id;
+        $draftitemid = $filerecord['itemid'];
+        $new_filepath = $filerecord['filepath'];
+        $new_filename = $filerecord['filename'];
 
         $contextid  = clean_param($params['contextid'], PARAM_INT);
         $fileitemid = clean_param($params['itemid'],    PARAM_INT);
@@ -676,11 +685,15 @@ abstract class repository {
         $context    = get_context_instance_by_id($contextid);
         // the file needs to copied to draft area
         $file_info  = $browser->get_file_info($context, $component, $filearea, $fileitemid, $filepath, $filename);
+        if ($maxbytes !== -1 && $file_info->get_filesize() > $maxbytes) {
+            throw new file_exception('maxbytes');
+        }
 
         if (repository::draftfile_exists($draftitemid, $new_filepath, $new_filename)) {
             // create new file
             $unused_filename = repository::get_unused_filename($draftitemid, $new_filepath, $new_filename);
-            $file_info->copy_to_storage($user_context->id, 'user', 'draft', $draftitemid, $new_filepath, $unused_filename);
+            $filerecord['filename'] = $unused_filename;
+            $file_info->copy_to_storage($filerecord);
             $event = array();
             $event['event'] = 'fileexists';
             $event['newfile'] = new stdClass;
@@ -690,12 +703,13 @@ abstract class repository {
             $event['existingfile'] = new stdClass;
             $event['existingfile']->filepath = $new_filepath;
             $event['existingfile']->filename = $new_filename;
-            $event['existingfile']->url      = moodle_url::make_draftfile_url($draftitemid, $filepath, $filename)->out();;
+            $event['existingfile']->url      = moodle_url::make_draftfile_url($draftitemid, $new_filepath, $new_filename)->out();;
             return $event;
         } else {
-            $file_info->copy_to_storage($user_context->id, 'user', 'draft', $draftitemid, $new_filepath, $new_filename);
+            $file_info->copy_to_storage($filerecord);
             $info = array();
             $info['itemid'] = $draftitemid;
+            $info['file']  = $new_filename;
             $info['title']  = $new_filename;
             $info['contextid'] = $user_context->id;
             $info['url'] = moodle_url::make_draftfile_url($draftitemid, $new_filepath, $new_filename)->out();;
@@ -1464,6 +1478,7 @@ abstract class repository {
      * @return int file size in bytes
      */
     public function get_file_size($source) {
+        // TODO MDL-33297 remove this function completely?
         $browser    = get_file_browser();
         $params     = unserialize(base64_decode($source));
         $contextid  = clean_param($params['contextid'], PARAM_INT);
index 9022380..0d0b63c 100644 (file)
@@ -41,12 +41,14 @@ class repository_picasa extends repository {
     public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) {
         parent::__construct($repositoryid, $context, $options);
 
-        $returnurl = new moodle_url('/repository/repository_callback.php',
-            array('callback' => 'yes', 'repo_id' =>$this->id));
+        $returnurl = new moodle_url('/repository/repository_callback.php');
+        $returnurl->param('callback', 'yes');
+        $returnurl->param('repo_id', $this->id);
+        $returnurl->param('sesskey', sesskey());
 
         $clientid = get_config('picasa', 'clientid');
         $secret = get_config('picasa', 'secret');
-        $this->googleoauth = new google_oauth($clientid, $secret, $returnurl->out(false), google_picasa::REALM);
+        $this->googleoauth = new google_oauth($clientid, $secret, $returnurl, google_picasa::REALM);
 
         $this->check_login();
     }
index a491015..2c1acf2 100644 (file)
@@ -180,19 +180,28 @@ class repository_recent extends repository {
     /**
      * This function overwrite the default implement to copying file using file_storage
      *
-     * @global object $USER
-     * @global object $DB
      * @param string $encoded The information of file, it is base64 encoded php serialized data
-     * @param string $draftitemid itemid
-     * @param string $new_filename The intended name of file
-     * @param string $new_filepath the new path in draft area
+     * @param stdClass|array $filerecord contains itemid, filepath, filename and optionally other
+     *      attributes of the new file
+     * @param int $maxbytes maximum allowed size of file, -1 if unlimited. If size of file exceeds
+     *      the limit, the file_exception is thrown.
      * @return array The information of file
      */
-    public function copy_to_area($encoded, $draftitemid, $new_filepath, $new_filename) {
-        global $USER, $DB;
+    public function copy_to_area($encoded, $filerecord, $maxbytes = -1) {
+        global $USER;
 
         $user_context = get_context_instance(CONTEXT_USER, $USER->id);
 
+        $filerecord = (array)$filerecord;
+        // make sure the new file will be created in user draft area
+        $filerecord['component'] = 'user'; // make sure
+        $filerecord['filearea'] = 'draft'; // make sure
+        $filerecord['contextid'] = $user_context->id;
+        $filerecord['sortorder'] = 0;
+        $draftitemid = $filerecord['itemid'];
+        $new_filepath = $filerecord['filepath'];
+        $new_filename = $filerecord['filename'];
+
         $fs = get_file_storage();
 
         $params = unserialize(base64_decode($encoded));
@@ -211,21 +220,23 @@ class repository_recent extends repository {
         //
         // To get 'recent' plugin working, we need to use lower level file_stoarge class to bypass the
         // capability check, we will use a better workaround to improve it.
+        // TODO MDL-33297 apply here
         if ($stored_file = $fs->get_file($contextid, $component, $filearea, $fileitemid, $filepath, $filename)) {
             // verify user id
             if ($USER->id != $stored_file->get_userid()) {
                 throw new moodle_exception('errornotyourfile', 'repository');
             }
-            $file_record = array('contextid'=>$user_context->id, 'component'=>'user', 'filearea'=>'draft',
-                'itemid'=>$draftitemid, 'filepath'=>$new_filepath, 'filename'=>$new_filename, 'sortorder'=>0);
+            if ($maxbytes !== -1 && $stored_file->get_filesize() > $maxbytes) {
+                throw new file_exception('maxbytes');
+            }
 
             // test if file already exists
             if (repository::draftfile_exists($draftitemid, $new_filepath, $new_filename)) {
                 // create new file
                 $unused_filename = repository::get_unused_filename($draftitemid, $new_filepath, $new_filename);
-                $file_record['filename'] = $unused_filename;
+                $filerecord['filename'] = $unused_filename;
                 // create a tmp file
-                $fs->create_file_from_storedfile($file_record, $stored_file);
+                $fs->create_file_from_storedfile($filerecord, $stored_file);
                 $event = array();
                 $event['event'] = 'fileexists';
                 $event['newfile'] = new stdClass;
@@ -238,9 +249,10 @@ class repository_recent extends repository {
                 $event['existingfile']->url      = moodle_url::make_draftfile_url($draftitemid, $new_filepath, $new_filename)->out();;
                 return $event;
             } else {
-                $fs->create_file_from_storedfile($file_record, $stored_file);
+                $fs->create_file_from_storedfile($filerecord, $stored_file);
                 $info = array();
                 $info['title']  = $new_filename;
+                $info['file']  = $new_filename;
                 $info['itemid'] = $draftitemid;
                 $info['filesize']  = $stored_file->get_filesize();
                 $info['url'] = moodle_url::make_draftfile_url($draftitemid, $new_filepath, $new_filename)->out();;
index aa1e434..240faf3 100644 (file)
@@ -209,30 +209,6 @@ switch ($action) {
             die;
         } else {
             $fs = get_file_storage();
-            // Some repository plugins are hosting moodle internal files, we cannot use get_file
-            // method, so we use copy_to_area method
-            // (local, user, coursefiles, recent)
-            if ($repo->has_moodle_files() && !$usefilereference) {
-                // check filesize against max allowed size
-                $filesize = $repo->get_file_size($source);
-                if (empty($filesize)) {
-                    $filesize = 0;
-                }
-                if (($maxbytes !== -1) && ($filesize > $maxbytes)) {
-                    throw new file_exception('maxbytes');
-                }
-                // If the moodle file is an alias to a file in external repository
-                // we copy this alias instead of create alias to alias
-                // {@link repository::copy_to_area()}.
-                $fileinfo = $repo->copy_to_area($source, $itemid, $saveas_path, $saveas_filename);
-
-                if (!isset($fileinfo['event'])) {
-                    $fileinfo['file'] = $fileinfo['title'];
-                }
-
-                echo json_encode($fileinfo);
-                die;
-            }
 
             // Prepare file record.
             $record = new stdClass();
@@ -240,21 +216,9 @@ switch ($action) {
             $record->filename = $saveas_filename;
             $record->component = 'user';
             $record->filearea = 'draft';
-            if (!is_numeric($itemid)) {
-                $record->itemid = 0;
-            } else {
-                $record->itemid   = $itemid;
-            }
-            if (!empty($file['license'])) {
-                $record->license  = $file['license'];
-            } else {
-                $record->license  = $license;
-            }
-            if (!empty($file['author'])) {
-                $record->author   = $file['author'];
-            } else {
-                $record->author   = $author;
-            }
+            $record->itemid = $itemid;
+            $record->license = $license;
+            $record->author = $author;
 
             if ($record->filepath !== '/') {
                 $record->filepath = trim($record->filepath, '/');
@@ -263,10 +227,9 @@ switch ($action) {
             $usercontext = get_context_instance(CONTEXT_USER, $USER->id);
             $now = time();
             $record->contextid = $usercontext->id;
-            $record->timecreated  = $now;
+            $record->timecreated = $now;
             $record->timemodified = $now;
-            $record->userid       = $USER->id;
-
+            $record->userid = $USER->id;
 
             if ($usefilereference) {
                 $reference = $repo->get_file_reference($source);
@@ -291,21 +254,30 @@ switch ($action) {
                     $event['existingfile']->filepath = $saveas_path;
                     $event['existingfile']->filename = $saveas_filename;
                     $event['existingfile']->url      = moodle_url::make_draftfile_url($itemid, $saveas_path, $saveas_filename)->out();;
-                    echo json_encode($event);
-                    die;
+                } else {
+                    $storedfile = $fs->create_file_from_reference($record, $repo_id, $reference);
+                    $event = array(
+                        'url'=>moodle_url::make_draftfile_url($storedfile->get_itemid(), $storedfile->get_filepath(), $storedfile->get_filename())->out(),
+                        'id'=>$storedfile->get_itemid(),
+                        'file'=>$storedfile->get_filename(),
+                        'icon' => $OUTPUT->pix_url(file_file_icon($storedfile, 32))->out(),
+                    );
                 }
-                $storedfile = $fs->create_file_from_reference($record, $repo_id, $reference);
                 // Repository plugin callback
                 // You can cache reository file in this callback
                 // or complete other tasks.
                 $repo->cache_file_by_reference($reference, $storedfile);
-                $info = array(
-                    'url'=>moodle_url::make_draftfile_url($storedfile->get_itemid(), $storedfile->get_filepath(), $storedfile->get_filename())->out(),
-                    'id'=>$storedfile->get_itemid(),
-                    'file'=>$storedfile->get_filename(),
-                    'icon' => $OUTPUT->pix_url(file_file_icon($storedfile, 32))->out(),
-                );
-                echo json_encode($info);
+                echo json_encode($event);
+                die;
+            } else if ($repo->has_moodle_files()) {
+                // Some repository plugins (local, user, coursefiles, recent) are hosting moodle
+                // internal files, we cannot use get_file method, so we use copy_to_area method
+
+                // If the moodle file is an alias we copy this alias, otherwise we copy the file
+                // {@link repository::copy_to_area()}.
+                $fileinfo = $repo->copy_to_area($source, $record, $maxbytes);
+
+                echo json_encode($fileinfo);
                 die;
             } else {
                 // Download file to moodle.
index fa7eaf3..a307ab6 100644 (file)
@@ -171,7 +171,7 @@ class repository_upload extends repository {
 
         if ($this->mimetypes != '*') {
             // check filetype
-            $filemimetype = file_storage::mimetype($_FILES[$elname]['tmp_name']);
+            $filemimetype = file_storage::mimetype($_FILES[$elname]['tmp_name'], $record->filename);
             if (!in_array($filemimetype, $this->mimetypes)) {
                 throw new moodle_exception('invalidfiletype', 'repository', '', get_mimetype_description(array('filename' => $_FILES[$elname]['name'])));
             }
index 5067068..b6ed919 100644 (file)
@@ -2,12 +2,12 @@
  * File Picker and File Manager
  */
 
-.filemanager, .file-picker {font-size:11px;color: #555;letter-spacing: .2px;}
-.filemanager a, .file-picker a {color:#555;}
-.filemanager a:hover, .file-picker a:hover {color:#555;text-decoration: none;}
+.filemanager, .file-picker {font-size:11px;color: #555555;letter-spacing: .2px;}
+.filemanager a, .file-picker a {color:#555555;}
+.filemanager a:hover, .file-picker a:hover {color:#555555;text-decoration: none;}
 .filemanager select, .filemanager input, .filemanagerbutton, .filemanager textarea,
-.file-picker select, .file-picker input, .file-picker button, .file-picker textarea {color:#555; letter-spacing: .2px;}
-.filemanager input[type="text"], .file-picker input[type="text"] {border: 1px solid #BBB;width: 265px;height: 18px;padding: 1px 6px;}
+.file-picker select, .file-picker input, .file-picker button, .file-picker textarea {color:#555555; letter-spacing: .2px;}
+.filemanager input[type="text"], .file-picker input[type="text"] {border: 1px solid #BBBBBB;width: 265px;height: 18px;padding: 1px 6px;}
 .filemanager select, .file-picker select {height: 22px;padding: 2px 1px;}
 .fp-content-center {height: 100%;width: 100%;display:table-cell;vertical-align: middle;}
 
  * Dialogue (File Picker and File Manager)
  */
 .yui3-panel-focused {outline: none;}
-.yui3-panel-content {padding-bottom: 20px!important;background: #F2F2F2!important;border-radius: 8px;border: 1px solid #FFF!important;display: inline-block;-webkit-box-shadow: 5px 5px 20px 0px #666!important;-moz-box-shadow: 5px 5px 20px 0px #666!important;box-shadow: 5px 5px 20px 0px #666!important;}
-.yui3-widget-hd {border-radius: 10px 10px 0px 0px;border-bottom: 1px solid #BBB;padding:5px 5px 5px 5px!important;text-align: center;font-size:12px;letter-spacing: 1px;color:#333!important; text-shadow: 1px 1px 1px #FFF;filter: dropshadow(color=#FFF, offx=1, offy=1);
-background: #CCC!important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFF', endColorstr='#CCC')!important;background: -webkit-gradient(linear, left top, left bottom, from(#FFF), to(#CCC))!important;background: -moz-linear-gradient(top,  #FFF,  #CCC)!important;}
-.fp-panel-button {background: #FFF;padding: 3px 20px 2px 20px; text-align: center;margin:10px; border-radius: 10px;display: inline-block;-webkit-box-shadow: 2px 2px 3px .1px #999;-moz-box-shadow: 2px 2px 3px .1px #999;box-shadow: 2px 2px 3px .1px #999;}
+#filesskin .yui3-panel-content {padding-bottom: 20px;background: #F2F2F2;border-radius: 8px;border: 1px solid #FFFFFF;display: inline-block;-webkit-box-shadow: 5px 5px 20px 0px #666666;-moz-box-shadow: 5px 5px 20px 0px #666666;box-shadow: 5px 5px 20px 0px #666666;}
+#filesskin .yui3-widget-hd {border-radius: 10px 10px 0px 0px;border-bottom: 1px solid #BBBBBB;padding:5px 5px 5px 5px;text-align: center;font-size:12px;letter-spacing: 1px;color:#333333; text-shadow: 1px 1px 1px #FFFFFF;filter: dropshadow(color=#FFFFFF, offx=1, offy=1);
+background: #CCCCCC;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFF', endColorstr='#CCCCCC');background: -webkit-gradient(linear, left top, left bottom, from(#FFFFFF), to(#CCCCCC));background: -moz-linear-gradient(top,  #FFFFFF,  #CCCCCC);}
+.fp-panel-button {background: #FFFFFF;padding: 3px 20px 2px 20px; text-align: center;margin:10px; border-radius: 10px;display: inline-block;-webkit-box-shadow: 2px 2px 3px .1px #999999;-moz-box-shadow: 2px 2px 3px .1px #999999;box-shadow: 2px 2px 3px .1px #999999;}
 
 /*
  * File Picker layout
  */
-.file-picker.fp-generallayout {width: 724px;background: #FFF!important;border-radius:10px;border: 1px solid #CCC!important;position: relative;}
-.file-picker .fp-repo-area {width:180px;overflow:auto;display:inline-block;border-right:1px solid #BBB;position:absolute;top:26px;bottom:1px;}
+#filesskin .file-picker.fp-generallayout {width: 724px;background: #FFFFFF;border-radius:10px;border: 1px solid #CCCCCC;position: relative;}
+.file-picker .fp-repo-area {width:180px;overflow:auto;display:inline-block;border-right:1px solid #BBBBBB;position:absolute;top:26px;bottom:1px;}
 .file-picker .fp-repo-items {vertical-align:top;display: inline-block;margin-left: 181px;}
-.file-picker .fp-navbar {background: #F2F2F2;min-height:22px;border-bottom: 1px solid #BBB;padding: 5px 8px;}
-.file-picker .fp-content {background: #FFF;clear: both;overflow:auto;width: 543px;height: 349px;margin-bottom:-14px;}
+.file-picker .fp-navbar {background: #F2F2F2;min-height:22px;border-bottom: 1px solid #BBBBBB;padding: 5px 8px;}
+.file-picker .fp-content {background: #FFFFFF;clear: both;overflow:auto;width: 543px;height: 349px;margin-bottom:-14px;}
 .file-picker .fp-content-loading {height: 100%;width: 100%;display: table;text-align:center;}
 .file-picker .fp-content .fp-object-container {width:98%;height:98%;}
 
@@ -38,23 +38,20 @@ background: #CCC!important;filter: progid:DXImageTransform.Microsoft.gradient(st
 .dir-rtl .file-picker .fp-list {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-repo-icon {padding: 0px 7px 0px 5px;}
+.file-picker .fp-list .fp-repo-icon {padding: 0px 7px 0px 5px;}
 
 /*
  * Tools, Path & View on fp-navbar (File Picker and File Manager)
  */
-.fp-toolbar {/*display: table-row;*/display: block;line-height: 22px;float:left;}
+.fp-toolbar {display: table-row;line-height: 22px;float:left;/*display: inline-block;*/}
 .fp-toolbar.empty {display:none;}
 .fp-toolbar .disabled {display:none;}
 .fp-toolbar div {display: inline-block;padding: 0px 2px;padding-right: 10px;}
 .fp-toolbar img {vertical-align: -15%; margin-right: 5px;}
-.file-picker .search-entry {background:#FFF url('[[pix:a/search]]') no-repeat 3px 3px;height:18px;width:230px;border: 1px solid #BBB;padding-left:20px;}
+.fp-toolbar .fp-tb-search {width: 228px;height: 14px;}
+.fp-toolbar .fp-tb-search input {background:#FFFFFF url('[[pix:a/search]]') no-repeat 3px 3px;padding: 2px 6px 1px 20px;width: 200px;height: 16px;border: 1px solid #BBBBBB;}
 
-.file-picker .fp-pathbar {display: table-row;}
-.fp-pathbar .fp-path-folder {background:url('[[pix:theme|fp/path_folder]]') no-repeat 0 0;width:27px;height:12px;margin-left: 4px;}
-.fp-pathbar .fp-path-folder-name {margin-left: 32px;line-height: 20px;}
-
-.fp-viewbar {float:right;width:69px;height:22px;margin-right:8px;}
+.fp-viewbar {float:right;width:69px;height:22px;margin-right:8px;/*display: inline-block;*/}
 .fp-vb-icons {background:url('[[pix:theme|fp/view_icon_active]]') no-repeat 0 0;width:22px;height:22px;display: inline-block;}
 .fp-vb-icons.checked {background:url('[[pix:theme|fp/view_icon_selected]]');}
 .fp-viewbar.disabled .fp-vb-icons {background:url('[[pix:theme|fp/view_icon_inactive]]');}
@@ -64,29 +61,31 @@ background: #CCC!important;filter: progid:DXImageTransform.Microsoft.gradient(st
 .fp-vb-tree {background:url('[[pix:theme|fp/view_tree_active]]') no-repeat 0px 0px;width:23px;height:22px;display: inline-block;margin-left: -4px;}
 .fp-vb-tree.checked {background:url('[[pix:theme|fp/view_tree_selected]]');}
 .fp-viewbar.disabled .fp-vb-tree {background:url('[[pix:theme|fp/view_tree_inactive]]');}
-.file-picker .fp-clear-right {clear: right;}
+.file-picker .fp-clear-left {clear: left;}
+
+.file-picker .fp-pathbar {display: table-row;/*display: inline-block;*/}
+.fp-pathbar.empty {display: none;}
+.fp-pathbar .fp-path-folder {background:url('[[pix:theme|fp/path_folder]]') no-repeat 0 0;width:27px;height:12px;margin-left: 4px;}
+.fp-pathbar .fp-path-folder-name {margin-left: 32px;line-height: 20px;}
 
 /*
  * Icon view (File Picker and File Manager)
  */
 .fp-iconview .fp-file {float: left;text-align: center;position: relative;margin: 10px 10px 35px;}
-.fp-iconview .fp-thumbnail {min-width:110px;min-height:110px;line-height: 110px;text-align: center;border: 1px solid #FFF;}
-.fp-iconview .fp-thumbnail img {border: 1px solid #DDD;padding:3px;vertical-align: middle;-webkit-box-shadow: 1px 1px 2px 0px #CCC;-moz-box-shadow: 1px 1px 2px 0px #CCC;box-shadow: 1px 1px 2px 0px #CCC;}
-.fp-iconview .fp-thumbnail:hover {background: #FFF;border: 1px solid #DDD;-webkit-box-shadow: inset 0px 0px 10px 0px #CCC;-moz-box-shadow: inset 0px 0px 10px 0px #CCC;box-shadow: inset 0px 0px 10px 0px #CCC;}
+.fp-iconview .fp-thumbnail {min-width:110px;min-height:110px;line-height: 110px;text-align: center;border: 1px solid #FFFFFF;display: block;}
+.fp-iconview .fp-thumbnail img {border: 1px solid #DDDDDD;padding:3px;vertical-align: middle;-webkit-box-shadow: 1px 1px 2px 0px #CCCCCC;-moz-box-shadow: 1px 1px 2px 0px #CCCCCC;box-shadow: 1px 1px 2px 0px #CCCCCC;}
+.fp-iconview .fp-thumbnail:hover {background: #FFFFFF;border: 1px solid #DDDDDD;-webkit-box-shadow: inset 0px 0px 10px 0px #CCCCCC;-moz-box-shadow: inset 0px 0px 10px 0px #CCCCCC;box-shadow: inset 0px 0px 10px 0px #CCCCCC;}
 .fp-iconview .fp-filename-field {height:33px;word-wrap:break-word;overflow: hidden;position: absolute;}
 .fp-iconview .fp-filename-field:hover {overflow: visible;z-index: 1000;}
-.fp-iconview .fp-filename-field .fp-filename {background: #FFF;padding-top: 5px;padding-bottom: 12px;min-width:112px;}
+.fp-iconview .fp-filename-field .fp-filename {background: #FFFFFF;padding-top: 5px;padding-bottom: 12px;min-width:112px;}
 
 /*
  * Table view (File Picker only)
  */
-.file-picker .yui3-datatable table {border: 0px solid #BBB;width:100%;}
-.file-picker .yui3-datatable-header {background: #FFF;border-bottom: 1px solid #CCC;border-left: 0 solid #FFF;color: #555;}
-.file-picker .yui3-datatable-columns .yui3-datatable-sorted, .file-picker .yui3-datatable-sortable-column:hover {background-color: #FFF;}
-.file-picker .yui3-datatable-odd .yui3-datatable-cell {background-color: #F6F6F6;border-left: 0px solid #F6F6F6;}
-.file-picker .yui3-datatable-data .yui3-datatable-odd .yui3-datatable-sorted {background-color: #F6F6F6;}
-.file-picker .yui3-datatable-even .yui3-datatable-cell {background-color: #FFF;border-left: 0px solid #FFF;}
-.file-picker .yui3-datatable-data .yui3-datatable-even .yui3-datatable-sorted {background-color: #FFF;}
+.file-picker .yui3-datatable table {border: 0px solid #BBBBBB;width:100%;}
+#filesskin .file-picker .yui3-datatable-header {background: #FFFFFF;border-bottom: 1px solid #CCCCCC;border-left: 0 solid #FFFFFF;color: #555555;}
+#filesskin .file-picker .yui3-datatable-odd .yui3-datatable-cell {background-color: #F6F6F6;border-left: 0px solid #F6F6F6;}
+#filesskin .file-picker .yui3-datatable-even .yui3-datatable-cell {background-color: #FFFFFF;border-left: 0px solid #FFFFFF;}
 
 /*
  * Tree view (File Manager only)
@@ -127,9 +126,9 @@ background: #CCC!important;filter: progid:DXImageTransform.Microsoft.gradient(st
 .filemanager .ygtvlabel,.filemanager .ygtvlabel:link,.filemanager .ygtvlabel:visited,.filemanager .ygtvlabel:hover {margin-left:2px;text-decoration: none;}*/
 a.ygtvspacer:hover {color: transparent;text-decoration: none;}
 .ygtvlabel, .ygtvlabel:link, .ygtvlabel:visited, .ygtvlabel:hover {background-color: transparent;cursor: pointer;margin-left: 2px;text-decoration: none;}
-.file-picker .ygtvfocus, .filemanager .ygtvfocus {background-color: #EEE;}
+.file-picker .ygtvfocus, .filemanager .ygtvfocus {background-color: #EEEEEE;}
 
-.fp-filename-icon {margin-top: 10px;display: block;/*top: -10px;position: relative;*/}
+.fp-filename-icon {margin-top: 10px;display: block;position: relative;}
 .fp-icon {float: left;margin-top: -7px;width: 24px;height: 24px;margin-right: 10px;text-align: center;line-height: 24px;}
 .fp-icon img {max-height:24px;max-width:24px;vertical-align: middle;}
 .fp-filename {padding-right: 10px;}
@@ -184,14 +183,14 @@ a.ygtvspacer:hover {color: transparent;text-decoration: none;}
  */
 .file-picker.fp-select {width:420px;}
 .fp-select .fp-select-loading {text-align: center;margin-top: 20px;}
-.fp-select .fp-hr {clear: both;height: 1px; background-color: #FFF;border-bottom: 1px solid #BBB;width: auto; margin: 5px 20px;}
+.fp-select .fp-hr {clear: both;height: 1px; background-color: #FFFFFF;border-bottom: 1px solid #BBBBBB;width: auto; margin: 5px 20px;}
 .fp-select table {margin: 10px 20px;}
 .fp-select-update {float:right;margin-right: 20px;}
 .fp-select .fp-file-update {background:url('[[pix:theme|fp/check]]') no-repeat left center;width:17px;height:17px;}
 .fp-select .fp-file-cancel {background:url('[[pix:theme|fp/cross]]') no-repeat left center;width:17px;height:17px;margin-left: 25px;}
 .fp-select .fp-select-update span {margin-left: 17px;}
-.fp-select .fp-thumbnail {float:left;min-width:110px;min-height:110px;line-height: 110px;text-align: center;margin: 10px 20px 0px 20px;background: #FFF;border: 1px solid #DDD;-webkit-box-shadow: inset 0px 0px 10px 0px #CCC;-moz-box-shadow: inset 0px 0px 10px 0px #CCC;box-shadow: inset 0px 0px 10px 0px #CCC;}
-.fp-select .fp-thumbnail img {border: 1px solid #DDD;padding:3px;vertical-align: middle;margin: 10px;}
+.fp-select .fp-thumbnail {float:left;min-width:110px;min-height:110px;line-height: 110px;text-align: center;margin: 10px 20px 0px 20px;background: #FFFFFF;border: 1px solid #DDDDDD;-webkit-box-shadow: inset 0px 0px 10px 0px #CCCCCC;-moz-box-shadow: inset 0px 0px 10px 0px #CCCCCC;box-shadow: inset 0px 0px 10px 0px #CCCCCC;}
+.fp-select .fp-thumbnail img {border: 1px solid #DDDDDD;padding:3px;vertical-align: middle;margin: 10px;}
 .fp-select .fp-fileinfo {display: inline-block;margin-top: 4px;margin-right: 20px;}
 .file-picker.fp-select .fp-fileinfo {max-width:240px;}
 .fp-select .fp-fileinfo div {padding: 4px 0px;}
@@ -224,12 +223,12 @@ a.ygtvspacer:hover {color: transparent;text-decoration: none;}
  * File Manager layout
  */
 .fp-restrictions{text-align: right;}
-.filemanager .fp-navbar {background: #F2F2F2;border-top: 1px solid #BBB;border-left: 1px solid #BBB;border-right: 1px solid #BBB;}
+.filemanager .fp-navbar {background: #F2F2F2;border-top: 1px solid #BBBBBB;border-left: 1px solid #BBBBBB;border-right: 1px solid #BBBBBB;}
 .filemanager-toolbar{padding: 5px 8px;min-height:22px;}
-.fp-pathbar {border-top: 1px solid #BBB;padding: 5px 8px 1px;min-height: 20px;}
+.fp-pathbar {border-top: 1px solid #BBBBBB;padding: 5px 8px 1px;min-height: 20px;}
 .filemanager .fp-pathbar.empty {display:none;}
 .filepicker-filelist,
-.filemanager-container {background: #FFF;clear: both;overflow:auto;border: 1px solid #BBB;min-height: 140px;position: relative;}
+.filemanager-container {background: #FFFFFF;clear: both;overflow:auto;border: 1px solid #BBBBBB;min-height: 140px;position: relative;}
 /*.filemanager-container ul{margin:0;padding:0;}
 .filemanager-container ul li{white-space:nowrap;list-style-type:none;}
 .filemanager-container ul li a{padding:0}*/
@@ -247,13 +246,10 @@ a.ygtvspacer:hover {color: transparent;text-decoration: none;}
 /*
  * Table view (File Manager only)
  */
-.filemanager .yui3-datatable table {border: 0px solid #BBB;width:100%;}
-.filemanager .yui3-datatable-header {background: #FFF;border-bottom: 1px solid #CCC;border-left: 0 solid #FFF;color: #555;}
-.filemanager .yui3-datatable-columns .yui3-datatable-sorted, .filemanager .yui3-datatable-sortable-column:hover {background-color: #FFF;}
-.filemanager .yui3-datatable-odd .yui3-datatable-cell {background-color: #F6F6F6;border-left: 0px solid #F6F6F6;}
-.filemanager .yui3-datatable-data .yui3-datatable-odd .yui3-datatable-sorted {background-color: #F6F6F6;}
-.filemanager .yui3-datatable-even .yui3-datatable-cell {background-color: #FFF;border-left: 0px solid #FFF;}
-.filemanager .yui3-datatable-data .yui3-datatable-even .yui3-datatable-sorted {background-color: #FFF;}
+.filemanager .yui3-datatable table {border: 0px solid #BBBBBB;width:100%;}
+.filemanager .yui3-datatable-header {background: #FFFFFF!important;border-bottom: 1px solid #CCCCCC!important;border-left: 0 solid #FFFFFF!important;color: #555555!important;}
+.filemanager .yui3-datatable-odd .yui3-datatable-cell {background-color: #F6F6F6!important;border-left: 0px solid #F6F6F6;}
+.filemanager .yui3-datatable-even .yui3-datatable-cell {background-color: #FFFFFF!important;border-left: 0px solid #FFFFFF;}
 
 /*
  * Folder Context Menu (File Manager only)
@@ -261,17 +257,17 @@ a.ygtvspacer:hover {color: transparent;text-decoration: none;}
 .filemanager .fp-contextmenu {display:none;}
 .filemanager .fp-iconview .fp-folder.fp-hascontextmenu .fp-contextmenu {display:block;position:absolute;right:7px;bottom:5px;z-index: 2000;}
 .filemanager .fp-treeview .fp-folder.fp-hascontextmenu .fp-contextmenu,
-.filemanager .fp-tableview .fp-folder.fp-hascontextmenu .fp-contextmenu {/*display: inline;*//*position: relative;left: 14px;margin-right: -20px;top: 6px;background: yellow;*/}
+.filemanager .fp-tableview .fp-folder.fp-hascontextmenu .fp-contextmenu {display: inline;position: absolute;left: 14px;margin-right: -20px;top: 6px;}
 
 /*
  * Drag and drop support (File Manager only)
  */
 .filepicker-filelist .filepicker-container,
-.filemanager.fm-noitems .fm-empty-container {display:block;position:absolute;top:10px;bottom:10px;left:10px;right:10px;border: 2px dashed #BBB;padding-top:85px;text-align:center;z-index: 3000;}
+.filemanager.fm-noitems .fm-empty-container {display:block;position:absolute;top:10px;bottom:10px;left:10px;right:10px;border: 2px dashed #BBBBBB;padding-top:85px;text-align:center;z-index: 3000;}
 .filepicker-filelist .dndupload-target,
-.filemanager-container .dndupload-target {background:#FFF;position:absolute;top:10px;bottom:10px;left:10px;right:10px;border: 2px dashed #fb7979;padding-top:85px;text-align:center;z-index:3000;-webkit-box-shadow:  0px 0px 0px 10px #FFF;-moz-box-shadow: 0px 0px 0px 10px #FFF;box-shadow:  0px 0px 0px 10px #FFF;}
+.filemanager-container .dndupload-target {background:#FFFFFF;position:absolute;top:10px;bottom:10px;left:10px;right:10px;border: 2px dashed #fb7979;padding-top:85px;text-align:center;z-index:3000;-webkit-box-shadow:  0px 0px 0px 10px #FFFFFF;-moz-box-shadow: 0px 0px 0px 10px #FFFFFF;box-shadow:  0px 0px 0px 10px #FFFFFF;}
 .filepicker-filelist.dndupload-over .dndupload-target,
-.filemanager-container.dndupload-over .dndupload-target {background:#FFF;position:absolute;top:10px;bottom:10px;left:10px;right:10px;border: 2px dashed #6c8cd3;padding-top:85px;text-align:center;z-index: 3000;}
+.filemanager-container.dndupload-over .dndupload-target {background:#FFFFFF;position:absolute;top:10px;bottom:10px;left:10px;right:10px;border: 2px dashed #6c8cd3;padding-top:85px;text-align:center;z-index: 3000;}
 .dndupload-message {display:none;}
 .dndsupported .dndupload-message {display:inline;}
 .dndupload-target {display:none;}
@@ -310,15 +306,14 @@ a.ygtvspacer:hover {color: transparent;text-decoration: none;}
 .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 {background: #FFF;border: 1px solid #BBB;padding: 8px 7px;margin: 0px;max-width: 265px;max-height: 75px;overflow:auto;}
+.filemanager.fp-select .fp-reflist .fp-value {background: #FFFFFF;border: 1px solid #BBBBBB;padding: 8px 7px;margin: 0px;max-width: 265px;max-height: 75px;overflow:auto;}
 .filemanager.fp-select .fp-reflist .fp-value li {padding-bottom: 7px;}
 
 /*
  * Create folder dialogue (File Manager only)
  */
-.filemanager.fp-mkdir-dlg {text-align: center;z-index: 999999}
-.filemanager .fp-mkdir-dlg p {text-align: left;margin: 40px 20px 0px;}
-.filemanager .fp-mkdir-dlg input {margin: 0px 20px 20px;}
+.filemanager.fp-mkdir-dlg {text-align: center;}
+.filemanager.fp-mkdir-dlg .fp-mkdir-dlg-text {text-align: left;margin: 40px 20px 20px;}
 
 /*
  * Confirm dialogue for delete (File Manager only)
index fd97b59..813b25b 100644 (file)
@@ -30,7 +30,7 @@
 defined('MOODLE_INTERNAL') || die();
 
 
-$version  = 2012060100.00;              // YYYYMMDD      = weekly release date of this DEV branch
+$version  = 2012060400.00;              // YYYYMMDD      = weekly release date of this DEV branch
                                         //         RR    = release increments - 00 in DEV branches
                                         //           .XX = incremental changes