Merge branch 'MDL-33788b-23' of git://github.com/srynot4sale/moodle into MOODLE_23_STABLE
authorSam Hemelryk <sam@moodle.com>
Sun, 15 Jul 2012 21:18:46 +0000 (09:18 +1200)
committerSam Hemelryk <sam@moodle.com>
Sun, 15 Jul 2012 21:18:46 +0000 (09:18 +1200)
76 files changed:
admin/mnet/peers.php
admin/renderer.php
admin/settings/frontpage.php
admin/settings/mnet.php
admin/tool/assignmentupgrade/batchupgrade.php
admin/tool/assignmentupgrade/index.php
admin/tool/assignmentupgrade/listnotupgraded.php
admin/tool/assignmentupgrade/upgradesingle.php
admin/tool/assignmentupgrade/upgradesingleconfirm.php
admin/tool/phpunit/cli/util.php
admin/tool/profiling/index.php
admin/tool/replace/index.php
admin/tool/replace/lang/en/tool_replace.php
auth/email/lang/en/auth_email.php
backup/util/helper/backup_cron_helper.class.php
blog/edit_form.php
calendar/delete.php
course/edit_form.php
enrol/cohort/yui/quickenrolment/assets/skins/sam/quickenrolment.css
enrol/meta/locallib.php
grade/edit/tree/item.php
grade/edit/tree/item_form.php
install/lang/ca/error.php
install/lang/ca/install.php
install/lang/es_mx/moodle.php [new file with mode: 0644]
install/lang/ga/langconfig.php
install/lang/id/admin.php [new file with mode: 0644]
install/lang/id/moodle.php
install/lang/ja/langconfig.php
install/lang/pt/admin.php
install/lang/pt/error.php
install/lang/pt/install.php
install/lang/pt/langconfig.php
install/lang/pt/moodle.php
install/lang/sv_fi/moodle.php [new file with mode: 0644]
lang/en/admin.php
lang/en/grades.php
lib/db/install.php
lib/db/install.xml
lib/db/upgrade.php
lib/dml/moodle_database.php
lib/dml/tests/dml_test.php
lib/editor/tinymce/lib.php
lib/filelib.php
lib/form/filemanager.js
lib/form/yui/dateselector/dateselector.js
lib/grade/grade_item.php
lib/moodlelib.php
lib/outputrenderers.php
lib/outputrequirementslib.php
lib/phpunit/bootstraplib.php
lib/phpunit/classes/hint_resultprinter.php
lib/rsslib.php
lib/tests/backup_test.php [new file with mode: 0644]
lib/tests/outputrequirementslib_test.php [new file with mode: 0644]
lib/yui/blocks/blocks.js
mod/choice/lang/en/choice.php
mod/choice/renderer.php
mod/choice/styles.css
mod/lesson/renderer.php
mod/lti/typessettings.php
mod/quiz/lib.php
mod/resource/lib.php
mod/scorm/report/interactions/report.php
question/format/gift/format.php
question/format/gift/tests/giftformat_test.php
repository/filepicker.js
repository/filepicker.php
repository/flickr/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 4d402ed..e7c1daf 100644 (file)
@@ -30,7 +30,7 @@
 require_once(dirname(dirname(dirname(__FILE__))) . '/config.php');
 require_once($CFG->libdir.'/adminlib.php');
 require_once($CFG->dirroot.'/mnet/lib.php');
-require_once($CFG->dirroot.'/admin/mnet/peer_forms.php');
+require_once($CFG->dirroot.'/'.$CFG->admin.'/mnet/peer_forms.php');
 
 require_login();
 
index c064ca6..3a3c2bd 100644 (file)
@@ -68,7 +68,7 @@ class core_admin_renderer extends plugin_renderer_base {
         $output .= $this->header();
         $output .= $this->heading(get_string('upgradestalefiles', 'admin'));
         $output .= $this->box_start('generalbox', 'notice');
-        $output .= get_string('upgradestalefilesinfo', 'admin', get_docs_url('Upgrading'));
+        $output .= format_text(get_string('upgradestalefilesinfo', 'admin', get_docs_url('Upgrading')), FORMAT_MARKDOWN);
         $output .= html_writer::empty_tag('br');
         $output .= html_writer::tag('div', $this->single_button($this->page->url, get_string('reload'), 'get'), array('class' => 'buttons'));
         $output .= $this->box_end();
index edd701d..c380e43 100644 (file)
@@ -77,7 +77,7 @@ if (!during_initial_install()) { //do not use during installation
 
         $ADMIN->add('frontpage', new admin_externalpage('frontpagebackup', new lang_string('frontpagebackup', 'admin'), $CFG->wwwroot.'/backup/backup.php?id='.SITEID, 'moodle/backup:backupcourse', false, $frontpagecontext));
 
-        $ADMIN->add('frontpage', new admin_externalpage('frontpagerestore', new lang_string('frontpagerestore', 'admin'), $CFG->wwwroot.'/files/index.php?id='.SITEID.'&amp;wdir=/backupdata', 'moodle/restore:restorecourse', false, $frontpagecontext));
+        $ADMIN->add('frontpage', new admin_externalpage('frontpagerestore', new lang_string('frontpagerestore', 'admin'), $CFG->wwwroot.'/backup/restorefile.php?contextid='.$frontpagecontext->id, 'moodle/restore:restorecourse', false, $frontpagecontext));
 
         $questioncapabilities = array(
                 'moodle/question:add',
index ed77e03..9bb5b15 100644 (file)
@@ -29,7 +29,7 @@ if (isset($CFG->mnet_dispatcher_mode) and $CFG->mnet_dispatcher_mode !== 'off')
             new admin_externalpage(
                 'mnetpeer' . $host->id,
                 $host->name,
-                $CFG->wwwroot . '/admin/mnet/peers.php?step=update&hostid=' . $host->id,
+                $CFG->wwwroot . '/'.$CFG->admin.'/mnet/peers.php?step=update&hostid=' . $host->id,
                 'moodle/site:config'
             )
         );
index 31bca24..a654f6e 100644 (file)
@@ -26,9 +26,9 @@ define('NO_OUTPUT_BUFFERING', true);
 
 require_once(dirname(__FILE__) . '/../../../config.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/locallib.php');
-require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/upgradableassignmentstable.php');
-require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/upgradableassignmentsbatchform.php');
+require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/locallib.php');
+require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/upgradableassignmentstable.php');
+require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/upgradableassignmentsbatchform.php');
 
 require_sesskey();
 
index f4cd179..71ed56f 100644 (file)
@@ -35,7 +35,7 @@
 
 require_once(dirname(__FILE__) . '/../../../config.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/locallib.php');
+require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/locallib.php');
 
 // admin_externalpage_setup calls require_login and checks moodle/site:config
 admin_externalpage_setup('assignmentupgrade');
index b03883a..9d68c26 100644 (file)
 
 require_once(dirname(__FILE__) . '/../../../config.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/locallib.php');
-require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/upgradableassignmentstable.php');
-require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/upgradableassignmentsbatchform.php');
-require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/paginationform.php');
+require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/locallib.php');
+require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/upgradableassignmentstable.php');
+require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/upgradableassignmentsbatchform.php');
+require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/paginationform.php');
 
 // admin_externalpage_setup calls require_login and checks moodle/site:config
 admin_externalpage_setup('assignmentupgrade', '', array(), tool_assignmentupgrade_url('listnotupgraded'));
index 5125bbb..67f24b0 100644 (file)
@@ -24,7 +24,7 @@
 
 require_once(dirname(__FILE__) . '/../../../config.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/locallib.php');
+require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/locallib.php');
 
 require_sesskey();
 
index b7ec24c..143ebf1 100644 (file)
@@ -24,7 +24,7 @@
 
 require_once(dirname(__FILE__) . '/../../../config.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/locallib.php');
+require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/locallib.php');
 
 require_sesskey();
 
index 1a8cea7..2986d64 100644 (file)
@@ -123,7 +123,7 @@ Options:
 -h, --help     Print out this help
 
 Example:
-\$/usr/bin/php lib/phpunit/tool.php --install
+\$ php ".phpunit_bootstrap_cli_argument_path('/admin/tool/phpunit/cli/util.php')." --install
 ";
     echo $help;
     exit(0);
index 197a694..eebfcd8 100644 (file)
@@ -142,7 +142,7 @@ if (isset($script)) {
 
     // The flexitable that will root listings
     $table = new xhprof_table_sql('profiling-list-table');
-    $baseurl = $CFG->wwwroot . '/admin/tool/profiling/index.php';
+    $baseurl = $CFG->wwwroot . '/'.$CFG->admin.'/tool/profiling/index.php';
 
     // Check if we are listing all or some URL ones
     $sqlconditions = '';
index 6f3c89f..11e1068 100644 (file)
@@ -38,25 +38,29 @@ $sure    = optional_param('sure', 0, PARAM_BOOL);
 ###################################################################
 echo $OUTPUT->header();
 
-echo $OUTPUT->heading('Search and replace text throughout the whole database');
+echo $OUTPUT->heading(get_string('pageheader', 'tool_replace'));
 
 if ($DB->get_dbfamily() !== 'mysql' and $DB->get_dbfamily() !== 'postgres') {
     //TODO: add $DB->text_replace() to DML drivers
-    echo $OUTPUT->notification('Sorry, this feature is implemented only for MySQL and PostgreSQL databases.');
+    echo $OUTPUT->notification(get_string('notimplemented', 'tool_replace'));
     echo $OUTPUT->footer();
     die;
 }
 
 if (!data_submitted() or !$search or !$replace or !confirm_sesskey() or !$sure) {   /// Print a form
-    echo $OUTPUT->notification('This script is not supported, always make complete backup before proceeding!<br />This operation can not be reverted!');
+    echo $OUTPUT->notification(get_string('notsupported', 'tool_replace'));
 
     echo $OUTPUT->box_start();
     echo '<div class="mdl-align">';
     echo '<form action="index.php" method="post"><div>';
     echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
-    echo '<div><label for="search">Search whole database for: </label><input id="search" type="text" name="search" size="40" /> (usually previous server URL)</div>';
-    echo '<div><label for="replace">Replace with this string: </label><input type="text" id="replace" name="replace" size="40" /> (usually new server URL)</div>';
-    echo '<div><label for="sure">I understand the risks of this operation: </label><input type="checkbox" id="sure" name="sure" value="1" /></div>';
+    echo '<div><label for="search">'.get_string('searchwholedb', 'tool_replace').
+            ' </label><input id="search" type="text" name="search" size="40" /> ('.
+            get_string('searchwholedbhelp', 'tool_replace').')</div>';
+    echo '<div><label for="replace">'.get_string('replacewith', 'tool_replace').
+            ' </label><input type="text" id="replace" name="replace" size="40" /> ('.
+            get_string('replacewithhelp', 'tool_replace').')</div>';
+    echo '<div><label for="sure">'.get_string('disclaimer', 'tool_replace').' </label><input type="checkbox" id="sure" name="sure" value="1" /></div>';
     echo '<div class="buttons"><input type="submit" class="singlebutton" value="Yes, do it now" /></div>';
     echo '</div></form>';
     echo '</div>';
@@ -70,9 +74,9 @@ db_replace($search, $replace);
 echo $OUTPUT->box_end();
 
 /// Rebuild course cache which might be incorrect now
-echo $OUTPUT->notification('Rebuilding course cache...', 'notifysuccess');
+echo $OUTPUT->notification(get_string('notifyrebuilding', 'tool_replace'), 'notifysuccess');
 rebuild_course_cache();
-echo $OUTPUT->notification('...finished', 'notifysuccess');
+echo $OUTPUT->notification(get_string('notifyfinished', 'tool_replace'), 'notifysuccess');
 
 echo $OUTPUT->continue_button(new moodle_url('/admin/index.php'));
 
index f967fad..2193805 100644 (file)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+$string['disclaimer'] = 'I understand the risks of this operation:';
+$string['pageheader'] = 'Search and replace text throughout the whole database';
+$string['notifyfinished'] = '...finished';
+$string['notifyrebuilding'] = 'Rebuilding course cache...';
+$string['notimplemented'] = 'Sorry, this feature is implemented only for MySQL and PostgreSQL databases.';
+$string['notsupported'] ='This script is not supported, always make complete backup before proceeding!<br />This operation can not be reverted!';
 $string['pluginname'] = 'DB search and replace';
+$string['replacewith'] = 'Replace with this string:';
+$string['replacewithhelp'] = 'usually new server URL';
+$string['searchwholedb'] = 'Search whole database for:';
+$string['searchwholedbhelp'] = 'usually previous server URL';
\ No newline at end of file
index edd1a9e..e1dbb71 100644 (file)
@@ -23,7 +23,7 @@
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-$string['auth_emaildescription'] = 'Email confirmation is the default authentication method.  When the user signs up, choosing their own new username and password, a confirmation email is sent to the user\'s email address.  This email contains a secure link to a page where the user can confirm their account. Future logins just check the username and password against the stored values in the Moodle database.';
+$string['auth_emaildescription'] = '<p>Email-based self-registration enables a user to create their own account via a \'Create new account\' button on the login page. The user then receives an email containing a secure link to a page where they can confirm their account. Future logins just check the username and password against the stored values in the Moodle database.</p><p>Note: In addition to enabling the plugin, email-based self-registration must also be selected from the self registration drop-down menu on the \'Manage authentication\' page.</p>';
 $string['auth_emailnoemail'] = 'Tried to send you an email but failed!';
 $string['auth_emailrecaptcha'] = 'Adds a visual/audio confirmation form element to the signup page for email self-registering users. This protects your site against spammers and contributes to a worthwhile cause. See http://www.google.com/recaptcha/learnmore for more details. <br /><em>PHP cURL extension is required.</em>';
 $string['auth_emailrecaptcha_key'] = 'Enable reCAPTCHA element';
index 65e56ee..00db13d 100644 (file)
@@ -281,23 +281,25 @@ abstract class backup_cron_automated_helper {
         $midnight = usergetmidnight($now, $timezone);
         $date = usergetdate($now, $timezone);
 
-        //Get number of days (from today) to execute backups
-        $automateddays = substr($config->backup_auto_weekdays,$date['wday']) . $config->backup_auto_weekdays;
-        $daysfromtoday = strpos($automateddays, "1");
+        // Get number of days (from today) to execute backups
+        $automateddays = substr($config->backup_auto_weekdays, $date['wday']) . $config->backup_auto_weekdays;
+        $daysfromtoday = strpos($automateddays, "1", 1);
+
+        // If we can't find the next day, we set it to tomorrow
         if (empty($daysfromtoday)) {
             $daysfromtoday = 1;
         }
 
-        //If some day has been found
+        // If some day has been found
         if ($daysfromtoday !== false) {
-            //Calculate distance
-            $dist = ($daysfromtoday * 86400) +                //Days distance
-                    ($config->backup_auto_hour * 3600) +      //Hours distance
-                    ($config->backup_auto_minute * 60);       //Minutes distance
+            // Calculate distance
+            $dist = ($daysfromtoday * 86400) +                // Days distance
+                    ($config->backup_auto_hour * 3600) +      // Hours distance
+                    ($config->backup_auto_minute * 60);       // Minutes distance
             $result = $midnight + $dist;
         }
 
-        //If that time is past, call the function recursively to obtain the next valid day
+        // If that time is past, call the function recursively to obtain the next valid day
         if ($result > 0 && $result < time()) {
             $result = self::calculate_next_automated_backup($timezone, $result);
         }
index 2eb767a..292d55c 100644 (file)
@@ -38,11 +38,12 @@ class blog_edit_form extends moodleform {
 
         $mform->addElement('header', 'general', get_string('general', 'form'));
 
-        $mform->addElement('text', 'subject', get_string('entrytitle', 'blog'), 'size="60"');
+        $mform->addElement('text', 'subject', get_string('entrytitle', 'blog'), array('size' => 60, 'maxlength' => 128));
         $mform->addElement('editor', 'summary_editor', get_string('entrybody', 'blog'), null, $summaryoptions);
 
         $mform->setType('subject', PARAM_TEXT);
         $mform->addRule('subject', get_string('emptytitle', 'blog'), 'required', null, 'client');
+        $mform->addRule('subject', get_string('maximumchars', '', 128), 'maxlength', 128, 'client');
 
         $mform->setType('summary_editor', PARAM_RAW);
         $mform->addRule('summary_editor', get_string('emptybody', 'blog'), 'required', null, 'client');
index e79e945..9ca5374 100644 (file)
@@ -124,7 +124,7 @@ echo $OUTPUT->box_end();
 $event->time = calendar_format_event_time($event, time(), null, false);
 $renderer = $PAGE->get_renderer('core_calendar');
 echo $renderer->start_layout();
-echo $renderer->event($event);
+echo $renderer->event($event, false);
 echo $renderer->complete_layout();
 
 echo $OUTPUT->box_end();
index 19d1f98..dd3d4bd 100644 (file)
@@ -229,7 +229,7 @@ class course_edit_form extends moodleform {
             if (!empty($course->id)) {
                 $mform->setConstant('visible', $course->visible);
             } else {
-                $mform->setConstant('visible', $category->visible);
+                $mform->setConstant('visible', $courseconfig->visible);
             }
         }
 
index 540ed78..9509c01 100644 (file)
@@ -33,4 +33,7 @@
 .qce-panel .qce-search input {width:70%;}
 
 .qce-panel .qce-cohort.headings {font-weight:bold;border-width:0;}
-.qce-panel .qce-cohort.headings .qce-cohort-button {display:none;}
\ No newline at end of file
+.qe-panel .qce-cohort.headings .qce-cohort-button {display:none;}
+
+.ie7 .qce-panel .qce-cohort div,
+.ie7 .qce-panel .canenrolusers .qce-cohort .qce-cohort-name {float:left;}
index 454c974..fa3125c 100644 (file)
@@ -477,11 +477,10 @@ function enrol_meta_sync($courseid = NULL, $verbose = false) {
     $sql = "SELECT ue.*
               FROM {user_enrolments} ue
               JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' $onecourse)
-         LEFT JOIN (SELECT xpue.userid, xpe.courseid
-                      FROM {user_enrolments} xpue
+         LEFT JOIN ({user_enrolments} xpue
                       JOIN {enrol} xpe ON (xpe.id = xpue.enrolid AND xpe.enrol <> 'meta' AND xpe.enrol $enabled)
-                   ) pue ON (pue.courseid = e.customint1 AND pue.userid = ue.userid)
-             WHERE pue.userid IS NULL";
+                   ) ON (xpe.courseid = e.customint1 AND xpue.userid = ue.userid)
+             WHERE xpue.userid IS NULL";
     $rs = $DB->get_recordset_sql($sql, $params);
     foreach($rs as $ue) {
         if (!isset($instances[$ue->enrolid])) {
index 5b2a7c0..0e80c6b 100644 (file)
@@ -97,6 +97,7 @@ if ($parent_category->aggregation == GRADE_AGGREGATE_SUM or $parent_category->ag
 } else {
     $item->aggregationcoef = format_float($item->aggregationcoef, 4);
 }
+$item->cancontrolvisibility = $grade_item->can_control_visibility();
 
 $mform = new edit_item_form(null, array('current'=>$item, 'gpr'=>$gpr));
 
index 6dd9683..862a6fd 100644 (file)
@@ -143,11 +143,18 @@ class edit_item_form extends moodleform {
         }
 
         /// hiding
-        // advcheckbox is not compatible with disabledIf!
-        $mform->addElement('checkbox', 'hidden', get_string('hidden', 'grades'));
+        if ($item->cancontrolvisibility) {
+            // advcheckbox is not compatible with disabledIf!
+            $mform->addElement('checkbox', 'hidden', get_string('hidden', 'grades'));
+            $mform->addElement('date_time_selector', 'hiddenuntil', get_string('hiddenuntil', 'grades'), array('optional'=>true));
+            $mform->disabledIf('hidden', 'hiddenuntil[off]', 'notchecked');
+        } else {
+            $mform->addElement('static', 'hidden', get_string('hidden', 'grades'),
+                    get_string('componentcontrolsvisibility', 'grades'));
+            // Unset hidden to avoid data override.
+            unset($item->hidden);
+        }
         $mform->addHelpButton('hidden', 'hidden', 'grades');
-        $mform->addElement('date_time_selector', 'hiddenuntil', get_string('hiddenuntil', 'grades'), array('optional'=>true));
-        $mform->disabledIf('hidden', 'hiddenuntil[off]', 'notchecked');
 
         /// locking
         $mform->addElement('advcheckbox', 'locked', get_string('locked', 'grades'));
index e8c7b55..e1de235 100644 (file)
@@ -34,12 +34,12 @@ $string['cannotcreatelangdir'] = 'No s\'ha pogut crear el directori d\'idiomes.'
 $string['cannotcreatetempdir'] = 'No s\'ha pogut crear el directori temporal';
 $string['cannotdownloadcomponents'] = 'No s\'han pogut baixar components';
 $string['cannotdownloadzipfile'] = 'No s\'ha pogut baixar el fitxer zip';
-$string['cannotfindcomponent'] = 'No s\'ha pogut trobar un component';
+$string['cannotfindcomponent'] = 'No s\'ha pogut trobar el component';
 $string['cannotsavemd5file'] = 'No s\'ha pogut desar el fitxer md5';
 $string['cannotsavezipfile'] = 'No s\'ha pogut desar el fitxer zip';
 $string['cannotunzipfile'] = 'No s\'ha pogut descomprimir el fitxer';
 $string['componentisuptodate'] = 'El component està al dia';
-$string['downloadedfilecheckfailed'] = 'Ha fallat la comprovació del fitxer baixat.';
+$string['downloadedfilecheckfailed'] = 'Ha fallat la comprovació del fitxer baixat';
 $string['invalidmd5'] = 'L\'md5 no és vàlid. Torneu-ho a provar';
 $string['missingrequiredfield'] = 'Falta algun camp necessari';
 $string['remotedownloaderror'] = 'No s\'ha pogut baixar el component al vostre servidor. Verifiqueu els paràmetres de servidor intermediari. Es recomana l\'extensió cURL.<br /><br />Haureu de baixar manualment el fitxer <a href="{$a->url}">{$a->url}</a>, copiar-lo a la ubicació "{$a->dest}" del vostre servidor i descomprimir-lo allí.';
index 2b15652..940d880 100644 (file)
@@ -33,16 +33,23 @@ defined('MOODLE_INTERNAL') || die();
 $string['admindirname'] = 'Directori d\'administració';
 $string['availablelangs'] = 'Llista d\'idiomes disponibles';
 $string['chooselanguagehead'] = 'Trieu un idioma';
-$string['chooselanguagesub'] = 'Trieu un idioma NOMÉS per a la instal·lació. En una pantalla posterior podreu triar idiomes per al lloc i per als usuaris.';
+$string['chooselanguagesub'] = 'Trieu un idioma per a la instal·lació. S\'utilitzarà també com a idioma per defecte del lloc, tot i que després podeu canviar-lo.';
+$string['clialreadyconfigured'] = 'El fitxer config.php ja existeix, feu servir dmin/cli/install_database.php si voleu instal·lar aquest lloc web.';
+$string['clialreadyinstalled'] = 'El fitxer config.php ja existeix, feu servir admin/cli/upgrade.php si voleu actualitzar aquest lloc web.';
+$string['cliinstallheader'] = 'Programa d\'instal·lació de línia d\'ordres de Moodle {$a}';
 $string['databasehost'] = 'Servidor de base de dades:';
 $string['databasename'] = 'Nom de la base de dades:';
+$string['databasetypehead'] = 'Trieu el controlador de la base de dades';
 $string['dataroot'] = 'Directori de dades';
+$string['datarootpermission'] = 'Permisos dels directoris de dades';
 $string['dbprefix'] = 'Prefix de taules';
 $string['dirroot'] = 'Directori de Moodle';
 $string['environmenthead'] = 'S\'està comprovant el vostre entorn';
-$string['errorsinenvironment'] = 'Hi ha errors en l\'entorn.';
+$string['environmentsub2'] = 'Cada versió de Moodle té uns requeriments mínims de versió de PHP i un nombre d\'extensions de PHP necessàries.
+Abans de cada instal·lació o actualització es realitza una comprovació exhaustiva de l\'entorn. Contacteu amb l\'administrador si no sabeu com instal·lar una nova versió de PHP o com habilitar les extensions.';
+$string['errorsinenvironment'] = 'La comprovació de l\'entorn ha fallat.';
 $string['installation'] = 'Instal·lació';
-$string['langdownloaderror'] = 'Dissortadament l\'idioma "{$a}" no està instal·lat. La instal·lació prosseguirà en anglès.';
+$string['langdownloaderror'] = 'Dissortadament l\'idioma "{$a}" no es pot baixar. La instal·lació prosseguirà en anglès.';
 $string['memorylimithelp'] = '<p>El límit de memòria del PHP del vostre servidor actualment està definit en {$a}.</p>
 
 <p>Això pot causar que Moodle tingui problemes de memòria més endavant, especialment si teniu molts mòduls habilitats i/o molts usuaris.</p>
@@ -55,13 +62,23 @@ $string['memorylimithelp'] = '<p>El límit de memòria del PHP del vostre servid
 <p><blockquote>php_value memory_limit 40M</blockquote></p>
 <p>Tanmateix, en alguns servidors això farà que no funcioni <b>cap</b> pàgina PHP (es visualitzaran errors) en el qual cas hauríeu de suprimir el fitxer .htaccess.</p></li>
 </ol>';
+$string['paths'] = 'Camins';
+$string['pathserrcreatedataroot'] = 'L\'instal·lador no pot crear el directori de dades ({$a->dataroot}).';
+$string['pathshead'] = 'Confirmeu els camins';
+$string['pathsrodataroot'] = 'No es pot escriure en el directori dataroot.';
+$string['pathsroparentdataroot'] = 'No es pot escriure en el directori pare ({$a->parent}). L\'instal·lador no pot crear el directori ({$a->dataroot}).';
+$string['pathssubadmindir'] = 'Alguns serveis d\'allotjament web (pocs) utilitzen un URL especial /admin p. ex. per a accedir a un tauler de control o quelcom semblant. Malauradament això entra en conflicte amb la ubicació estàndard de les pàgines d\'administració de Moodle. Podeu arreglar aquest problema canviant el nom del directori d\'administració de Moodle en la vostra instal·lació i posant el nou nom aquí. Per exemple <em>moodleadmin</em>. Això modificarà els enllaços d\'administració de Moodle.';
 $string['pathssubdataroot'] = 'Necessiteu un espai on Moodle pugui desar els fitxers penjats. Aquest directori hauria de tenir permisos de lectura I ESCRIPTURA per a l\'usuari del servidor web (normalment \'nobody\' o \'apache\'), però no cal que sigui accessible directament via web. L\'instal·lador provarà de crear-lo si no existeix.';
+$string['pathssubdirroot'] = 'Camí complet del directori d\'instal·lació de Moodle.';
+$string['pathsunsecuredataroot'] = 'La ubicació del dataroot no és segura.';
+$string['pathswrongadmindir'] = 'No existeix el directori d\'administració';
+$string['phpextension'] = 'Extensió PHP {$a}';
 $string['phpversion'] = 'Versió PHP';
-$string['phpversionhelp'] = '<p>Moodle necessita la versió de PHP 4.1.0 o posterior.</p>
+$string['phpversionhelp'] = '<p>Moodle necessita una versió de PHP 4.3.0 o 5.1.0 (les versions 5.0.x tenien uns quants problemes coneguts).</p>
 <p>A hores d\'ara esteu utilitzant la versió {$a}.</p>
-<p>Us caldrà actualitzar el PHP o traslladar Moodle a un ordinador amb una versió de PHP més recent.</p>';
+<p>Us cal actualitzar el PHP o traslladar Moodle a un ordinador amb una versió de PHP més recent.<br />(Si esteu utilitzant la versió 5.0.x, alternativament també podríeu tornar enrere a la 4.4.x)</p>';
 $string['welcomep10'] = '{$a->installername} ({$a->installerversion})';
-$string['welcomep20'] = 'Esteu veient aquesta pàgina perquè heu instal·lat amb èxit i heu executat el paquet <strong>{$a->packname} {$a->packversion}</strong>. Felicitacions!';
+$string['welcomep20'] = 'Esteu veient aquesta pàgina perquè heu instal·lat amb èxit i heu executat el paquet <strong>{$a->packname} {$a->packversion}</strong>. Felicitacions.';
 $string['welcomep30'] = 'Aquesta versió de <strong>{$a->installername}</strong> inclou les aplicacions necessàries per crear un entorn en el qual funcioni <strong>Moodle</strong>:';
 $string['welcomep40'] = 'El paquet inclou també <strong>Moodle {$a->moodlerelease} ({$a->moodleversion})</strong>.';
 $string['welcomep50'] = 'L\'ús de totes les aplicacions d\'aquest paquet és governat per les seves llicències respectives. El paquet <strong>{$a->installername}</strong> complet és
diff --git a/install/lang/es_mx/moodle.php b/install/lang/es_mx/moodle.php
new file mode 100644 (file)
index 0000000..2b6d46e
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Automatically generated strings for Moodle installer
+ *
+ * Do not edit this file manually! It contains just a subset of strings
+ * needed during the very first steps of installation. This file was
+ * generated automatically by export-installer.php (which is part of AMOS
+ * {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
+ * list of strings defined in /install/stringnames.txt.
+ *
+ * @package   installer
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$string['language'] = 'Idioma';
+$string['next'] = 'Siguiente';
+$string['previous'] = 'Anterior';
+$string['reload'] = 'Recargar';
index 9cea86c..cd9ab38 100644 (file)
@@ -32,4 +32,4 @@ defined('MOODLE_INTERNAL') || die();
 
 $string['parentlanguage'] = '';
 $string['thisdirection'] = 'ltr';
-$string['thislanguage'] = 'Gaeilge';
+$string['thislanguage'] = 'Béarla';
diff --git a/install/lang/id/admin.php b/install/lang/id/admin.php
new file mode 100644 (file)
index 0000000..63281c9
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Automatically generated strings for Moodle installer
+ *
+ * Do not edit this file manually! It contains just a subset of strings
+ * needed during the very first steps of installation. This file was
+ * generated automatically by export-installer.php (which is part of AMOS
+ * {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
+ * list of strings defined in /install/stringnames.txt.
+ *
+ * @package   installer
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$string['clianswerno'] = 'T';
+$string['cliansweryes'] = 'Y';
+$string['cliincorrectvalueerror'] = 'Error, nilai yang salah "{$a->value}" untuk opsi "{$a->option}"';
+$string['cliincorrectvalueretry'] = 'Nilai input salah, silahkan coba lagi';
+$string['clitypevalue'] = 'tipe nilai';
+$string['clitypevaluedefault'] = 'tipe nilai, tekan enter untuk menggunakan nilai default ({$a})';
+$string['cliunknowoption'] = 'Opsi tidak dikenali :
+ {$a}
+Silahkan gunakan opsi --help';
+$string['cliyesnoprompt'] = 'ketik y (Ya) atau t (Tidak)';
index 81eb64b..e7db667 100644 (file)
@@ -33,3 +33,4 @@ defined('MOODLE_INTERNAL') || die();
 $string['language'] = 'Bahasa';
 $string['next'] = 'Selanjutnya';
 $string['previous'] = 'Sebelumnya';
+$string['reload'] = 'Muat ulang';
index a0245d5..eb70f69 100644 (file)
@@ -30,6 +30,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$string['parentlanguage'] = 'en';
+$string['parentlanguage'] = '';
 $string['thisdirection'] = 'ltr';
 $string['thislanguage'] = '日本語';
index cd1814f..09bd68f 100644 (file)
@@ -32,13 +32,11 @@ defined('MOODLE_INTERNAL') || die();
 
 $string['clianswerno'] = 'n';
 $string['cliansweryes'] = 's';
-$string['cliincorrectvalueerror'] = 'Erro. Valor "{$a->value}" incorreto para "{$a->option}"';
+$string['cliincorrectvalueerror'] = 'Erro: o valor "{$a->value}" não é permitido para a opção "{$a->option}"';
 $string['cliincorrectvalueretry'] = 'Valor incorreto, por favor tente novamente';
 $string['clitypevalue'] = 'valor do tipo';
-$string['clitypevaluedefault'] = 'Escreva o valor. Ou Enter para usar o valor  por omissão ({$a}).';
-$string['cliunknowoption'] = 'Opções desconhecidas:
-{$a}
-Por favor use a opção --help';
+$string['clitypevaluedefault'] = 'valor do tipo, pressione a tecla Enter para usar o valor predefinido ({$a})';
+$string['cliunknowoption'] = 'Opções desconhecidas: {$a} Por favor use a opção --help';
 $string['cliyesnoprompt'] = 'digite s (para sim) ou n (para não)';
-$string['environmentrequireinstall'] = 'é necessário estar instalada/ativa';
-$string['environmentrequireversion'] = 'Ã\89 requerida a versão {$a->needed} e está a correr a versão {$a->current}';
+$string['environmentrequireinstall'] = 'deve estar instalada e ativa';
+$string['environmentrequireversion'] = 'é requerida a versão {$a->needed} e está a correr a versão {$a->current}';
index 1107cdc..05bdef9 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
-$string['cannotcreatelangdir'] = 'Não é possível criar o diretório para pacotes linguísticos';
-$string['cannotcreatetempdir'] = 'Não é possível criar o diretório temporário';
-$string['cannotdownloadcomponents'] = 'Não é possível descarregar  componentes';
-$string['cannotdownloadzipfile'] = 'Não é possível descarregar o ficheiro ZIP';
-$string['cannotfindcomponent'] = 'O componente não foi encontrado';
-$string['cannotsavemd5file'] = 'Não é possível gravar ficheiro md5';
-$string['cannotsavezipfile'] = 'Não  é possível gravar ficheiro ZIP';
-$string['cannotunzipfile'] = 'Não é possível descompatar ficheiro ZIP';
-$string['componentisuptodate'] = 'O componente está atualizado';
-$string['downloadedfilecheckfailed'] = 'Falhou a verificação do ficheiro descarregado.';
+$string['cannotcreatelangdir'] = 'Não é possível criar a pasta de pacotes linguísticos';
+$string['cannotcreatetempdir'] = 'Não é possível criar a pasta de ficheiros temporários';
+$string['cannotdownloadcomponents'] = 'Não é possível descarregar os componentes.';
+$string['cannotdownloadzipfile'] = 'Não é possível descarregar o ficheiro ZIP.';
+$string['cannotfindcomponent'] = 'Não é possível encontrar o componente';
+$string['cannotsavemd5file'] = 'Não é possível gravar ficheiro md5';
+$string['cannotsavezipfile'] = 'Não é possível gravar o ficheiro ZIP';
+$string['cannotunzipfile'] = 'Não é possível descompactar o ficheiro ZIP';
+$string['componentisuptodate'] = 'O componente está atualizado.';
+$string['downloadedfilecheckfailed'] = 'A verificação do ficheiro descarregado falhou.';
 $string['invalidmd5'] = 'md5 inválido';
-$string['missingrequiredfield'] = 'Falta algum campo necessário';
-$string['remotedownloaderror'] = 'Não foi possível descarregar algum componente para o seu servidor; verifique as definições do proxy; recomenda-se fortemente o uso da extensão cURL do PHP.<br /><br />Deverá descarregar o ficheiro <a href="{$a->url}">{$a->url}</a> manualmente, copiá-lo para "{$a->dest}" no seu servidor, e descomprimi-lo nesse local.';
+$string['missingrequiredfield'] = 'Um dos campos obrigatórios está em falta';
+$string['remotedownloaderror'] = 'O download do componente para o servidor falhou. Verifique as configurações do proxy. A instalação da extensão cURL do PHP é muito recomendada.<br /><br />Terá que descarregar o ficheiro <a href="{$a->url}">{$a->url}</a> manualmente, copiá-lo para a pasta "{$a->dest}" no seu servidor e descompactá-lo.';
 $string['wrongdestpath'] = 'Caminho de destino errado.';
-$string['wrongsourcebase'] = 'URL errado para a fonte.';
+$string['wrongsourcebase'] = 'Base do URL de origem errada';
 $string['wrongzipfilename'] = 'Nome de ficheiro ZIP errado.';
index 4e35aff..c2d95ef 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
-$string['admindirname'] = 'Diretório de administração';
-$string['availablelangs'] = 'Lista de línguas disponíveis';
-$string['chooselanguagehead'] = 'Escolha uma língua';
-$string['chooselanguagesub'] = 'Escolha por favor a língua a usar na instalação. Esta língua será usada por omissão no site, mas pode ser alterada posteriormente.';
-$string['clialreadyconfigured'] = 'O ficheiro config.php já existe; por favor execute admin/cli/install_database.php se quiser instalar este sítio.';
-$string['clialreadyinstalled'] = 'O ficheiro config.php já existe. Por favor, use o script admin/cli/upgrade.php se quiser atualizar o seu sítio.';
-$string['cliinstallheader'] = 'Programa de instalação do Moodle {$a} por linha de comandos';
+$string['admindirname'] = 'Pasta de administração';
+$string['availablelangs'] = 'Idiomas disponíveis';
+$string['chooselanguagehead'] = 'Selecione um idioma';
+$string['chooselanguagesub'] = 'Selecione o idioma a utilizar durante a instalação. Poderá depois selecionar um outro idioma para o site e para os utilizadores.';
+$string['clialreadyconfigured'] = 'O ficheiro config.php já existe, use admin/cli/install_database.php se desejar instalar este site.';
+$string['clialreadyinstalled'] = 'O ficheiro <b>config.php</b> já se encontra no servidor, o que indica que já existe uma instalação prévia do Moodle. Se pretender realizar uma atualização do Moodle existente, deve usar o <i>script</i> <b>admin/cli/upgrade.php</b>';
+$string['cliinstallheader'] = 'Programa para instalação do Moodle <b>{$a}</b> através da linha de comandos';
 $string['databasehost'] = 'Servidor da base de dados';
 $string['databasename'] = 'Nome da base de dados';
-$string['databasetypehead'] = 'Escolha driver da base de dados';
-$string['dataroot'] = 'Diretório de dados';
-$string['datarootpermission'] = 'Permissão dos diretórios de dados';
+$string['databasetypehead'] = 'Escolha o <i>driver</i> da base de dados';
+$string['dataroot'] = 'Pasta de dados';
+$string['datarootpermission'] = 'Permissões da diretoria de dados';
 $string['dbprefix'] = 'Prefixo das tabelas';
-$string['dirroot'] = 'Diretório do Moodle';
-$string['environmenthead'] = 'A verificar o seu ambiente ...';
-$string['environmentsub2'] = 'Cada versão do Moodle tem requisitos mínimos relativamente à versão do PHP e às extensões PHP obrigatórias. É feita uma análise total ao ambiente existente antes de cada instalação ou atualização. Por favor contate o seu administrador de sistemas se não souber como instalar uma nova versão do PHP ou ativar as suas extensões.';
-$string['errorsinenvironment'] = 'Erros no ambiente!';
+$string['dirroot'] = 'Pasta do Moodle';
+$string['environmenthead'] = 'A verificar sistema...';
+$string['environmentsub2'] = 'Cada nova versão do Moodle tem pré-requisitos mínimos relativamente à versão do PHP e extensões necessárias para o seu correto funcionamento. Estes pré-requisitos são verificados sempre que o Moodle é instalado ou atualizado. Contacte o administrador do servidor caso seja necessário atualizar a versão do PHP ou instalar novas extensões.';
+$string['errorsinenvironment'] = 'A verificação do sistema falhou!';
 $string['installation'] = 'Instalação';
-$string['langdownloaderror'] = 'Não foi possível descarregar a língua "{$a}". O processo de instalação continuará em Inglês.';
-$string['memorylimithelp'] = '<p>Atualmente o seu servidor impõe ao PHP um limite de memória de {$a}.</p>
-
-<p>Isso poderá causar mais tarde problemas, especialmente se tiver um grande número de módulos ativos e/ou um número elevado de utilizadores.</p>
-
-<p>Recomendamos que configure o PHP com um limite maior, por exemplo, 40M.
-Existem várias formas de fazer essa alteração:</p>
-<ol>
-<li>Recompilar o PHP com <i>--enable-memory-limit</i>.
-Isso permitirá que o próprio Moodle modifique o limite de memória.</li>
-<li>Se tiver acesso ao ficheiro php.ini, poderá modificar o valor de <b>memory_limit</b> para algo como 40M. Se não tiver acesso, poderá pedir ao adiminstrador do seu sistema que o faça.</li>
-<li>Em alguns servidores PHP poderá criar um ficheiro .htaccess no diretório do Moodle, com a linha:
-<p><blockquote>php_value memory_limit 40M</blockquote></p>
-<p>No entanto, em alguns servidores, isso faz com que nenhuma página PHP funcione (verá erros quando tentar ver as páginas) e terá que apagar o ficheiro .htaccess.</p></li>
-</ol>';
+$string['langdownloaderror'] = 'Não foi possível instalar o idioma <b>{$a}</b> por falha no download. O processo de instalação continuará em Inglês.';
+$string['memorylimithelp'] = '<p>O limite de memória para o PHP definido atualmente no servidor é <b>{$a}</b>.</p><p>Um número elevado de módulos em utilização ou de utilizadores registados pode fazer com que o Moodle apresente problemas de falta de memória.</p><p>É recomendado que o PHP seja configurado com um limite de memória de pelo menos 40MB. Esta configuração pode ser definida de diversas formas:</p><ol><li>Compilação do PHP com o parâmetro <b>--enable-memory-limit</b>. Esta definição permitirá ao próprio Moodle definir o valor a utilizar.</li><li>Alteração do parâmetro <b>memory_limit</b> no ficheiro de configuração do PHP para um valor igual ou superior a 40MB.</li><li>Criação de um ficheiro <b>.htaccess</b> na raiz da pasta do Moodle com a linha <b>php_value memory_limit 40M</b><p>ATENÇÃO: Em alguns servidores esta configuração impedirá o funcionamento de <b>todas</b> as páginas PHP. Nestes casos, não poderá ser utilizado o ficheiro <b>.htaccess</b>.</p></li></ol>';
 $string['paths'] = 'Caminhos';
-$string['pathserrcreatedataroot'] = 'O programa de instalação não conseguiu criar o diretório de dados ({$a->dataroot})';
+$string['pathserrcreatedataroot'] = 'O programa de instalação não conseguiu criar a pasta de dados <b>{$a->dataroot}</b>.';
 $string['pathshead'] = 'Confirmar caminhos';
-$string['pathsrodataroot'] = 'A diretoria dataroot não tem permissões de escrita.';
-$string['pathsroparentdataroot'] = 'O diretório pai ({$a->parent}) não tem permissões de escrita. O programa de instalação não conseguiu criar o diretório de dados ({$a->dataroot})';
-$string['pathssubadmindir'] = 'Alguns (poucos) alojamentos web usam /admin como um URL especial para permitir o acesso ao control panel ou a outras funcionalidades.
-Infelizmente esta designação entra em conflito com a localização que o Moodle atribui às páginas de administração.
-A solução passa por renomear o diretório admin da sua instalação do Moodle e colocando o nome escolhido aqui. Por exemplo:
-<em>moodleadmin</em>. Isto corrige os links de administração no Moodle.';
-$string['pathssubdataroot'] = 'É necessário um local onde o Moodle possa gravar os ficheiros submetidos. Este diretório tem que ter permissões de leitura e ESCRITA pelo servidor web (normalmente \'nobody\' ou \'apache\'), mas não pode estar acessível através da web. O programa de instalação tentará criar este diretório se ele ainda não existir.';
-$string['pathssubdirroot'] = 'Caminho completo para a diretoria de instalação do Moodle.';
-$string['pathssubwwwroot'] = 'Endereço web completo para acesso ao Moodle.
-Não é possível aceder ao Moodle usando vários endereços.
-Se o seu site tem vários endereços públicos é necessário definir redirecionamentos permanentes em todos eles exceto neste.
-Se o seu site pode ser acedido via intranet e Internet use este endereço público e configure o DNS para que a intranet permita a utilização deste endereço.
-Se o endereço não estiver correto mude o URL no seu browser para reiniciar a instalação com um valor diferente.';
-$string['pathsunsecuredataroot'] = 'O diretório dataroot não é seguro';
-$string['pathswrongadmindir'] = 'A diretoria admin não existe';
-$string['phpextension'] = 'Extensão PHP {$a}';
+$string['pathsrodataroot'] = 'A pasta de dados não tem permissões de escrita.';
+$string['pathsroparentdataroot'] = 'A pasta pai <b>{$a->parent}</b> não tem permissões de escrita. O programa de instalação não conseguiu criar a pasta <b>{$a->dataroot}</b>.';
+$string['pathssubadmindir'] = 'Alguns servidores Web utilizam a pasta <strong>admin</strong> em URL\'s especiais de acesso a funcionalidades especiais, como é o caso de painéis de controlo. Algumas situações podem criar conflitos com a localização normal das páginas de administração do Moodle. Estes problemas podem ser resolvidos renomeando a pasta <strong>admin</strong> na instalação do Moodle e indicando aqui o novo nome a utilizar. Por exemplo:<br /><br /><b>moodleadmin</b><br /><br />Esta ação resolverá os problemas de acesso dos links para as funcionalidades de administração do Moodle.';
+$string['pathssubdataroot'] = 'É necessária uma pasta onde o Moodle possa gravar os ficheiros enviados para a plataforma. Esta pasta deve ter permissão de <b>leitura</b> e <b>escrita</b> pelo utilizador do web server (normalmente <b>nobody</b> ou <b>apache</b>). Por razões de segurança esta pasta não deve estar diretamente acessível através da Internet.';
+$string['pathssubdirroot'] = 'Caminho completo para a pasta de instalação do Moodle.';
+$string['pathssubwwwroot'] = 'Endereço web completo de acesso ao Moodle. Não é possível aceder ao Moodle usando mais do que um endereço. Se o site tiver mais do que um endereço público, devem ser configurados redireccionamentos permanentes em todos eles, à exceção deste. Se o site pode ser acedido a partir da Internet e de Intranets, então este endereço deve ser configurado no DNS de forma a que os utilizadores das Intranets possam usar este endereço público para aceder ao Moodle. Se o endereço não está correto, então altere o endereço indicado no browser para reiniciar a instalação com o URL correto.';
+$string['pathsunsecuredataroot'] = 'A localização da pasta de dados não é segura';
+$string['pathswrongadmindir'] = 'A pasta <b>admin</b> não existe';
+$string['phpextension'] = 'Extensão <b>{$a}</b> do PHP';
 $string['phpversion'] = 'Versão do PHP';
-$string['phpversionhelp'] = '<p>O Moodle precisa da versão 4.3.0 ou 5.1.0 do PHP (5.0.x produz vários problemas) ou superior.</p>
-<p>Atualmente está a utilizar a versão {$a}</p>
-<p>Deverá atualizar o PHP ou migrar para outro servidor com uma versão do PHP mais recente!</p>
-(No caso da versão 5.0.x, poderá regredir para uma versão 4.4.x)</p>';
+$string['phpversionhelp'] = '<p>A instalação do Moodle só é possível se o servidor tiver instalada a versão 4.3.0 ou 5.1.0 ( a versão 5.0.x apresenta vários problemas) ou superiores.</p><p>A versão atualmente instalada é  <b>{$a}</b></p><p>É necessário atualizar esta versão do PHP ou mudar para um novo servidor que possua as referidas versões!<br />(Se a versão instalada for a 5.0.x é possível regredir para a versão 4.4.x)</p>';
 $string['welcomep10'] = '{$a->installername} ({$a->installerversion})';
-$string['welcomep20'] = 'Está a ver esta página porque o pacote <strong>{$a->packname} {$a->packversion}</strong> foi instalado e posto a funcionar com sucesso no seu computador. Parabens!';
-$string['welcomep30'] = 'Esta versão do <strong>{$a->installername}</strong> inclui aplicações para criar um ambiente onde o <strong>Moodle</strong> possa funcionar, nomeadamente:';
-$string['welcomep40'] = 'Este pacote também inclui <strong>Moodle {$a->moodlerelease} ({$a->moodleversion})</strong>.';
-$string['welcomep50'] = 'A utilização de todas as aplicações neste pacote está regida pelas respetivas licenças. O pacote <strong>{$a->installername}</strong> completo é <a href="http://www.opensource.org/docs/definition_plain.html">open source</a> distribuido nos termos da licença <a href="http://www.gnu.org/copyleft/gpl.html">GPL</a>.';
-$string['welcomep60'] = 'As páginas seguintes vão conduzí-lo por alguns passos simples de seguir para configurar o <strong>Moodle</strong> no seu computador. Poderá aceitar as definições selecionadas por omissão, ou, opcionalmente, usar outras definições mais apropriadas às suas necessidades.';
-$string['welcomep70'] = 'Clique no botão "Seguinte" em baixo, para continuar com a configuração do <strong>Moodle</strong>.';
-$string['wwwroot'] = 'Endereço Web';
+$string['welcomep20'] = 'A apresentação desta página confirma a correta instalação e ativação do pacote <strong>{$a->packname} {$a->packversion}</strong> no servidor.';
+$string['welcomep30'] = 'Esta versão do pacote <strong>{$a->installername}</strong> inclui as aplicações necessárias para o correto funcionamento do  <strong>Moodle</strong>, nomeadamente:';
+$string['welcomep40'] = 'Este pacote inclui <strong>Moodle {$a->moodlerelease} ({$a->moodleversion})</strong>.';
+$string['welcomep50'] = 'A utilização de todas as aplicações incluídas neste pacote é limitada pelas respetivas licenças. O pacote completo <strong>{$a->installername}</strong> é <ahref="http://www.opensource.org/docs/definition_plain.html">código aberto</a> e distribuído nos termos da licença <a href="http://www.gnu.org/copyleft/gpl.html">GPL</a>.';
+$string['welcomep60'] = 'As páginas seguintes irão levá-lo através de alguns passos simples para
+     configurar e definir o <strong>Moodle</strong> no seu computador. Você pode aceitar as configurações predefinidas ou, opcionalmente, alterá-las para atender às suas próprias necessidades.';
+$string['welcomep70'] = 'Clique no botão "Seguinte" para continuar a configuração do <strong>Moodle</strong>.';
+$string['wwwroot'] = 'Endereço web';
index 58ad62b..02f60f7 100644 (file)
@@ -30,5 +30,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
+$string['parentlanguage'] = '';
 $string['thisdirection'] = 'ltr';
 $string['thislanguage'] = 'Português - Portugal';
index 9473ac8..1374074 100644 (file)
@@ -30,7 +30,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$string['language'] = 'Língua';
-$string['next'] = 'Próximo';
+$string['language'] = 'Idioma';
+$string['next'] = 'Seguinte';
 $string['previous'] = 'Anterior';
 $string['reload'] = 'Recarregar';
diff --git a/install/lang/sv_fi/moodle.php b/install/lang/sv_fi/moodle.php
new file mode 100644 (file)
index 0000000..48a4a3a
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Automatically generated strings for Moodle installer
+ *
+ * Do not edit this file manually! It contains just a subset of strings
+ * needed during the very first steps of installation. This file was
+ * generated automatically by export-installer.php (which is part of AMOS
+ * {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
+ * list of strings defined in /install/stringnames.txt.
+ *
+ * @package   installer
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$string['previous'] = 'Föregående';
+$string['reload'] = 'Ladda om';
index baf70f5..30253fd 100644 (file)
@@ -1010,8 +1010,24 @@ $string['upgradelogs'] = 'For full functionality, your old logs need to be upgra
 $string['upgradelogsinfo'] = 'Some changes have recently been made in the way logs are stored.  To be able to view all of your old logs on a per-activity basis, your old logs need to be upgraded.  Depending on your site this can take a long time (eg several hours) and can be quite taxing on the database for large sites.  Once you start this process you should let it finish (by keeping the browser window open).  Don\'t worry - your site will work fine for other people while the logs are being upgraded.<br /><br />Do you want to upgrade your logs now?';
 $string['upgradesettings'] = 'New settings';
 $string['upgradesettingsintro'] = 'The settings shown below were added during your last Moodle upgrade. Make any changes necessary to the defaults and then click the &quot;Save changes&quot; button at the bottom of this page.';
-$string['upgradestalefiles'] = 'Invalid installation files detected, upgrade cannot continue';
-$string['upgradestalefilesinfo'] = 'Some old PHP scripts have been detected which may indicate that you installed this version over an older one. Please fix the installation directory by removing all old scripts (except config.php) before installing the new version and then try the upgrade again. You can find more information in upgrade documentation at <a href="{$a}">{$a}</a>';
+$string['upgradestalefiles'] = 'Mixed Moodle versions detected, upgrade cannot continue';
+$string['upgradestalefilesinfo'] = 'The Moodle update process has been paused because PHP scripts from at least two major versions of Moodle have been detected in the Moodle directory.
+
+This can cause significant problems later, so in order to continue you must ensure that the Moodle directory contains only files for a single version of Moodle.
+
+The recommended way to clean your Moodle directory is as follows:
+
+* rename the current Moodle directory to "moodle_old"
+* create a new Moodle directory containing only files from either a standard Moodle package download, or from the Moodle CVS or GIT repositories
+* move the original config.php file and any non-standard plugins from the "moodle_old" directory to the new Moodle directory
+
+When you have a clean Moodle directory, refresh this page to resume the Moodle update process.
+
+This warning is often caused by unzipping a standard Moodle package over a previous version of Moodle. While this is OK for minor upgrades, it is strongly discouraged for major Moodle upgrades.
+
+This warning can also be caused by an incomplete checkout or update operation from a CVS, SVN or GIT repository, in which case you may just have to wait for the operation complete, or perhaps run the appropriate clean up command and retry the operation.
+
+You can find more information in upgrade documentation at <a href="{$a}">{$a}</a>';
 $string['upgradesure'] = 'Your Moodle files have been changed, and you are about to automatically upgrade your server to this version: <br /><br />
 <strong>{$a}</strong> <br /><br />
 Once you do this you can not go back again. <br /><br />
index 5443b07..850e873 100644 (file)
@@ -117,6 +117,7 @@ $string['categorytotalname'] = 'Category total name';
 $string['categorytotalfull'] = '{$a->category} total';
 $string['combo'] = 'Tabs and Dropdown menu';
 $string['compact'] = 'Compact';
+$string['componentcontrolsvisibility'] = 'Whether this grade item is hidden is controlled by the activity settings.';
 $string['contract'] = 'Contract category';
 $string['controls'] = 'Controls';
 $string['courseavg'] = 'Course average';
index b3e9aa2..787b871 100644 (file)
@@ -72,7 +72,7 @@ function xmldb_main_install() {
     $newsite->shortname    = '';
     $newsite->summary      = NULL;
     $newsite->newsitems    = 3;
-    $newsite->numsections  = 0;
+    $newsite->numsections  = 1;
     $newsite->category     = 0;
     $newsite->format       = 'site';  // Only for this course
     $newsite->timecreated  = time();
index 1d88b4d..22835b2 100644 (file)
       <INDEXES>
         <INDEX NAME="sortorder" UNIQUE="false" FIELDS="sortorder" NEXT="rolecontext"/>
         <INDEX NAME="rolecontext" UNIQUE="false" FIELDS="roleid, contextid" COMMENT="Index on roleid and contextid" PREVIOUS="sortorder" NEXT="usercontextrole"/>
-        <INDEX NAME="usercontextrole" UNIQUE="false" FIELDS="userid, contextid, roleid" COMMENT="Index on userid, contextid and roleid" PREVIOUS="rolecontext"/>
+        <INDEX NAME="usercontextrole" UNIQUE="false" FIELDS="userid, contextid, roleid" COMMENT="Index on userid, contextid and roleid" PREVIOUS="rolecontext" NEXT="component-itemid-userid"/>
+        <INDEX NAME="component-itemid-userid" UNIQUE="false" FIELDS="component, itemid, userid" PREVIOUS="usercontextrole"/>
       </INDEXES>
     </TABLE>
     <TABLE NAME="role_capabilities" COMMENT="permission has to be signed, overriding a capability for a particular role in a particular context" PREVIOUS="role_assignments" NEXT="role_names">
index f50ae6b..75e165f 100644 (file)
@@ -899,6 +899,21 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2012062500.02);
     }
 
+    if ($oldversion < 2012062501.01) {
+
+        // Define index component-itemid-userid (not unique) to be added to role_assignments
+        $table = new xmldb_table('role_assignments');
+        $index = new xmldb_index('component-itemid-userid', XMLDB_INDEX_NOTUNIQUE, array('component', 'itemid', 'userid'));
+
+        // Conditionally launch add index component-itemid-userid
+        if (!$dbman->index_exists($table, $index)) {
+            $dbman->add_index($table, $index);
+        }
+
+        // Main savepoint reached
+        upgrade_main_savepoint(true, 2012062501.01);
+    }
+
 
     return true;
 }
index 48a992c..9531782 100644 (file)
@@ -574,21 +574,38 @@ abstract class moodle_database {
      * @return array An array containing sql 'where' part and 'params'
      */
     protected function where_clause_list($field, array $values) {
+        if (empty($values)) {
+            return array("1 = 2", array()); // Fake condition, won't return rows ever. MDL-17645
+        }
+
+        // Note: Do not use get_in_or_equal() because it can not deal with bools and nulls.
+
         $params = array();
-        $select = array();
+        $select = "";
         $values = (array)$values;
         foreach ($values as $value) {
             if (is_bool($value)) {
                 $value = (int)$value;
             }
             if (is_null($value)) {
-                $select[] = "$field IS NULL";
+                $select = "$field IS NULL";
             } else {
-                $select[] = "$field = ?";
                 $params[] = $value;
             }
         }
-        $select = implode(" OR ", $select);
+        if ($params) {
+            if ($select !== "") {
+                $select = "$select OR ";
+            }
+            $count = count($params);
+            if ($count == 1) {
+                $select = $select."$field = ?";
+            } else {
+                $qs = str_repeat(',?', $count);
+                $qs = ltrim($qs, ',');
+                $select = $select."$field IN ($qs)";
+            }
+        }
         return array($select, $params);
     }
 
@@ -1034,10 +1051,6 @@ abstract class moodle_database {
      */
     public function get_recordset_list($table, $field, array $values, $sort='', $fields='*', $limitfrom=0, $limitnum=0) {
         list($select, $params) = $this->where_clause_list($field, $values);
-        if (empty($select)) {
-            $select = '1 = 2'; // Fake condition, won't return rows ever. MDL-17645
-            $params = array();
-        }
         return $this->get_recordset_select($table, $select, $params, $sort, $fields, $limitfrom, $limitnum);
     }
 
@@ -1132,10 +1145,6 @@ abstract class moodle_database {
      */
     public function get_records_list($table, $field, array $values, $sort='', $fields='*', $limitfrom=0, $limitnum=0) {
         list($select, $params) = $this->where_clause_list($field, $values);
-        if (empty($select)) {
-            // nothing to return
-            return array();
-        }
         return $this->get_records_select($table, $select, $params, $sort, $fields, $limitfrom, $limitnum);
     }
 
@@ -1662,10 +1671,6 @@ abstract class moodle_database {
      */
     public function delete_records_list($table, $field, array $values) {
         list($select, $params) = $this->where_clause_list($field, $values);
-        if (empty($select)) {
-            // nothing to delete
-            return true;
-        }
         return $this->delete_records_select($table, $select, $params);
     }
 
index a5ad8c2..2bb7270 100644 (file)
@@ -1137,7 +1137,7 @@ class dml_testcase extends database_driver_testcase {
         $tablename = $table->getName();
 
         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
-        $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
+        $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, '0');
         $table->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course'));
         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
         $dbman->create_table($table);
@@ -1146,9 +1146,11 @@ class dml_testcase extends database_driver_testcase {
         $DB->insert_record($tablename, array('course' => 3));
         $DB->insert_record($tablename, array('course' => 5));
         $DB->insert_record($tablename, array('course' => 2));
+        $DB->insert_record($tablename, array('course' => null));
+        $DB->insert_record($tablename, array('course' => 1));
+        $DB->insert_record($tablename, array('course' => 0));
 
         $rs = $DB->get_recordset_list($tablename, 'course', array(3, 2));
-
         $counter = 0;
         foreach ($rs as $record) {
             $counter++;
@@ -1156,6 +1158,54 @@ class dml_testcase extends database_driver_testcase {
         $this->assertEquals(3, $counter);
         $rs->close();
 
+        $rs = $DB->get_recordset_list($tablename, 'course', array(3));
+        $counter = 0;
+        foreach ($rs as $record) {
+            $counter++;
+        }
+        $this->assertEquals(2, $counter);
+        $rs->close();
+
+        $rs = $DB->get_recordset_list($tablename, 'course', array(null));
+        $counter = 0;
+        foreach ($rs as $record) {
+            $counter++;
+        }
+        $this->assertEquals(1, $counter);
+        $rs->close();
+
+        $rs = $DB->get_recordset_list($tablename, 'course', array(6, null));
+        $counter = 0;
+        foreach ($rs as $record) {
+            $counter++;
+        }
+        $this->assertEquals(1, $counter);
+        $rs->close();
+
+        $rs = $DB->get_recordset_list($tablename, 'course', array(null, 5, 5, 5));
+        $counter = 0;
+        foreach ($rs as $record) {
+            $counter++;
+        }
+        $this->assertEquals(2, $counter);
+        $rs->close();
+
+        $rs = $DB->get_recordset_list($tablename, 'course', array(true));
+        $counter = 0;
+        foreach ($rs as $record) {
+            $counter++;
+        }
+        $this->assertEquals(1, $counter);
+        $rs->close();
+
+        $rs = $DB->get_recordset_list($tablename, 'course', array(false));
+        $counter = 0;
+        foreach ($rs as $record) {
+            $counter++;
+        }
+        $this->assertEquals(1, $counter);
+        $rs->close();
+
         $rs = $DB->get_recordset_list($tablename, 'course',array()); // Must return 0 rows without conditions. MDL-17645
 
         $counter = 0;
index 01537e9..10753a9 100644 (file)
@@ -178,6 +178,9 @@ class tinymce_texteditor extends texteditor {
             $params['valid_elements'] = 'script[src|type],*[*]'; // for some reason the *[*] does not inlcude javascript src attribute MDL-25836
             $params['invalid_elements'] = '';
         }
+        // Add unique moodle elements - unfortunately we have to decide if these are SPANs or DIVs.
+        $params['extended_valid_elements'] = 'nolink,tex,algebra,lang[lang]';
+        $params['custom_elements'] = 'nolink,~tex,~algebra,lang';
 
         if (empty($options['legacy'])) {
             if (isset($options['maxfiles']) and $options['maxfiles'] != 0) {
index fd6b23d..3b2d453 100644 (file)
@@ -1375,6 +1375,7 @@ function &get_mimetypes_array() {
         'xxx'  => array ('type'=>'document/unknown', 'icon'=>'unknown'),
         '3gp'  => array ('type'=>'video/quicktime', 'icon'=>'quicktime', 'groups'=>array('video'), 'string'=>'video'),
         'aac'  => array ('type'=>'audio/aac', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'),
+        'accdb'  => array ('type'=>'application/msaccess', 'icon'=>'base'),
         'ai'   => array ('type'=>'application/postscript', 'icon'=>'eps', 'groups'=>array('image'), 'string'=>'image'),
         'aif'  => array ('type'=>'audio/x-aiff', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'),
         'aiff' => array ('type'=>'audio/x-aiff', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'),
@@ -1438,6 +1439,7 @@ function &get_mimetypes_array() {
         'latex'=> array ('type'=>'application/x-latex', 'icon'=>'text'),
         'm'    => array ('type'=>'text/plain', 'icon'=>'sourcecode'),
         'mbz'  => array ('type'=>'application/vnd.moodle.backup', 'icon'=>'moodle'),
+        'mdb'  => array ('type'=>'application/x-msaccess', 'icon'=>'base'),
         'mov'  => array ('type'=>'video/quicktime', 'icon'=>'quicktime', 'groups'=>array('video','web_video'), 'string'=>'video'),
         'movie'=> array ('type'=>'video/x-sgi-movie', 'icon'=>'quicktime', 'groups'=>array('video'), 'string'=>'video'),
         'm3u'  => array ('type'=>'audio/x-mpegurl', 'icon'=>'mp3', 'groups'=>array('audio'), 'string'=>'audio'),
index d81d5d9..164c683 100644 (file)
@@ -736,6 +736,12 @@ M.form_filemanager.init = function(Y, options) {
                 e.preventDefault();
                 this.update_file();
             }, this);
+            selectnode.all('form').on('keydown', function(e) {
+                if (e.keyCode == 13) {
+                    e.preventDefault();
+                    this.update_file();
+                }
+            }, this);
             selectnode.one('.fp-file-download').on('click', function(e) {
                 e.preventDefault();
                 if (this.selectui.fileinfo.type != 'folder') {
index 371e82f..d403547 100644 (file)
@@ -222,7 +222,7 @@ YUI.add('moodle-form-dateselector', function(Y) {
         },
         fix_position : function() {
             if (this.currentowner) {
-                this.panel.set('constrain', this.currentowner.get('node').ancestor('form'));
+                this.panel.set('constrain', Y.one(document.body));
                 this.panel.set('align', {
                     node:this.currentowner.get('node').one('select'),
                     points:[Y.WidgetPositionAlign.BL, Y.WidgetPositionAlign.TL]
index 64913cb..8b1d312 100644 (file)
@@ -2067,4 +2067,16 @@ class grade_item extends grade_object {
             return false;
         }
     }
+
+    /**
+     * Returns whether the grade item can control the visibility of the grades
+     *
+     * @return bool
+     */
+    public function can_control_visibility() {
+        if (get_plugin_directory($this->itemtype, $this->itemmodule)) {
+            return !plugin_supports($this->itemtype, $this->itemmodule, FEATURE_CONTROLS_GRADE_VISIBILITY, false);
+        }
+        return true;
+    }
 }
index 16db6c8..b5b82c8 100644 (file)
@@ -385,6 +385,8 @@ define('FEATURE_GRADE_HAS_GRADE', 'grade_has_grade');
 define('FEATURE_GRADE_OUTCOMES', 'outcomes');
 /** True if module supports advanced grading methods */
 define('FEATURE_ADVANCED_GRADING', 'grade_advanced_grading');
+/** True if module controls the grade visibility over the gradebook */
+define('FEATURE_CONTROLS_GRADE_VISIBILITY', 'controlsgradevisbility');
 
 /** True if module has code to track whether somebody viewed it */
 define('FEATURE_COMPLETION_TRACKS_VIEWS', 'completion_tracks_views');
index 9654364..b2d0e49 100644 (file)
@@ -468,7 +468,7 @@ class core_renderer extends renderer_base {
                 $link= '<a title="' . $title . '" href="' . $url . '">' . $txt . '</a>';
                 $output .= '<div class="profilingfooter">' . $link . '</div>';
             }
-            $output .= '<div class="purgecaches"><a href="'.$CFG->wwwroot.'/admin/purgecaches.php?confirm=1&amp;sesskey='.sesskey().'">'.get_string('purgecaches', 'admin').'</a></div>';
+            $output .= '<div class="purgecaches"><a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/purgecaches.php?confirm=1&amp;sesskey='.sesskey().'">'.get_string('purgecaches', 'admin').'</a></div>';
         }
         if (!empty($CFG->debugvalidators)) {
             // NOTE: this is not a nice hack, $PAGE->url is not always accurate and $FULLME neither, it is not a bug if it fails. --skodak
index a50fcd2..e438abf 100644 (file)
@@ -63,6 +63,11 @@ class page_requirements_manager {
      */
     protected $stringsforjs = array();
 
+    /**
+     * @var array List of get_string $a parameters - used for validation only.
+     */
+    protected $stringsforjs_as = array();
+
     /**
      * @var array List of JS variables to be initialised
      */
@@ -399,6 +404,12 @@ class page_requirements_manager {
         if ($url instanceof moodle_url) {
             return $url;
         } else if (strpos($url, '/') === 0) {
+            // Fix the admin links if needed.
+            if ($CFG->admin !== 'admin') {
+                if (strpos($url, "/admin/") === 0) {
+                    $url = preg_replace("|^/admin/|", "/$CFG->admin/", $url);
+                }
+            }
             if (debugging()) {
                 // check file existence only when in debug mode
                 if (!file_exists($CFG->dirroot . strtok($url, '?'))) {
@@ -861,15 +872,17 @@ class page_requirements_manager {
      * @param mixed $a any extra data to add into the string (optional).
      */
     public function string_for_js($identifier, $component, $a = NULL) {
-        $string = get_string($identifier, $component, $a);
         if (!$component) {
-            throw new coding_exception('The $module parameter is required for page_requirements_manager::string_for_js.');
+            throw new coding_exception('The $component parameter is required for page_requirements_manager::string_for_js().');
         }
-        if (isset($this->stringsforjs[$component][$identifier]) && $this->stringsforjs[$component][$identifier] !== $string) {
+        if (isset($this->stringsforjs_as[$component][$identifier]) and $this->stringsforjs_as[$component][$identifier] !== $a) {
             throw new coding_exception("Attempt to re-define already required string '$identifier' " .
-                    "from lang file '$component'. Did you already ask for it with a different \$a? {$this->stringsforjs[$component][$identifier]} !== $string");
+                    "from lang file '$component' with different \$a parameter?");
+        }
+        if (!isset($this->stringsforjs[$component][$identifier])) {
+            $this->stringsforjs[$component][$identifier] = new lang_string($identifier, $component, $a);
+            $this->stringsforjs_as[$component][$identifier] = $a;
         }
-        $this->stringsforjs[$component][$identifier] = $string;
     }
 
     /**
@@ -1212,7 +1225,13 @@ class page_requirements_manager {
 
         // add all needed strings
         if (!empty($this->stringsforjs)) {
-            $output .= html_writer::script(js_writer::set_variable('M.str', $this->stringsforjs));
+            $strings = array();
+            foreach ($this->stringsforjs as $component=>$v) {
+                foreach($v as $indentifier => $langstring) {
+                    $strings[$component][$indentifier] = $langstring->out();
+                }
+            }
+            $output .= html_writer::script(js_writer::set_variable('M.str', $strings));
         }
 
         // add variables
index d28de8d..bc74dc9 100644 (file)
@@ -101,7 +101,11 @@ function phpunit_bootstrap_cli_argument_path($moodlepath) {
     $path = realpath($CFG->dirroot.$moodlepath);
 
     if (strpos($path, $cwd) === 0) {
-        return substr($path, strlen($cwd));
+        $path = substr($path, strlen($cwd));
+    }
+
+    if (phpunit_bootstrap_is_cygwin()) {
+        $path = str_replace('\\', '/', $path);
     }
 
     return $path;
@@ -140,3 +144,14 @@ function phpunit_boostrap_fix_file_permissions($file) {
 
     return true;
 }
+
+/**
+ * Find out if running under Cygwin on Windows.
+ * @return bool
+ */
+function phpunit_bootstrap_is_cygwin() {
+    if (empty($_SERVER['SHELL']) or empty($_SERVER['OS'])) {
+        return false;
+    }
+    return ($_SERVER['OS'] === 'Windows_NT' and $_SERVER['SHELL'] === '/bin/bash');
+}
index 638b4d0..9e46811 100644 (file)
@@ -74,6 +74,12 @@ class Hint_ResultPrinter extends PHPUnit_TextUI_ResultPrinter {
             $file = substr($file, strlen($cwd)+1);
         }
 
-        $this->write("\nTo re-run:\n phpunit $testName $file\n");
+        $executable = 'phpunit';
+        if (phpunit_bootstrap_is_cygwin()) {
+            $file = str_replace('\\', '/', $file);
+            $executable = 'phpunit.bat';
+        }
+
+        $this->write("\nTo re-run:\n $executable $testName $file\n");
     }
 }
index 7c33d91..dda8714 100644 (file)
@@ -405,11 +405,12 @@ function rss_geterrorxmlfile($errortype = 'rsserror') {
  */
 function rss_get_userid_from_token($token) {
     global $DB;
-    $record = $DB->get_record('user_private_key', array('script'=>'rss','value' => $token), 'userid', IGNORE_MISSING);
-    if ($record) {
-        return $record->userid;
-    }
-    return null;
+
+    $sql = 'SELECT u.id FROM {user} u
+            JOIN {user_private_key} k ON u.id = k.userid
+            WHERE u.deleted = 0 AND u.confirmed = 1
+            AND u.suspended = 0 AND k.value = ?';
+    return $DB->get_field_sql($sql, array($token), IGNORE_MISSING);
 }
 
 /**
diff --git a/lib/tests/backup_test.php b/lib/tests/backup_test.php
new file mode 100644 (file)
index 0000000..1830f56
--- /dev/null
@@ -0,0 +1,184 @@
+<?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 backups.
+ *
+ * @package   core
+ * @category  phpunit
+ * @copyright 2012 Frédéric Massart <fred@moodle.com>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->dirroot . '/backup/util/helper/backup_cron_helper.class.php');
+
+/**
+ * Unit tests for backup system
+ */
+class backup_testcase extends advanced_testcase {
+
+    public function test_next_automated_backup() {
+
+        $this->resetAfterTest();
+        $admin = get_admin();
+        $timezone = $admin->timezone;
+
+        // Notes
+        // - The next automated backup will never be on the same date than $now
+        // - backup_auto_weekdays starts on Sunday
+        // - Tests cannot be done in the past.
+
+        // Every Wed and Sat at 11pm.
+        set_config('backup_auto_active', '1', 'backup');
+        set_config('backup_auto_weekdays', '0010010', 'backup');
+        set_config('backup_auto_hour', '23', 'backup');
+        set_config('backup_auto_minute', '0', 'backup');
+
+        $now = strtotime('next Monday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('2-23:00', date('w-H:i', $next));
+
+        $now = strtotime('next Tuesday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('5-23:00', date('w-H:i', $next));
+
+        $now = strtotime('next Wednesday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('5-23:00', date('w-H:i', $next));
+
+        $now = strtotime('next Thursday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('5-23:00', date('w-H:i', $next));
+
+        $now = strtotime('next Friday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('2-23:00', date('w-H:i', $next));
+
+        $now = strtotime('next Saturday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('2-23:00', date('w-H:i', $next));
+
+        $now = strtotime('next Sunday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('2-23:00', date('w-H:i', $next));
+
+        // Every Sun and Sat at 12pm.
+        set_config('backup_auto_active', '1', 'backup');
+        set_config('backup_auto_weekdays', '1000001', 'backup');
+        set_config('backup_auto_hour', '0', 'backup');
+        set_config('backup_auto_minute', '0', 'backup');
+
+        $now = strtotime('next Monday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('6-00:00', date('w-H:i', $next));
+
+        $now = strtotime('next Tuesday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('6-00:00', date('w-H:i', $next));
+
+        $now = strtotime('next Wednesday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('6-00:00', date('w-H:i', $next));
+
+        $now = strtotime('next Thursday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('6-00:00', date('w-H:i', $next));
+
+        $now = strtotime('next Friday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('6-00:00', date('w-H:i', $next));
+
+        $now = strtotime('next Saturday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('0-00:00', date('w-H:i', $next));
+
+        $now = strtotime('next Sunday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('6-00:00', date('w-H:i', $next));
+
+        // Every Sun at 4am.
+        set_config('backup_auto_active', '1', 'backup');
+        set_config('backup_auto_weekdays', '1000000', 'backup');
+        set_config('backup_auto_hour', '4', 'backup');
+        set_config('backup_auto_minute', '0', 'backup');
+
+        $now = strtotime('next Monday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('0-04:00', date('w-H:i', $next));
+
+        $now = strtotime('next Tuesday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('0-04:00', date('w-H:i', $next));
+
+        $now = strtotime('next Wednesday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('0-04:00', date('w-H:i', $next));
+
+        $now = strtotime('next Thursday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('0-04:00', date('w-H:i', $next));
+
+        $now = strtotime('next Friday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('0-04:00', date('w-H:i', $next));
+
+        $now = strtotime('next Saturday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('0-04:00', date('w-H:i', $next));
+
+        $now = strtotime('next Sunday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('0-04:00', date('w-H:i', $next));
+
+        // Every day but Wed at 8:30pm.
+        set_config('backup_auto_active', '1', 'backup');
+        set_config('backup_auto_weekdays', '1110111', 'backup');
+        set_config('backup_auto_hour', '20', 'backup');
+        set_config('backup_auto_minute', '30', 'backup');
+
+        $now = strtotime('next Monday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('2-20:30', date('w-H:i', $next));
+
+        $now = strtotime('next Tuesday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('4-20:30', date('w-H:i', $next));
+
+        $now = strtotime('next Wednesday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('4-20:30', date('w-H:i', $next));
+
+        $now = strtotime('next Thursday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('5-20:30', date('w-H:i', $next));
+
+        $now = strtotime('next Friday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('6-20:30', date('w-H:i', $next));
+
+        $now = strtotime('next Saturday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('0-20:30', date('w-H:i', $next));
+
+        $now = strtotime('next Sunday');
+        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
+        $this->assertEquals('1-20:30', date('w-H:i', $next));
+
+    }
+}
diff --git a/lib/tests/outputrequirementslib_test.php b/lib/tests/outputrequirementslib_test.php
new file mode 100644 (file)
index 0000000..b5b1b20
--- /dev/null
@@ -0,0 +1,49 @@
+<?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 lib/outputrequirementslibphp.
+ *
+ * @package   core
+ * @category  phpunit
+ * @copyright 2012 Petr Škoda
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->libdir . '/outputrequirementslib.php');
+
+
+class outputrequirements_test extends advanced_testcase {
+    public function test_string_for_js() {
+        $this->resetAfterTest();
+
+        $page = new moodle_page();
+        $page->requires->string_for_js('course', 'moodle', 1);
+        $page->requires->string_for_js('course', 'moodle', 1);
+        try {
+            $page->requires->string_for_js('course', 'moodle', 2);
+            $this->fail('Exception expected when the same string with different $a requested');
+        } catch (Exception $e) {
+            $this->assertInstanceOf('coding_exception', $e);
+        }
+
+        // Note: we can not switch languages in phpunit yet,
+        //       it would be nice to test that the strings are actually fetched in the footer.
+    }
+}
index 21cc5f1..cec719f 100644 (file)
@@ -8,7 +8,6 @@ YUI.add('moodle-core-blocks', function(Y) {
         EDITINGMOVE : 'editing_move',
         HEADER : 'header',
         LIGHTBOX : 'lightbox',
-        PAGECONTENT : 'page-content',
         REGIONCONTENT : 'region-content',
         SKIPBLOCK : 'skip-block',
         SKIPBLOCKTO : 'skip-block-to'
@@ -28,7 +27,8 @@ YUI.add('moodle-core-blocks', function(Y) {
             this.parentnodeclass = CSS.REGIONCONTENT;
 
             // Initialise blocks dragging
-            var blockregionlist = Y.Node.all('#'+CSS.PAGECONTENT+' div.'+CSS.BLOCKREGION);
+            // Find all block regions on the page
+            var blockregionlist = Y.Node.all('div.'+CSS.BLOCKREGION);
 
             if (blockregionlist.size() === 0) {
                 return false;
@@ -84,9 +84,6 @@ YUI.add('moodle-core-blocks', function(Y) {
                         }).plug(Y.Plugin.DDProxy, {
                             // Don't move the node at the end of the drag
                             moveOnEnd: false
-                        }).plug(Y.Plugin.DDConstrained, {
-                            // Keep it inside the .course-content
-                            constrain: '#'+CSS.PAGECONTENT
                         }).plug(Y.Plugin.DDWinScroll);
                     }
                 }, this);
@@ -139,6 +136,10 @@ YUI.add('moodle-core-blocks', function(Y) {
                 return false;
             }
 
+            // TODO: Hiding-displaying block region only works for base theme blocks
+            // (region-pre, region-post) at the moment. It should be improved
+            // to work with custom block regions as well.
+
             // TODO: Fix this for the case when user drag block towards empty section,
             // then the section appears, then user chnages his mind and moving back to
             // original section. The opposite section remains opened and empty.
@@ -151,9 +152,9 @@ YUI.add('moodle-core-blocks', function(Y) {
             }
 
             // Moving from empty region-content towards the opposite one,
-            // hide empty one
+            // hide empty one (only for region-pre, region-post areas at the moment).
             regionname = this.get_region_id(drop.ancestor('div.'+CSS.BLOCKREGION));
-            if (this.dragsourceregion.all('.'+CSS.BLOCK).size() == 0) {
+            if (this.dragsourceregion.all('.'+CSS.BLOCK).size() == 0 && this.dragsourceregion.get('id').match(/(region-pre|region-post)/i)) {
                 if (!documentbody.hasClass('side-'+regionname+'-only')) {
                     documentbody.addClass('side-'+regionname+'-only');
                 }
index d1c89c7..42f4c1b 100644 (file)
@@ -68,12 +68,15 @@ A choice activity may be used
 * To facilitate student decision-making, for example allowing students to vote on a direction for the course';
 $string['modulename_link'] = 'mod/choice/view';
 $string['modulenameplural'] = 'Choices';
+$string['moveselectedusersto'] = 'Move selected users to...';
 $string['mustchooseone'] = 'You must choose an answer before saving.  Nothing was saved.';
 $string['noguestchoose'] = 'Sorry, guests are not allowed to make choices.';
 $string['noresultsviewable'] = 'The results are not currently viewable.';
 $string['notanswered'] = 'Not answered yet';
 $string['notenrolledchoose'] = 'Sorry, only enrolled users are allowed to make choices.';
 $string['notopenyet'] = 'Sorry, this activity is not available until {$a}';
+$string['numberofuser'] = 'The number of user';
+$string['numberofuserinpercentage'] = 'The number of user in percentage';
 $string['option'] = 'Option';
 $string['page-mod-choice-x'] = 'Any choice module page';
 $string['pluginadministration'] = 'Choice administration';
@@ -89,6 +92,7 @@ $string['publishnot'] = 'Do not publish results to students';
 $string['removemychoice'] = 'Remove my choice';
 $string['removeresponses'] = 'Remove all responses';
 $string['responses'] = 'Responses';
+$string['responsesresultgraphheader'] = 'Graph display';
 $string['responsesto'] = 'Responses to {$a}';
 $string['savemychoice'] = 'Save my choice';
 $string['showunanswered'] = 'Show column for unanswered';
@@ -98,7 +102,6 @@ $string['taken'] = 'Taken';
 $string['timerestrict'] = 'Restrict answering to this time period';
 $string['viewallresponses'] = 'View {$a} responses';
 $string['withselected'] = 'With selected';
+$string['userchoosethisoption'] = 'User choose this option';
 $string['yourselection'] = 'Your selection';
 $string['skipresultgraph'] = 'Skip result graph';
-$string['moveselectedusersto'] = 'Move selected users to...';
-$string['numberofuser'] = 'The number of user';
index 1c4da2b..07bbd19 100644 (file)
@@ -141,36 +141,72 @@ class mod_choice_renderer extends plugin_renderer_base {
         $table->cellspacing = 0;
         $table->attributes['class'] = 'results names ';
         $table->tablealign = 'center';
+        $table->summary = get_string('responsesto', 'choice', format_string($choices->name));
         $table->data = array();
 
         $count = 0;
         ksort($choices->options);
 
         $columns = array();
+        $celldefault = new html_table_cell();
+        $celldefault->attributes['class'] = 'data';
+
+        // This extra cell is needed in order to support accessibility for screenreader. MDL-30816
+        $accessiblecell = new html_table_cell();
+        $accessiblecell->scope = 'row';
+        $accessiblecell->text = get_string('choiceoptions', 'choice');
+        $columns['options'][] = $accessiblecell;
+
+        $usernumberheader = clone($celldefault);
+        $usernumberheader->header = true;
+        $usernumberheader->attributes['class'] = 'header data';
+        $usernumberheader->text = get_string('numberofuser', 'choice');
+        $columns['usernumber'][] = $usernumberheader;
+
+
         foreach ($choices->options as $optionid => $options) {
-            $coldata = '';
+            $celloption = clone($celldefault);
+            $cellusernumber = clone($celldefault);
+            $cellusernumber->style = 'text-align: center;';
+
+            $celltext = '';
             if ($choices->showunanswered && $optionid == 0) {
-                $coldata .= html_writer::tag('div', format_string(get_string('notanswered', 'choice')), array('class'=>'option'));
+                $celltext = format_string(get_string('notanswered', 'choice'));
             } else if ($optionid > 0) {
-                $coldata .= html_writer::tag('div', format_string($choices->options[$optionid]->text), array('class'=>'option'));
+                $celltext = format_string($choices->options[$optionid]->text);
             }
             $numberofuser = 0;
             if (!empty($options->user) && count($options->user) > 0) {
                 $numberofuser = count($options->user);
             }
 
-            $coldata .= html_writer::tag('div', ' ('.$numberofuser. ')', array('class'=>'numberofuser', 'title' => get_string('numberofuser', 'choice')));
-            $columns[] = $coldata;
+            $celloption->text = $celltext;
+            $cellusernumber->text = $numberofuser;
+
+            $columns['options'][] = $celloption;
+            $columns['usernumber'][] = $cellusernumber;
         }
 
-        $table->head = $columns;
+        $table->head = $columns['options'];
+        $table->data[] = new html_table_row($columns['usernumber']);
 
-        $coldata = '';
         $columns = array();
+
+        // This extra cell is needed in order to support accessibility for screenreader. MDL-30816
+        $accessiblecell = new html_table_cell();
+        $accessiblecell->text = get_string('userchoosethisoption', 'choice');
+        $accessiblecell->header = true;
+        $accessiblecell->scope = 'row';
+        $accessiblecell->attributes['class'] = 'header data';
+        $columns[] = $accessiblecell;
+
         foreach ($choices->options as $optionid => $options) {
-            $coldata = '';
+            $cell = new html_table_cell();
+            $cell->attributes['class'] = 'data';
+
             if ($choices->showunanswered || $optionid > 0) {
                 if (!empty($options->user)) {
+                    $optionusers = '';
                     foreach ($options->user as $user) {
                         $data = '';
                         if (empty($user->imagealt)){
@@ -188,19 +224,17 @@ class mod_choice_renderer extends plugin_renderer_base {
                         $name = html_writer::tag('a', fullname($user, $choices->fullnamecapability), array('href'=>$userlink, 'class'=>'username'));
                         $data .= html_writer::tag('div', $name, array('class'=>'fullname'));
                         $data .= html_writer::tag('div','', array('class'=>'clearfloat'));
-                        $coldata .= html_writer::tag('div', $data, array('class'=>'user'));
+                        $optionusers .= html_writer::tag('div', $data, array('class'=>'user'));
                     }
+                    $cell->text = $optionusers;
                 }
             }
-
-            $columns[] = $coldata;
+            $columns[] = $cell;
             $count++;
         }
+        $row = new html_table_row($columns);
+        $table->data[] = $row;
 
-        $table->data[] = $columns;
-        foreach ($columns as $d) {
-            $table->colclasses[] = 'data';
-        }
         $html .= html_writer::tag('div', html_writer::table($table), array('class'=>'response'));
 
         $actiondata = '';
@@ -245,71 +279,88 @@ class mod_choice_renderer extends plugin_renderer_base {
         $table->cellpadding = 5;
         $table->cellspacing = 0;
         $table->attributes['class'] = 'results anonymous ';
+        $table->summary = get_string('responsesto', 'choice', format_string($choices->name));
         $table->data = array();
+
         $count = 0;
         ksort($choices->options);
         $columns = array();
         $rows = array();
 
-        foreach ($choices->options as $optionid => $options) {
-            $numberofuser = 0;
-            if (!empty($options->user)) {
-               $numberofuser = count($options->user);
+        $headercelldefault = new html_table_cell();
+        $headercelldefault->scope = 'row';
+        $headercelldefault->header = true;
+        $headercelldefault->attributes = array('class'=>'header data');
+
+        // column header
+        $tableheader = clone($headercelldefault);
+        $tableheader->text = html_writer::tag('div', get_string('choiceoptions', 'choice'), array('class' => 'accesshide'));
+        $rows['header'][] = $tableheader;
+
+        // graph row header
+        $graphheader = clone($headercelldefault);
+        $graphheader->text = html_writer::tag('div', get_string('responsesresultgraphheader', 'choice'), array('class' => 'accesshide'));
+        $rows['graph'][] = $graphheader;
+
+        // user number row header
+        $usernumberheader = clone($headercelldefault);
+        $usernumberheader->text = get_string('numberofuser', 'choice');
+        $rows['usernumber'][] = $usernumberheader;
+
+        // user percentage row header
+        $userpercentageheader = clone($headercelldefault);
+        $userpercentageheader->text = get_string('numberofuserinpercentage', 'choice');
+        $rows['userpercentage'][] = $userpercentageheader;
+
+        $contentcelldefault = new html_table_cell();
+        $contentcelldefault->attributes = array('class'=>'data');
+
+        foreach ($choices->options as $optionid => $option) {
+            // calculate display length
+            $height = $percentageamount = $numberofuser = 0;
+            $usernumber = $userpercentage = '';
+
+            if (!empty($option->user)) {
+               $numberofuser = count($option->user);
             }
-            $height = 0;
-            $percentageamount = 0;
+
             if($choices->numberofuser > 0) {
                $height = ($CHOICE_COLUMN_HEIGHT * ((float)$numberofuser / (float)$choices->numberofuser));
                $percentageamount = ((float)$numberofuser/(float)$choices->numberofuser)*100.0;
             }
 
-            $displaydiagram = html_writer::tag('img','', array('style'=>'height:'.$height.'px;width:49px;', 'alt'=>'', 'src'=>$this->output->pix_url('column', 'choice')));
-
-            $cell = new html_table_cell();
-            $cell->text = $displaydiagram;
-            $cell->attributes = array('class'=>'graph vertical data');
-            $columns[] = $cell;
-        }
-        $rowgraph = new html_table_row();
-        $rowgraph->cells = $columns;
-        $rows[] = $rowgraph;
+            $displaygraph = html_writer::tag('img','', array('style'=>'height:'.$height.'px;width:49px;', 'alt'=>'', 'src'=>$this->output->pix_url('column', 'choice')));
 
-        $columns = array();
-        $printskiplink = true;
-        foreach ($choices->options as $optionid => $options) {
-            $columndata = '';
-            $numberofuser = 0;
-            if (!empty($options->user)) {
-               $numberofuser = count($options->user);
-            }
+            // header
+            $headercell = clone($contentcelldefault);
+            $headercell->text = $option->text;
+            $rows['header'][] = $headercell;
 
-            if ($printskiplink) {
-                $columndata .= html_writer::tag('div', '', array('class'=>'skip-block-to', 'id'=>'skipresultgraph'));
-                $printskiplink = false;
-            }
+            // Graph
+            $graphcell = clone($contentcelldefault);
+            $graphcell->attributes = array('class'=>'graph vertical data');
+            $graphcell->text = $displaygraph;
+            $rows['graph'][] = $graphcell;
 
-            if ($choices->showunanswered && $optionid == 0) {
-                $columndata .= html_writer::tag('div', format_string(get_string('notanswered', 'choice')), array('class'=>'option'));
-            } else if ($optionid > 0) {
-                $columndata .= html_writer::tag('div', format_string($choices->options[$optionid]->text), array('class'=>'option'));
-            }
-            $columndata .= html_writer::tag('div', ' ('.$numberofuser.')', array('class'=>'numberofuser', 'title'=> get_string('numberofuser', 'choice')));
+            $usernumber .= html_writer::tag('div', ' '.$numberofuser.'', array('class'=>'numberofuser', 'title'=> get_string('numberofuser', 'choice')));
+            $userpercentage .= html_writer::tag('div', format_float($percentageamount,1). '%', array('class'=>'percentage'));
 
-            if($choices->numberofuser > 0) {
-               $percentageamount = ((float)$numberofuser/(float)$choices->numberofuser)*100.0;
-            }
-            $columndata .= html_writer::tag('div', format_float($percentageamount,1). '%', array('class'=>'percentage'));
+            // number of user
+            $usernumbercell = clone($contentcelldefault);
+            $usernumbercell->text = $usernumber;
+            $rows['usernumber'][] = $usernumbercell;
 
-            $cell = new html_table_cell();
-            $cell->text = $columndata;
-            $cell->attributes = array('class'=>'data header');
-            $columns[] = $cell;
+            // percentage of user
+            $numbercell = clone($contentcelldefault);
+            $numbercell->text = $userpercentage;
+            $rows['userpercentage'][] = $numbercell;
         }
-        $rowdata = new html_table_row();
-        $rowdata->cells = $columns;
-        $rows[] = $rowdata;
 
-        $table->data = $rows;
+        $table->head = $rows['header'];
+        $trgraph = new html_table_row($rows['graph']);
+        $trusernumber = new html_table_row($rows['usernumber']);
+        $truserpercentage = new html_table_row($rows['userpercentage']);
+        $table->data = array($trgraph, $trusernumber, $truserpercentage);
 
         $header = html_writer::tag('h2',format_string(get_string("responses", "choice")));
         $html .= html_writer::tag('div', $header, array('class'=>'responseheader'));
@@ -331,52 +382,76 @@ class mod_choice_renderer extends plugin_renderer_base {
         $table->cellpadding = 5;
         $table->cellspacing = 0;
         $table->attributes['class'] = 'results anonymous ';
+        $table->summary = get_string('responsesto', 'choice', format_string($choices->name));
         $table->data = array();
 
+        $columnheaderdefault = new html_table_cell();
+        $columnheaderdefault->scope = 'col';
+
+        $tableheadertext = clone($columnheaderdefault);
+        $tableheadertext->text = get_string('choiceoptions', 'choice');
+
+        $tableheadernumber = clone($columnheaderdefault);
+        $tableheadernumber->text = get_string('numberofuser', 'choice');
+
+        $tableheaderpercentage = clone($columnheaderdefault);
+        $tableheaderpercentage->text = get_string('numberofuserinpercentage', 'choice');
+
+        $tableheadergraph = clone($columnheaderdefault);
+        $tableheadergraph->text = get_string('responsesresultgraphheader', 'choice');
+
+        $table->head = array($tableheadertext, $tableheadernumber, $tableheaderpercentage, $tableheadergraph);
+
         $count = 0;
         ksort($choices->options);
 
+        $columndefault = new html_table_cell();
+        $columndefault->attributes['class'] = 'data';
+
+        $colheaderdefault = new html_table_cell();
+        $colheaderdefault->scope = 'row';
+        $colheaderdefault->header = true;
+        $colheaderdefault->attributes['class'] = 'header data';
+
         $rows = array();
         foreach ($choices->options as $optionid => $options) {
-            $numberofuser = 0;
-            $graphcell = new html_table_cell();
+            $colheader = clone($colheaderdefault);
+            $colheader->text = $options->text;
+
+            $graphcell = clone($columndefault);
+            $datacellnumber = clone($columndefault);
+            $datacellpercentage = clone($columndefault);
+
+            $numberofuser = $width = $percentageamount = 0;
+
             if (!empty($options->user)) {
                $numberofuser = count($options->user);
             }
 
-            $width = 0;
-            $percentageamount = 0;
-            $columndata = '';
             if($choices->numberofuser > 0) {
                $width = ($CHOICE_COLUMN_WIDTH * ((float)$numberofuser / (float)$choices->numberofuser));
                $percentageamount = ((float)$numberofuser/(float)$choices->numberofuser)*100.0;
             }
-            $displaydiagram = html_writer::tag('img','', array('style'=>'height:50px; width:'.$width.'px', 'alt'=>'', 'src'=>$this->output->pix_url('row', 'choice')));
 
-            $skiplink = html_writer::tag('a', get_string('skipresultgraph', 'choice'), array('href'=>'#skipresultgraph'. $optionid, 'class'=>'skip-block'));
-            $skiphandler = html_writer::tag('span', '', array('class'=>'skip-block-to', 'id'=>'skipresultgraph'.$optionid));
+            $attributes = array();
+            $attributes['style'] = 'height:50px; width:'.$width.'px';
+            $attributes['alt'] = '';
+            $attributes['src'] = $this->output->pix_url('row', 'choice');
+            $displaydiagram = html_writer::tag('img','', $attributes);
 
-            $graphcell->text = $skiplink . $displaydiagram . $skiphandler;
+            $graphcell->text = $displaydiagram;
             $graphcell->attributes = array('class'=>'graph horizontal');
 
-            $datacell = new html_table_cell();
-            if ($choices->showunanswered && $optionid == 0) {
-                $columndata .= html_writer::tag('div', format_string(get_string('notanswered', 'choice')), array('class'=>'option'));
-            } else if ($optionid > 0) {
-                $columndata .= html_writer::tag('div', format_string($choices->options[$optionid]->text), array('class'=>'option'));
-            }
-            $columndata .= html_writer::tag('div', ' ('.$numberofuser.')', array('title'=> get_string('numberofuser', 'choice'), 'class'=>'numberofuser'));
-
             if($choices->numberofuser > 0) {
                $percentageamount = ((float)$numberofuser/(float)$choices->numberofuser)*100.0;
             }
-            $columndata .= html_writer::tag('div', format_float($percentageamount,1). '%', array('class'=>'percentage'));
 
-            $datacell->text = $columndata;
-            $datacell->attributes = array('class'=>'header');
+            $datacellnumber->text = $numberofuser;
+            $datacellpercentage->text = format_float($percentageamount,1). '%';
+
 
             $row = new html_table_row();
-            $row->cells = array($datacell, $graphcell);
+            $row->cells = array($colheader, $datacellnumber, $datacellpercentage, $graphcell);
             $rows[] = $row;
         }
 
index ed2c5aa..bdca951 100644 (file)
@@ -23,6 +23,8 @@
 
 .path-mod-choice .results.anonymous .graph.vertical,
 .path-mod-choice .cell {vertical-align: bottom; text-align: center; }
+.path-mod-choice .results.anonymous th.header {border: 1px solid inherit;}
+
 .path-mod-choice .results.names .header{width:10%; white-space: normal;}
 .path-mod-choice .results.names .cell{vertical-align: top; text-align: left;}
 .path-mod-choice .results.names .user,
index fc1c99e..765b7ca 100644 (file)
@@ -510,15 +510,20 @@ class mod_lesson_renderer extends plugin_renderer_base {
                 $ntries = 0;  // may not be necessary
             }
 
-
             $viewedpageids = array();
-            if ($attempts = $lesson->get_attempts($ntries, true)) {
-                $viewedpageids = array_merge($viewedpageids, array_keys($attempts));
+            if ($attempts = $lesson->get_attempts($ntries, false)) {
+                foreach($attempts as $attempt) {
+                    $viewedpageids[$attempt->pageid] = $attempt;
+                }
             }
 
+            $viewedbranches = array();
             // collect all of the branch tables viewed
-            if ($viewedbranches = $DB->get_records("lesson_branch", array ("lessonid"=>$lesson->id, "userid"=>$USER->id, "retry"=>$ntries), 'timeseen DESC', 'id, pageid')) {
-                $viewedpageids = array_merge($viewedpageids, array_keys($viewedbranches));
+            if ($branches = $DB->get_records("lesson_branch", array ("lessonid"=>$lesson->id, "userid"=>$USER->id, "retry"=>$ntries), 'timeseen ASC', 'id, pageid')) {
+                foreach($branches as $branch) {
+                    $viewedbranches[$branch->pageid] = $branch;
+                }
+                $viewedpageids = array_merge($viewedpageids, $viewedbranches);
             }
 
             // Filter out the following pages:
index f88cb5e..037aa50 100644 (file)
@@ -106,7 +106,7 @@ if ($data = $form->get_data()) {
 }
 
 $PAGE->set_title("$SITE->shortname: " . get_string('toolsetup', 'lti'));
-$PAGE->navbar->add(get_string('lti_administration', 'lti'), $CFG->wwwroot.'/admin/settings.php?section=modsettinglti');
+$PAGE->navbar->add(get_string('lti_administration', 'lti'), $CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=modsettinglti');
 
 echo $OUTPUT->header();
 echo $OUTPUT->heading(get_string('toolsetup', 'lti'));
index 97bd198..6e28cbf 100644 (file)
@@ -1550,15 +1550,16 @@ function quiz_attempt_summary_link_to_reports($quiz, $cm, $context, $returnzero
  */
 function quiz_supports($feature) {
     switch($feature) {
-        case FEATURE_GROUPS:                  return true;
-        case FEATURE_GROUPINGS:               return true;
-        case FEATURE_GROUPMEMBERSONLY:        return true;
-        case FEATURE_MOD_INTRO:               return true;
-        case FEATURE_COMPLETION_TRACKS_VIEWS: return true;
-        case FEATURE_GRADE_HAS_GRADE:         return true;
-        case FEATURE_GRADE_OUTCOMES:          return false;
-        case FEATURE_BACKUP_MOODLE2:          return true;
-        case FEATURE_SHOW_DESCRIPTION:        return true;
+        case FEATURE_GROUPS:                    return true;
+        case FEATURE_GROUPINGS:                 return true;
+        case FEATURE_GROUPMEMBERSONLY:          return true;
+        case FEATURE_MOD_INTRO:                 return true;
+        case FEATURE_COMPLETION_TRACKS_VIEWS:   return true;
+        case FEATURE_GRADE_HAS_GRADE:           return true;
+        case FEATURE_GRADE_OUTCOMES:            return false;
+        case FEATURE_BACKUP_MOODLE2:            return true;
+        case FEATURE_SHOW_DESCRIPTION:          return true;
+        case FEATURE_CONTROLS_GRADE_VISIBILITY: return true;
 
         default: return null;
     }
index 8243c5b..b500784 100644 (file)
@@ -514,6 +514,7 @@ function resource_dndupload_handle($uploadinfo) {
     $data->printintro = $config->printintro;
     $data->showsize = $config->showsize;
     $data->showtype = $config->showtype;
+    $data->filterfiles = $config->filterfiles;
 
     return resource_add_instance($data, null);
 }
index 99204d1..b251127 100644 (file)
@@ -183,8 +183,8 @@ class scorm_interactions_report extends scorm_default_report {
             $countsql .= 'COUNT(DISTINCT('.$DB->sql_concat('u.id', '\'#\'', 'st.attempt').')) AS nbattempts, ';
             $countsql .= 'COUNT(DISTINCT(u.id)) AS nbusers ';
             $countsql .= $from.$where;
-            $attempts = $DB->get_records_sql($select.$from.$where, $params);
             $questioncount = get_scorm_question_count($scorm->id);
+            $nbmaincolumns = count($columns);
             for($id = 0; $id < $questioncount; $id++) {
                 if ($displayoptions['qtext']) {
                     $columns[] = 'question' . $id;
@@ -476,9 +476,7 @@ class scorm_interactions_report extends scorm_default_report {
                                     $row[] = $score;
                                 }
                                 // interaction data
-                                $i=0;
-                                $element='cmi.interactions_'.$i.'.id';
-                                while(isset($trackdata->$element)) {
+                                for ($i=0; $i < $questioncount; $i++) {
                                     if ($displayoptions['qtext']) {
                                         $element='cmi.interactions_'.$i.'.id';
                                         if (isset($trackdata->$element)) {
@@ -513,8 +511,6 @@ class scorm_interactions_report extends scorm_default_report {
                                             $row[] = '&nbsp;';
                                         }
                                     }
-                                    $i++;
-                                    $element = 'cmi.interactions_'.$i.'.id';
                                 }
                             //---end of interaction data*/
                             } else {
@@ -525,6 +521,10 @@ class scorm_interactions_report extends scorm_default_report {
                                 } else {
                                     $row[] = $strstatus;
                                 }
+                                // complete the empty cells
+                                for ($i=0; $i < count($columns) - $nbmaincolumns; $i++) {
+                                    $row[] = '&nbsp;';
+                                }
                             }
                         }
                     }
index 7aa95f2..06bcebc 100644 (file)
@@ -553,8 +553,8 @@ class qformat_gift extends qformat_default {
     protected function repchar($text, $notused = 0) {
         // Escapes 'reserved' characters # = ~ {) :
         // Removes new lines
-        $reserved = array( '#', '=', '~', '{', '}', ':', "\n", "\r");
-        $escaped =  array('\#','\=','\~','\{','\}','\:', '\n', '' );
+        $reserved = array(  '\\',  '#', '=', '~', '{', '}', ':', "\n", "\r");
+        $escaped =  array('\\\\', '\#','\=','\~','\{','\}','\:', '\n', '' );
 
         $newtext = str_replace($reserved, $escaped, $text);
         return $newtext;
index 73a8a6e..e06a123 100644 (file)
@@ -885,4 +885,73 @@ FALSE#42 is the Ultimate Answer.#You gave the right answer.}";
 
         $this->assert_same_gift($expectedgift, $gift);
     }
+
+    public function test_export_backslash() {
+        // There was a bug (MDL-34171) where \\ was getting exported as \\, not
+        // \\\\, and on import, \\ in converted to \.
+        // We need \\\\ in the test code, because of PHPs string escaping rules.
+        $qdata = (object) array(
+            'id' => 666 ,
+            'name' => 'backslash',
+            'questiontext' => 'A \\ B \\\\ C',
+            'questiontextformat' => FORMAT_MOODLE,
+            'generalfeedback' => '',
+            'generalfeedbackformat' => FORMAT_MOODLE,
+            'defaultmark' => 1,
+            'penalty' => 0.3333333,
+            'length' => 1,
+            'qtype' => 'essay',
+            'options' => (object) array(
+                'responseformat' => 'editor',
+                'responsefieldlines' => 15,
+                'attachments' => 0,
+                'graderinfo' => '',
+                'graderinfoformat' => FORMAT_HTML,
+            ),
+        );
+
+        $exporter = new qformat_gift();
+        $gift = $exporter->writequestion($qdata);
+
+        $expectedgift = "// question: 666  name: backslash
+::backslash::A \\\\ B \\\\\\\\ C{}
+
+";
+
+        $this->assert_same_gift($expectedgift, $gift);
+    }
+
+    public function test_import_backslash() {
+        // There was a bug (MDL-34171) where \\ in the import was getting changed
+        // to \. This test checks for that.
+        // We need \\\\ in the test code, because of PHPs string escaping rules.
+        $gift = '
+// essay
+::double backslash:: A \\\\ B \\\\\\\\ C{}';
+        $lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
+
+        $importer = new qformat_gift();
+        $q = $importer->readquestion($lines);
+
+        $expectedq = (object) array(
+            'name' => 'double backslash',
+            'questiontext' => 'A \\ B \\\\ C',
+            'questiontextformat' => FORMAT_MOODLE,
+            'generalfeedback' => '',
+            'generalfeedbackformat' => FORMAT_MOODLE,
+            'qtype' => 'essay',
+            'defaultmark' => 1,
+            'penalty' => 0.3333333,
+            'length' => 1,
+            'responseformat' => 'editor',
+            'responsefieldlines' => 15,
+            'attachments' => 0,
+            'graderinfo' => array(
+                'text' => '',
+                'format' => FORMAT_HTML,
+                'files' => array()),
+        );
+
+        $this->assert(new question_check_specified_fields_expectation($expectedq), $q);
+    }
 }
index 93e4490..d23f361 100644 (file)
@@ -1625,6 +1625,9 @@ M.core_filepicker.init = function(Y, options) {
             });
             content.one('form').set('id', id);
             content.one('.fp-file input').set('name', 'repo_upload_file');
+            if (data.upload.label && content.one('.fp-file label')) {
+                content.one('.fp-file label').setContent(data.upload.label);
+            }
             content.one('.fp-saveas input').set('name', 'title');
             content.one('.fp-setauthor input').setAttrs({name:'author', value:this.options.author});
             content.one('.fp-setlicense select').set('name', 'license');
index 20b67ca..73970d6 100644 (file)
@@ -59,6 +59,7 @@ $search_text = optional_param('s', '',             PARAM_CLEANHTML);
 $maxfiles    = optional_param('maxfiles', -1,      PARAM_INT);    // maxfiles
 $maxbytes    = optional_param('maxbytes',  0,      PARAM_INT);    // maxbytes
 $subdirs     = optional_param('subdirs',  0,       PARAM_INT);    // maxbytes
+$accepted_types = optional_param_array('accepted_types', '*', PARAM_RAW);
 
 // the path to save files
 $savepath = optional_param('savepath', '/',    PARAM_PATH);
@@ -75,22 +76,16 @@ if (!$course = $DB->get_record('course', array('id'=>$courseid))) {
 }
 $PAGE->set_course($course);
 
-// init repository plugin
-$sql = 'SELECT i.name, i.typeid, r.type FROM {repository} r, {repository_instances} i '.
-       'WHERE i.id=? AND i.typeid=r.id';
-if ($repository = $DB->get_record_sql($sql, array($repo_id))) {
-    $type = $repository->type;
-    if (file_exists($CFG->dirroot.'/repository/'.$type.'/lib.php')) {
-        require_once($CFG->dirroot.'/repository/'.$type.'/lib.php');
-        $classname = 'repository_' . $type;
-        try {
-            $repo = new $classname($repo_id, $contextid, array('ajax'=>false, 'name'=>$repository->name, 'type'=>$type));
-        } catch (repository_exception $e){
-            print_error('pluginerror', 'repository');
-        }
-    } else {
-        print_error('invalidplugin', 'repository');
-    }
+if ($repo_id) {
+    // Get repository instance information
+    $repooptions = array(
+        'ajax' => false,
+        'mimetypes' => $accepted_types
+    );
+    $repo = repository::get_repository_by_id($repo_id, $contextid, $repooptions);
+
+    // Check permissions
+    $repo->check_capability();
 }
 
 $context = context::instance_by_id($contextid);
@@ -285,40 +280,65 @@ case 'sign':
     break;
 
 case 'download':
-    $thefile = $repo->get_file($fileurl, $filename);
-    $filesize = filesize($thefile['path']);
-    if (($maxbytes!=-1) && ($filesize>$maxbytes)) {
-        print_error('maxbytes');
+    // Check that user has permission to access this file
+    if (!$repo->file_is_accessible($fileurl)) {
+        print_error('storedfilecannotread');
     }
-    if (!empty($thefile)) {
-        $record = new stdClass();
-        $record->filepath = $savepath;
-        $record->filename = $filename;
-        $record->component = 'user';
-        $record->filearea = 'draft';
-        $record->itemid   = $itemid;
-        $record->license  = '';
-        $record->author   = '';
-
-        $now = time();
-        $record->timecreated  = $now;
-        $record->timemodified = $now;
-        $record->userid       = $USER->id;
-        $record->contextid = $user_context->id;
-
-        $sourcefield = $repo->get_file_source_info($thefile['url']);
-        $record->source = repository::build_source_field($sourcefield);
-        try {
-            $info = repository::move_to_filepool($thefile['path'], $record);
-            redirect($home_url, get_string('downloadsucc', 'repository'));
-        } catch (moodle_exception $e) {
-            // inject target URL
-            $e->link = $PAGE->url->out();
-            echo $OUTPUT->header(); // hack: we need the embedded header here, standard error printing would not use it
-            throw $e;
+
+    // If file is already a reference, set $fileurl = file source, $repo = file repository
+    // note that in this case user may not have permission to access the source file directly
+    // so no file_browser/file_info can be used below
+    if ($repo->has_moodle_files()) {
+        $file = repository::get_moodle_file($fileurl);
+        if ($file && $file->is_external_file()) {
+            $fileurl = $file->get_reference();
+            $repo_id = $file->get_repository_id();
+            $repo = repository::get_repository_by_id($repo_id, $contextid, $repooptions);
         }
+    }
+
+    $record = new stdClass();
+    $record->filepath = $savepath;
+    $record->filename = $filename;
+    $record->component = 'user';
+    $record->filearea = 'draft';
+    $record->itemid   = $itemid;
+    $record->license  = '';
+    $record->author   = '';
+
+    $now = time();
+    $record->timecreated  = $now;
+    $record->timemodified = $now;
+    $record->userid       = $USER->id;
+    $record->contextid = $user_context->id;
+    $record->sortorder = 0;
+
+    $sourcefield = $repo->get_file_source_info($fileurl);
+    $record->source = repository::build_source_field($sourcefield);
+
+    if ($repo->has_moodle_files()) {
+        $fileinfo = $repo->copy_to_area($fileurl, $record, $maxbytes);
+        redirect($home_url, get_string('downloadsucc', 'repository'));
     } else {
-        print_error('cannotdownload', 'repository');
+        $thefile = $repo->get_file($fileurl, $filename);
+        if (!empty($thefile['path'])) {
+            $filesize = filesize($thefile['path']);
+            if ($maxbytes != -1 && $filesize>$maxbytes) {
+                unlink($thefile['path']);
+                print_error('maxbytes');
+            }
+            try {
+                $info = repository::move_to_filepool($thefile['path'], $record);
+                redirect($home_url, get_string('downloadsucc', 'repository'));
+            } catch (moodle_exception $e) {
+                // inject target URL
+                $e->link = $PAGE->url->out();
+                echo $OUTPUT->header(); // hack: we need the embedded header here, standard error printing would not use it
+                throw $e;
+            }
+        } else {
+            print_error('cannotdownload', 'repository');
+        }
     }
 
     break;
index 7d3dcd6..da01736 100644 (file)
@@ -278,6 +278,8 @@ class repository_flickr extends repository {
             $secret = '';
         }
 
+        parent::type_config_form($mform);
+
         $strrequired = get_string('required');
         $mform->addElement('text', 'api_key', get_string('apikey', 'repository_flickr'), array('value'=>$api_key,'size' => '40'));
         $mform->addElement('text', 'secret', get_string('secret', 'repository_flickr'), array('value'=>$secret,'size' => '40'));
index 6231209..c34dec7 100644 (file)
@@ -521,9 +521,10 @@ abstract class repository {
      *
      * @param int $repositoryid repository ID
      * @param stdClass|int $context context instance or context ID
+     * @param array $options additional repository options
      * @return repository
      */
-    public static function get_repository_by_id($repositoryid, $context) {
+    public static function get_repository_by_id($repositoryid, $context, $options = array()) {
         global $CFG, $DB;
 
         $sql = 'SELECT i.name, i.typeid, r.type FROM {repository} r, {repository_instances} i WHERE i.id=? AND i.typeid=r.id';
@@ -539,10 +540,15 @@ abstract class repository {
                 if (is_object($context)) {
                     $contextid = $context->id;
                 }
-                $repository = new $classname($repositoryid, $contextid, array('type'=>$type));
+                $options['type'] = $type;
+                $options['typeid'] = $record->typeid;
+                if (empty($options['name'])) {
+                    $options['name'] = $record->name;
+                }
+                $repository = new $classname($repositoryid, $contextid, $options);
                 return $repository;
             } else {
-                throw new moodle_exception('error');
+                throw new repository_exception('invalidplugin', 'repository');
             }
         }
     }
@@ -609,16 +615,16 @@ abstract class repository {
     }
 
     /**
-     * To check if the context id is valid
+     * Checks if user has a capability to view the current repository in current context
      *
-     * @static
-     * @param int $contextid
-     * @param stdClass $instance
      * @return bool
      */
-    public static function check_capability($contextid, $instance) {
-        $context = get_context_instance_by_id($contextid);
-        $capability = has_capability('repository/'.$instance->type.':view', $context);
+    public final function check_capability() {
+        $capability = false;
+        if (preg_match("/^repository_(.*)$/", get_class($this), $matches)) {
+            $type = $matches[1];
+            $capability = has_capability('repository/'.$type.':view', $this->context);
+        }
         if (!$capability) {
             throw new repository_exception('nopermissiontoaccess', 'repository');
         }
@@ -651,45 +657,60 @@ abstract class repository {
      * @return stored_file|null
      */
     public static function get_moodle_file($source) {
-        $params = unserialize(base64_decode($source));
-        if (empty($params) || !is_array($params)) {
-            return null;
-        }
-        foreach (array('contextid', 'itemid', 'filename', 'filepath', 'component') as $key) {
-            if (!array_key_exists($key, $params)) {
-                return null;
+        $params = file_storage::unpack_reference($source, true);
+        $fs = get_file_storage();
+        return $fs->get_file($params['contextid'], $params['component'], $params['filearea'],
+                    $params['itemid'], $params['filepath'], $params['filename']);
+    }
+
+    /**
+     * Repository method to make sure that user can access particular file.
+     *
+     * This is checked when user tries to pick the file from repository to deal with
+     * potential parameter substitutions is request
+     *
+     * @param string $source
+     * @return bool whether the file is accessible by current user
+     */
+    public function file_is_accessible($source) {
+        if ($this->has_moodle_files()) {
+            try {
+                $params = file_storage::unpack_reference($source, true);
+            } catch (file_reference_exception $e) {
+                return false;
             }
+            $browser = get_file_browser();
+            $context = context::instance_by_id($params['contextid']);
+            $file_info = $browser->get_file_info($context, $params['component'], $params['filearea'],
+                    $params['itemid'], $params['filepath'], $params['filename']);
+            return !empty($file_info);
         }
-        $contextid  = clean_param($params['contextid'], PARAM_INT);
-        $component  = clean_param($params['component'], PARAM_COMPONENT);
-        $filearea   = clean_param($params['filearea'],  PARAM_AREA);
-        $itemid     = clean_param($params['itemid'],    PARAM_INT);
-        $filepath   = clean_param($params['filepath'],  PARAM_PATH);
-        $filename   = clean_param($params['filename'],  PARAM_FILE);
-        $fs = get_file_storage();
-        return $fs->get_file($contextid, $component, $filearea, $itemid, $filepath, $filename);
+        return true;
     }
 
     /**
-     * This function is used to copy a moodle file to draft area
+     * 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
+     * It DOES NOT check if the user is allowed to access this file because the actual file
+     * can be located in the area where user does not have access to but there is an alias
+     * to this file in the area where user CAN access it.
+     * {@link file_is_accessible} should be called for alias location before calling this function.
+     *
+     * @param string $source The metainfo of file, it is base64 encoded php serialized data
      * @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
+     * @return array The information about the created file
      */
-    public function copy_to_area($encoded, $filerecord, $maxbytes = -1) {
+    public function copy_to_area($source, $filerecord, $maxbytes = -1) {
         global $USER;
         $fs = get_file_storage();
-        $browser = get_file_browser();
 
         if ($this->has_moodle_files() == false) {
             throw new coding_exception('Only repository used to browse moodle files can use repository::copy_to_area()');
         }
 
-        $params = unserialize(base64_decode($encoded));
         $user_context = context_user::instance($USER->id);
 
         $filerecord = (array)$filerecord;
@@ -701,17 +722,9 @@ abstract class repository {
         $new_filepath = $filerecord['filepath'];
         $new_filename = $filerecord['filename'];
 
-        $contextid  = clean_param($params['contextid'], PARAM_INT);
-        $fileitemid = clean_param($params['itemid'],    PARAM_INT);
-        $filename   = clean_param($params['filename'],  PARAM_FILE);
-        $filepath   = clean_param($params['filepath'],  PARAM_PATH);;
-        $filearea   = clean_param($params['filearea'],  PARAM_AREA);
-        $component  = clean_param($params['component'], PARAM_COMPONENT);
-
-        $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) {
+        $stored_file = self::get_moodle_file($source);
+        if ($maxbytes != -1 && $stored_file->get_filesize() > $maxbytes) {
             throw new file_exception('maxbytes');
         }
 
@@ -719,7 +732,7 @@ abstract class repository {
             // create new file
             $unused_filename = repository::get_unused_filename($draftitemid, $new_filepath, $new_filename);
             $filerecord['filename'] = $unused_filename;
-            $file_info->copy_to_storage($filerecord);
+            $fs->create_file_from_storedfile($filerecord, $stored_file);
             $event = array();
             $event['event'] = 'fileexists';
             $event['newfile'] = new stdClass;
@@ -729,17 +742,17 @@ 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, $new_filepath, $new_filename)->out();;
+            $event['existingfile']->url = moodle_url::make_draftfile_url($draftitemid, $new_filepath, $new_filename)->out();
             return $event;
         } else {
-            $file_info->copy_to_storage($filerecord);
+            $fs->create_file_from_storedfile($filerecord, $stored_file);
             $info = array();
             $info['itemid'] = $draftitemid;
-            $info['file']  = $new_filename;
-            $info['title']  = $new_filename;
+            $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();;
-            $info['filesize'] = $file_info->get_filesize();
+            $info['url'] = moodle_url::make_draftfile_url($draftitemid, $new_filepath, $new_filename)->out();
+            $info['filesize'] = $stored_file->get_filesize();
             return $info;
         }
     }
index 7dbdf7b..642c7b3 100644 (file)
@@ -98,9 +98,6 @@ class repository_picasa extends repository {
         return parent::logout();
     }
 
-    public function get_name() {
-        return get_string('pluginname', 'repository_picasa');
-    }
     public function supported_filetypes() {
         return array('web_image');
     }
index 2c1acf2..f1265c8 100644 (file)
@@ -177,91 +177,22 @@ class repository_recent extends repository {
     public function supported_returntypes() {
         return FILE_INTERNAL;
     }
+
     /**
-     * This function overwrite the default implement to copying file using file_storage
+     * Repository method to make sure that user can access particular file.
+     *
+     * This is checked when user tries to pick the file from repository to deal with
+     * potential parameter substitutions is request
      *
-     * @param string $encoded The information of file, it is base64 encoded php serialized data
-     * @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
+     * @todo MDL-33805 remove this function when recent files are managed correctly
+     *
+     * @param string $source
+     * @return bool whether the file is accessible by current user
      */
-    public function copy_to_area($encoded, $filerecord, $maxbytes = -1) {
+    public function file_is_accessible($source) {
         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));
-
-        $contextid  = clean_param($params['contextid'], PARAM_INT);
-        $fileitemid = clean_param($params['itemid'],    PARAM_INT);
-        $filename   = clean_param($params['filename'],  PARAM_FILE);
-        $filepath   = clean_param($params['filepath'],  PARAM_PATH);;
-        $filearea   = clean_param($params['filearea'],  PARAM_AREA);
-        $component  = clean_param($params['component'], PARAM_COMPONENT);
-
-        // XXX:
-        // When user try to pick a file from other filearea, normally file api will use file browse to
-        // operate the files with capability check, but in some areas, users don't have permission to
-        // browse the files (for example, forum_attachment area).
-        //
-        // 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');
-            }
-            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);
-                $filerecord['filename'] = $unused_filename;
-                // create a tmp file
-                $fs->create_file_from_storedfile($filerecord, $stored_file);
-                $event = array();
-                $event['event'] = 'fileexists';
-                $event['newfile'] = new stdClass;
-                $event['newfile']->filepath = $new_filepath;
-                $event['newfile']->filename = $unused_filename;
-                $event['newfile']->url = moodle_url::make_draftfile_url($draftitemid, $new_filepath, $unused_filename)->out();
-                $event['existingfile'] = new stdClass;
-                $event['existingfile']->filepath = $new_filepath;
-                $event['existingfile']->filename = $new_filename;
-                $event['existingfile']->url      = moodle_url::make_draftfile_url($draftitemid, $new_filepath, $new_filename)->out();;
-                return $event;
-            } else {
-                $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();;
-                $info['contextid'] = $user_context->id;
-                return $info;
-            }
-        }
-        return false;
-
+        $file = self::get_moodle_file($source);
+        return (!empty($file) && $file->get_userid() == $USER->id);
     }
 
     /**
index c9863c4..2452158 100644 (file)
@@ -70,17 +70,14 @@ if (!confirm_sesskey()) {
 }
 
 // Get repository instance information
-$sql = 'SELECT i.name, i.typeid, r.type FROM {repository} r, {repository_instances} i WHERE i.id=? AND i.typeid=r.id';
-
-if (!$repository = $DB->get_record_sql($sql, array($repo_id))) {
-    $err->error = get_string('invalidrepositoryid', 'repository');
-    die(json_encode($err));
-} else {
-    $type = $repository->type;
-}
+$repooptions = array(
+    'ajax' => true,
+    'mimetypes' => $accepted_types
+);
+$repo = repository::get_repository_by_id($repo_id, $contextid, $repooptions);
 
 // Check permissions
-repository::check_capability($contextid, $repository);
+$repo->check_capability();
 
 $moodle_maxbytes = get_user_max_upload_file_size($context);
 // to prevent maxbytes greater than moodle maxbytes setting
@@ -121,21 +118,6 @@ switch ($action) {
         break;
 }
 
-if (file_exists($CFG->dirroot.'/repository/'.$type.'/lib.php')) {
-    require_once($CFG->dirroot.'/repository/'.$type.'/lib.php');
-    $classname = 'repository_' . $type;
-    $repooptions = array(
-        'ajax' => true,
-        'name' => $repository->name,
-        'type' => $type,
-        'mimetypes' => $accepted_types
-    );
-    $repo = new $classname($repo_id, $contextid, $repooptions);
-} else {
-    $err->error = get_string('invalidplugin', 'repository', $type);
-    die(json_encode($err));
-}
-
 // These actions all occur on the currently active repository instance
 switch ($action) {
     case 'sign':
@@ -232,7 +214,14 @@ switch ($action) {
             $record->userid = $USER->id;
             $record->sortorder = 0;
 
+            // Check that user has permission to access this file
+            if (!$repo->file_is_accessible($source)) {
+                throw new file_exception('storedfilecannotread');
+            }
+
             // If file is already a reference, set $source = file source, $repo = file repository
+            // note that in this case user may not have permission to access the source file directly
+            // so no file_browser/file_info can be used below
             if ($repo->has_moodle_files()) {
                 $file = repository::get_moodle_file($source);
                 if ($file && $file->is_external_file()) {
@@ -298,13 +287,13 @@ switch ($action) {
             } else {
                 // Download file to moodle.
                 $downloadedfile = $repo->get_file($source, $saveas_filename);
-                if ($downloadedfile['path'] === false) {
+                if (empty($downloadedfile['path'])) {
                     $err->error = get_string('cannotdownload', 'repository');
                     die(json_encode($err));
                 }
 
                 // Check if exceed maxbytes.
-                if (($maxbytes!==-1) && (filesize($downloadedfile['path']) > $maxbytes)) {
+                if ($maxbytes != -1 && filesize($downloadedfile['path']) > $maxbytes) {
                     throw new file_exception('maxbytes');
                 }
 
index 7420230..5b443a5 100644 (file)
@@ -155,17 +155,22 @@ class repository_upload extends repository {
             $ext = '';
             $match = array();
             $filename = clean_param($_FILES[$elname]['name'], PARAM_FILE);
-            if (preg_match('/\.([a-z0-9]+)$/i', $filename, $match)) {
-                if (isset($match[1])) {
-                    $ext = $match[1];
-                }
-            }
-            $ext = !empty($ext) ? $ext : '';
-            if (preg_match('#\.(' . $ext . ')$#i', $saveas_filename)) {
-                // saveas filename contains file extension already
+            if (strpos($filename, '.') === false) {
+                // File has no extension at all - do not add a dot.
                 $record->filename = $saveas_filename;
             } else {
-                $record->filename = $saveas_filename . '.' . $ext;
+                if (preg_match('/\.([a-z0-9]+)$/i', $filename, $match)) {
+                    if (isset($match[1])) {
+                        $ext = $match[1];
+                    }
+                }
+                $ext = !empty($ext) ? $ext : '';
+                if (preg_match('#\.(' . $ext . ')$#i', $saveas_filename)) {
+                    // saveas filename contains file extension already
+                    $record->filename = $saveas_filename;
+                } else {
+                    $record->filename = $saveas_filename . '.' . $ext;
+                }
             }
         }
 
index 1a0e2ec..836233a 100644 (file)
 .yui3-panel-focused {outline: none;}
 #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);}
+background: #E2E2E2;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
  */
-#filesskin .file-picker.fp-generallayout {width: 724px;background: #FFFFFF;border-radius:10px;border: 1px solid #CCCCCC;position: relative;}
+#filesskin .file-picker.fp-generallayout {width: 859px;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;}
 .dir-rtl .file-picker .fp-repo-area {border-left:1px solid #BBBBBB; border-right: none;}
 .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 #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 {background: #FFFFFF;clear: both;overflow:auto;width: 678px;height: 477px;margin-bottom:-14px;}
 
 .dir-rtl .file-picker .fp-repo-items {margin-right: 181px;}
 
index e220f57..246fae2 100644 (file)
 defined('MOODLE_INTERNAL') || die();
 
 
-$version  = 2012062501.00;              // YYYYMMDD      = weekly release date of this DEV branch
+$version  = 2012062501.02;              // YYYYMMDD      = weekly release date of this DEV branch
                                         //         RR    = release increments - 00 in DEV branches
                                         //           .XX = incremental changes
 
-$release  = '2.3.1 (Build: 20120706)';   // Human-friendly version name
+$release  = '2.3.1+ (Build: 20120712)';   // Human-friendly version name
 
 $branch   = '23';                       // this version's branch
 $maturity = MATURITY_STABLE;            // this version's maturity level