Merge branch 'MDL-38849' of git://github.com/timhunt/moodle
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 8 Apr 2013 22:52:27 +0000 (00:52 +0200)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 8 Apr 2013 22:52:27 +0000 (00:52 +0200)
33 files changed:
admin/cli/install.php
admin/cli/install_database.php
admin/index.php
admin/tool/behat/cli/init.php
backup/moodle2/restore_stepslib.php
calendar/lib.php
calendar/tests/calendarical_test.php [new file with mode: 0644]
calendar/upgrade.txt
install.php
lib/blocklib.php
lib/moodlelib.php
lib/navigationlib.php
lib/setup.php
lib/testing/lib.php
lib/tests/behat/behat_general.php
lib/tests/fixtures/langtest/aa/langconfig.php [new file with mode: 0644]
lib/tests/fixtures/langtest/bb/langconfig.php [new file with mode: 0644]
lib/tests/fixtures/langtest/bc/langconfig.php [new file with mode: 0644]
lib/tests/fixtures/langtest/cda/langconfig.php [new file with mode: 0644]
lib/tests/fixtures/langtest/cdb/langconfig.php [new file with mode: 0644]
lib/tests/fixtures/langtest/cdc/langconfig.php [new file with mode: 0644]
lib/tests/fixtures/langtest/de/langconfig.php [new file with mode: 0644]
lib/tests/fixtures/langtest/de_du/langconfig.php [new file with mode: 0644]
lib/tests/fixtures/langtest/de_kids/langconfig.php [new file with mode: 0644]
lib/tests/fixtures/langtest/sd/langconfig.php [new file with mode: 0644]
lib/tests/string_test.php [new file with mode: 0644]
mod/folder/module.js
mod/quiz/startattempt.php
question/type/calculated/edit_calculated_form.php
question/type/calculatedmulti/edit_calculatedmulti_form.php
question/type/calculatedsimple/edit_calculatedsimple_form.php
question/type/truefalse/edit_truefalse_form.php
version.php

index ca8aaef..35db018 100644 (file)
@@ -131,10 +131,10 @@ define('MOODLE_INTERNAL', true);
 define('CACHE_DISABLE_ALL', true);
 
 // Check that PHP is of a sufficient version
-if (version_compare(phpversion(), "5.3.2") < 0) {
+if (version_compare(phpversion(), "5.3.3") < 0) {
     $phpversion = phpversion();
     // do NOT localise - lang strings would not work here and we CAN NOT move it after installib
-    fwrite(STDERR, "Moodle 2.1 or later requires at least PHP 5.3.2 (currently using version $phpversion).\n");
+    fwrite(STDERR, "Moodle 2.5 or later requires at least PHP 5.3.3 (currently using version $phpversion).\n");
     fwrite(STDERR, "Please upgrade your server software or install older Moodle version.\n");
     exit(1);
 }
index 313f352..27a38aa 100644 (file)
@@ -55,10 +55,10 @@ Example:
 ";
 
 // Check that PHP is of a sufficient version
-if (version_compare(phpversion(), "5.3.2") < 0) {
+if (version_compare(phpversion(), "5.3.3") < 0) {
     $phpversion = phpversion();
     // do NOT localise - lang strings would not work here and we CAN NOT move it after installib
-    fwrite(STDERR, "Moodle 2.1 or later requires at least PHP 5.3.2 (currently using version $phpversion).\n");
+    fwrite(STDERR, "Moodle 2.5 or later requires at least PHP 5.3.3 (currently using version $phpversion).\n");
     fwrite(STDERR, "Please upgrade your server software or install older Moodle version.\n");
     exit(1);
 }
index def20d2..9c1a913 100644 (file)
@@ -30,10 +30,10 @@ if (!file_exists('../config.php')) {
 }
 
 // Check that PHP is of a sufficient version as soon as possible
-if (version_compare(phpversion(), '5.3.2') < 0) {
+if (version_compare(phpversion(), '5.3.3') < 0) {
     $phpversion = phpversion();
     // do NOT localise - lang strings would not work here and we CAN NOT move it to later place
-    echo "Moodle 2.1 or later requires at least PHP 5.3.2 (currently using version $phpversion).<br />";
+    echo "Moodle 2.5 or later requires at least PHP 5.3.3 (currently using version $phpversion).<br />";
     echo "Please upgrade your server software or install older Moodle version.";
     die();
 }
index ca68c16..fd11b08 100644 (file)
@@ -41,14 +41,22 @@ if ($code == 0) {
     echo "Behat test environment already installed\n";
 
 } else if ($code == BEHAT_EXITCODE_INSTALL) {
+
+    testing_update_composer_dependencies();
+
     // Behat and dependencies are installed and we need to install the test site.
+    chdir(__DIR__);
     passthru("php util.php --install", $code);
     if ($code != 0) {
         exit($code);
     }
 
 } else if ($code == BEHAT_EXITCODE_REINSTALL) {
+
+    testing_update_composer_dependencies();
+
     // Test site data is outdated.
+    chdir(__DIR__);
     passthru("php util.php --drop", $code);
     if ($code != 0) {
         exit($code);
@@ -62,19 +70,7 @@ if ($code == 0) {
 } else if ($code == BEHAT_EXITCODE_COMPOSER) {
     // Missing Behat dependencies.
 
-    // Changing to moodle dirroot to run composer related commands at project level.
-    chdir(__DIR__ . '/../../../..');
-    if (!file_exists(__DIR__ . '/../../../../composer.phar')) {
-        passthru("curl http://getcomposer.org/installer | php", $code);
-        if ($code != 0) {
-            exit($code);
-        }
-    }
-
-    passthru("php composer.phar update --dev", $code);
-    if ($code != 0) {
-        exit($code);
-    }
+    testing_update_composer_dependencies();
 
     // Returning to admin/tool/behat/cli.
     chdir(__DIR__);
index 716d29c..422533f 100644 (file)
@@ -150,6 +150,11 @@ class restore_gradebook_structure_step extends restore_structure_step {
         if ($data->itemtype=='manual') {
             // manual grade items store category id in categoryid
             $data->categoryid = $this->get_mappingid('grade_category', $data->categoryid, NULL);
+            // if mapping failed put in course's grade category
+            if (NULL == $data->categoryid) {
+                $coursecat = grade_category::fetch_course_category($this->get_courseid());
+                $data->categoryid = $coursecat->id;
+            }
         } else if ($data->itemtype=='course') {
             // course grade item stores their category id in iteminstance
             $coursecat = grade_category::fetch_course_category($this->get_courseid());
index e0c9b83..371b7ec 100644 (file)
@@ -2801,8 +2801,6 @@ function calendar_add_subscription($sub) {
         $sub->pollinterval = 0;
     }
 
-    $cache = cache::make('core', 'calendar_subscriptions');
-
     if (!empty($sub->name)) {
         if (empty($sub->id)) {
             $id = $DB->insert_record('event_subscriptions', $sub);
@@ -2810,9 +2808,7 @@ function calendar_add_subscription($sub) {
             return $id;
         } else {
             // Why are we doing an update here?
-            $DB->update_record('event_subscriptions', $sub);
-            // update cache.
-            $cache->set($sub->id, $sub);
+            calendar_update_subscription($sub);
             return $sub->id;
         }
     } else {
@@ -2920,11 +2916,7 @@ function calendar_process_subscription_row($subscriptionid, $pollinterval, $acti
                 break;
             }
             $sub->pollinterval = $pollinterval;
-            $DB->update_record('event_subscriptions', $sub);
-
-            // update the cache.
-            $cache = cache::make('core', 'calendar_subscriptions');
-            $cache->set($sub->id, $sub);
+            calendar_update_subscription($sub);
 
             // Update the events.
             return "<p>".get_string('subscriptionupdated', 'calendar', $sub->name)."</p>" . calendar_update_subscription_events($subscriptionid);
@@ -3049,13 +3041,33 @@ function calendar_update_subscription_events($subscriptionid) {
     $ical = calendar_get_icalendar($sub->url);
     $return = calendar_import_icalendar_events($ical, $sub->courseid, $subscriptionid);
     $sub->lastupdated = time();
-    $DB->update_record('event_subscriptions', $sub);
-    // Update the cache.
-    $cache = cache::make('core', 'calendar_subscriptions');
-    $cache->set($subscriptionid, $sub);
+    calendar_update_subscription($sub);
     return $return;
 }
 
+/**
+ * Update a calendar subscription. Also updates the associated cache.
+ *
+ * @param stdClass|array $subscription Subscription record.
+ * @throws coding_exception If something goes wrong
+ * @since Moodle 2.5
+ */
+function calendar_update_subscription($subscription) {
+    global $DB;
+
+    if (is_array($subscription)) {
+        $subscription = (object)$subscription;
+    }
+    if (empty($subscription->id) || !$DB->record_exists('event_subscriptions', array('id' => $subscription->id))) {
+        throw new coding_exception('Cannot update a subscription without a valid id');
+    }
+
+    $DB->update_record('event_subscriptions', $subscription);
+    // Update cache.
+    $cache = cache::make('core', 'calendar_subscriptions');
+    $cache->set($subscription->id, $subscription);
+}
+
 /**
  * Checks to see if the user can edit a given subscription feed.
  *
diff --git a/calendar/tests/calendarical_test.php b/calendar/tests/calendarical_test.php
new file mode 100644 (file)
index 0000000..7b4e117
--- /dev/null
@@ -0,0 +1,77 @@
+<?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/>.
+
+/**
+ * Calendar Ical unit tests
+ *
+ * @package    core_calendar
+ * @copyright  2013 Ankit Agarwal
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+
+
+/**
+ * Unit tests for ical APIs.
+ *
+ * @package    core_calendar
+ * @copyright  2013 Ankit Agarwal
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since Moodle 2.5
+ */
+class core_calendar_ical_testcase extends advanced_testcase {
+
+    /**
+     * Tests set up
+     */
+    protected function setUp() {
+        global $CFG;
+        require_once($CFG->dirroot . '/calendar/lib.php');
+    }
+
+    public function test_calendar_update_subscription() {
+        $this->resetAfterTest(true);
+
+        $subscription = new stdClass();
+        $subscription->eventtype = 'site';
+        $subscription->name = 'test';
+        $id = calendar_add_subscription($subscription);
+
+        $subscription = new stdClass();
+        $subscription->id = $id;
+        $subscription->name = 'awesome';
+        calendar_update_subscription($subscription);
+        $sub = calendar_get_subscription($id);
+        $this->assertEquals($subscription->name, $sub->name);
+
+        $subscription = new stdClass();
+        $subscription->id = $id;
+        $subscription->name = 'awesome2';
+        $subscription->pollinterval = 604800;
+        calendar_update_subscription($subscription);
+        $sub = calendar_get_subscription($id);
+        $this->assertEquals($subscription->name, $sub->name);
+        $this->assertEquals($subscription->pollinterval, $sub->pollinterval);
+
+        $subscription = new stdClass();
+        $subscription->name = 'awesome4';
+        $this->setExpectedException('coding_exception');
+        calendar_update_subscription($subscription);
+    }
+}
index 54262b0..72a666a 100644 (file)
@@ -8,6 +8,9 @@ required changes in code:
 * calendar_update_subscription_events() now throws a dml_exception instead of moodle_exception for bad subscriptions
 * calendar_get_mini() function now has optional $placement and $courseid paramaters.
 
+optional - no changes needed:
+* calendar_update_subscription() should now be used to update Ical subscriptions.
+
 === 2.4 ===
 
 required changes in code:
index 8c5bcf7..96e6269 100644 (file)
@@ -58,10 +58,10 @@ if (function_exists('date_default_timezone_set') and function_exists('date_defau
 @ini_set('display_errors', '1');
 
 // Check that PHP is of a sufficient version.
-if (version_compare(phpversion(), '5.3.2') < 0) {
+if (version_compare(phpversion(), '5.3.3') < 0) {
     $phpversion = phpversion();
     // do NOT localise - lang strings would not work here and we CAN not move it after installib
-    echo "Moodle 2.1 or later requires at least PHP 5.3.2 (currently using version $phpversion).<br />";
+    echo "Moodle 2.5 or later requires at least PHP 5.3.3 (currently using version $phpversion).<br />";
     echo "Please upgrade your server software or install older Moodle version.";
     die;
 }
@@ -490,7 +490,7 @@ if ($config->stage == INSTALL_DATABASETYPE) {
 
 
 if ($config->stage == INSTALL_ENVIRONMENT or $config->stage == INSTALL_PATHS) {
-    $version_fail = (version_compare(phpversion(), "5.3.2") < 0);
+    $version_fail = (version_compare(phpversion(), "5.3.3") < 0);
     $curl_fail    = ($lang !== 'en' and !extension_loaded('curl')); // needed for lang pack download
     $zip_fail     = ($lang !== 'en' and !extension_loaded('zip'));  // needed for lang pack download
 
@@ -503,7 +503,7 @@ if ($config->stage == INSTALL_ENVIRONMENT or $config->stage == INSTALL_PATHS) {
 
         echo '<div id="envresult"><dl>';
         if ($version_fail) {
-            $a = (object)array('needed'=>'5.3.2', 'current'=>phpversion());
+            $a = (object)array('needed'=>'5.3.3', 'current'=>phpversion());
             echo '<dt>'.get_string('phpversion', 'install').'</dt><dd>'.get_string('environmentrequireversion', 'admin', $a).'</dd>';
         }
         if ($curl_fail) {
index 43bd664..4d87115 100644 (file)
@@ -2154,6 +2154,7 @@ function blocks_add_default_course_blocks($course) {
         $blocknames = blocks_parse_default_blocks_list($CFG->{'defaultblocks_' . $course->format});
 
     } else {
+        require_once($CFG->dirroot. '/course/lib.php');
         $blocknames = course_get_format($course)->get_default_blocks();
 
     }
index 44b80c8..1d5b39a 100644 (file)
@@ -6685,28 +6685,18 @@ class core_string_manager implements string_manager {
     }
 
     /**
-     * Returns dependencies of current language, en is not included.
+     * Returns list of all explicit parent languages for the given language.
      *
-     * @param string $lang
-     * @return array all parents, the lang itself is last
+     * English (en) is considered as the top implicit parent of all language packs
+     * and is not included in the returned list. The language itself is appended to the
+     * end of the list. The method is aware of circular dependency risk.
+     *
+     * @see self::populate_parent_languages()
+     * @param string $lang the code of the language
+     * @return array all explicit parent languages with the lang itself appended
      */
     public function get_language_dependencies($lang) {
-        if ($lang === 'en') {
-            return array();
-        }
-        if (!file_exists("$this->otherroot/$lang/langconfig.php")) {
-            return array();
-        }
-        $string = array();
-        include("$this->otherroot/$lang/langconfig.php");
-
-        if (empty($string['parentlanguage'])) {
-            return array($lang);
-        } else {
-            $parentlang = $string['parentlanguage'];
-            unset($string);
-            return array_merge($this->get_language_dependencies($parentlang), array($lang));
-        }
+        return $this->populate_parent_languages($lang);
     }
 
     /**
@@ -7222,6 +7212,46 @@ class core_string_manager implements string_manager {
             return -1;
         }
     }
+
+    /// End of external API ////////////////////////////////////////////////////
+
+    /**
+     * Helper method that recursively loads all parents of the given language.
+     *
+     * @see self::get_language_dependencies()
+     * @param string $lang language code
+     * @param array $stack list of parent languages already populated in previous recursive calls
+     * @return array list of all parents of the given language with the $lang itself added as the last element
+     */
+    protected function populate_parent_languages($lang, array $stack = array()) {
+
+        // English does not have a parent language.
+        if ($lang === 'en') {
+            return $stack;
+        }
+
+        // Prevent circular dependency (and thence the infinitive recursion loop).
+        if (in_array($lang, $stack)) {
+            return $stack;
+        }
+
+        // Load language configuration and look for the explicit parent language.
+        if (!file_exists("$this->otherroot/$lang/langconfig.php")) {
+            return $stack;
+        }
+        $string = array();
+        include("$this->otherroot/$lang/langconfig.php");
+
+        if (empty($string['parentlanguage']) or $string['parentlanguage'] === 'en') {
+            unset($string);
+            return array_merge(array($lang), $stack);
+
+        } else {
+            $parentlang = $string['parentlanguage'];
+            unset($string);
+            return $this->populate_parent_languages($parentlang, array_merge(array($lang), $stack));
+        }
+    }
 }
 
 
index 61331f0..2322628 100644 (file)
@@ -2438,27 +2438,6 @@ class global_navigation extends navigation_node {
             $participants = $coursenode->add(get_string('participants'), null, self::TYPE_CONTAINER, get_string('participants'), 'participants');
         }
 
-        // View course reports
-        if (has_capability('moodle/site:viewreports', $this->page->context)) { // basic capability for listing of reports
-            $reportnav = $coursenode->add(get_string('reports'), null, self::TYPE_CONTAINER, null, null, new pix_icon('i/stats', ''));
-            $coursereports = get_plugin_list('coursereport'); // deprecated
-            foreach ($coursereports as $report=>$dir) {
-                $libfile = $CFG->dirroot.'/course/report/'.$report.'/lib.php';
-                if (file_exists($libfile)) {
-                    require_once($libfile);
-                    $reportfunction = $report.'_report_extend_navigation';
-                    if (function_exists($report.'_report_extend_navigation')) {
-                        $reportfunction($reportnav, $course, $this->page->context);
-                    }
-                }
-            }
-
-            $reports = get_plugin_list_with_function('report', 'extend_navigation_course', 'lib.php');
-            foreach ($reports as $reportfunction) {
-                $reportfunction($reportnav, $course, $this->page->context);
-            }
-        }
-
         // Badges.
         if ($CFG->enablebadges && has_capability('moodle/badges:viewbadges', $this->page->context)) {
             $url = new moodle_url($CFG->wwwroot . '/badges/view.php',
index 00721c6..5524a79 100644 (file)
@@ -251,10 +251,10 @@ if (file_exists("$CFG->dataroot/climaintenance.html")) {
 
 if (CLI_SCRIPT) {
     // sometimes people use different PHP binary for web and CLI, make 100% sure they have the supported PHP version
-    if (version_compare(phpversion(), '5.3.2') < 0) {
+    if (version_compare(phpversion(), '5.3.3') < 0) {
         $phpversion = phpversion();
         // do NOT localise - lang strings would not work here and we CAN NOT move it to later place
-        echo "Moodle 2.1 or later requires at least PHP 5.3.2 (currently using version $phpversion).\n";
+        echo "Moodle 2.5 or later requires at least PHP 5.3.3 (currently using version $phpversion).\n";
         echo "Some servers may have multiple PHP versions installed, are you using the correct executable?\n";
         exit(1);
     }
index 0713d6b..4cee9b1 100644 (file)
@@ -128,3 +128,42 @@ function testing_error($errorcode, $text = '') {
     echo($text."\n");
     exit($errorcode);
 }
+
+/**
+ * Updates the composer installer and the dependencies.
+ *
+ * Includes --dev dependencies.
+ *
+ * @return void exit() if something goes wrong
+ */
+function testing_update_composer_dependencies() {
+
+    // To restore the value after finishing.
+    $cwd = getcwd();
+
+    // Dirroot.
+    chdir(__DIR__ . '/../..');
+
+    // Download composer.phar if we can.
+    if (!file_exists(__DIR__ . '/../../composer.phar')) {
+        passthru("curl http://getcomposer.org/installer | php", $code);
+        if ($code != 0) {
+            exit($code);
+        }
+    } else {
+
+        // If it is already there update the installer.
+        passthru("php composer.phar self-update", $code);
+        if ($code != 0) {
+            exit($code);
+        }
+    }
+
+    // Update composer dependencies.
+    passthru("php composer.phar update --dev", $code);
+    if ($code != 0) {
+        exit($code);
+    }
+
+    chdir($cwd);
+}
index ea6b623..76fbdc3 100644 (file)
@@ -138,6 +138,28 @@ class behat_general extends behat_base {
         $node->click();
     }
 
+    /**
+     * Click on the specified element inside a table row containing the specified text.
+     *
+     * @Given /^I click on "(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>(?:[^"]|\\")*)" in the "(?P<row_text_string>(?:[^"]|\\")*)" table row$/
+     * @throws ElementNotFoundException
+     * @param string $element Element we look for
+     * @param string $selectortype The type of what we look for
+     * @param string $tablerowtext The table row text
+     */
+    public function i_click_on_in_the_table_row($element, $selectortype, $tablerowtext) {
+
+        // The table row container.
+        $nocontainerexception = new ElementNotFoundException($this->getSession(), '"' . $tablerowtext . '" row text ');
+        $tablerowtext = str_replace("'", "\'", $tablerowtext);
+        $rownode = $this->find('xpath', "//tr[contains(., '" . $tablerowtext . "')]", $nocontainerexception);
+
+        // Looking for the element DOM node inside the specified row.
+        list($selector, $locator) = $this->transform_selector($selectortype, $element);
+        $elementnode = $this->find($selector, $locator, false, $rownode);
+        $elementnode->click();
+    }
+
     /**
      * Checks, that page contains specified text.
      *
diff --git a/lib/tests/fixtures/langtest/aa/langconfig.php b/lib/tests/fixtures/langtest/aa/langconfig.php
new file mode 100644 (file)
index 0000000..15ea4c8
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+$string['thislanguage'] = 'AA native name';
+$string['thislanguageint'] = 'AA international name';
diff --git a/lib/tests/fixtures/langtest/bb/langconfig.php b/lib/tests/fixtures/langtest/bb/langconfig.php
new file mode 100644 (file)
index 0000000..3e7802c
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+$string['thislanguage'] = 'Orphaned language with non-existing parent';
+$string['parentlanguage'] = 'bbparent';
diff --git a/lib/tests/fixtures/langtest/bc/langconfig.php b/lib/tests/fixtures/langtest/bc/langconfig.php
new file mode 100644 (file)
index 0000000..cec2bf9
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+$string['thislanguage'] = 'My parent is orphaned language';
+$string['parentlanguage'] = 'bb';
diff --git a/lib/tests/fixtures/langtest/cda/langconfig.php b/lib/tests/fixtures/langtest/cda/langconfig.php
new file mode 100644 (file)
index 0000000..e9af9ca
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+$string['thislanguage'] = 'Circular dependency A';
+$string['parentlanguage'] = 'cdc';
diff --git a/lib/tests/fixtures/langtest/cdb/langconfig.php b/lib/tests/fixtures/langtest/cdb/langconfig.php
new file mode 100644 (file)
index 0000000..e3f4c62
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+$string['thislanguage'] = 'Circular dependency B';
+$string['parentlanguage'] = 'cda';
diff --git a/lib/tests/fixtures/langtest/cdc/langconfig.php b/lib/tests/fixtures/langtest/cdc/langconfig.php
new file mode 100644 (file)
index 0000000..42be227
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+$string['thislanguage'] = 'Circular dependency C';
+$string['parentlanguage'] = 'cdb';
diff --git a/lib/tests/fixtures/langtest/de/langconfig.php b/lib/tests/fixtures/langtest/de/langconfig.php
new file mode 100644 (file)
index 0000000..843d7c1
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+$string['thislanguage'] = 'Deutsch';
+$string['parentlanguage'] = 'en';
diff --git a/lib/tests/fixtures/langtest/de_du/langconfig.php b/lib/tests/fixtures/langtest/de_du/langconfig.php
new file mode 100644 (file)
index 0000000..173d669
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+$string['thislanguage'] = 'Deutsch - Du';
+$string['parentlanguage'] = 'de';
diff --git a/lib/tests/fixtures/langtest/de_kids/langconfig.php b/lib/tests/fixtures/langtest/de_kids/langconfig.php
new file mode 100644 (file)
index 0000000..c5305ef
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+$string['thislanguage'] = 'Deutsch - Kids';
+$string['parentlanguage'] = 'de_du';
diff --git a/lib/tests/fixtures/langtest/sd/langconfig.php b/lib/tests/fixtures/langtest/sd/langconfig.php
new file mode 100644 (file)
index 0000000..6551f7f
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+$string['thislanguage'] = 'Self dependency';
+$string['parentlanguage'] = 'sd';
diff --git a/lib/tests/string_test.php b/lib/tests/string_test.php
new file mode 100644 (file)
index 0000000..7ca2d9b
--- /dev/null
@@ -0,0 +1,107 @@
+<?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 localization support in lib/moodlelib.php
+ *
+ * @package     core
+ * @category    test
+ * @copyright   2013 David Mudrak <david@moodle.com>
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->libdir.'/moodlelib.php');
+
+/**
+ * Tests for the API of the string_manager
+ *
+ * @copyright 2013 David Mudrak <david@moodle.com>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class string_manager_test extends advanced_testcase {
+
+    public function test_string_manager_instance() {
+        global $CFG;
+        $this->resetAfterTest();
+
+        $otherroot = dirname(__FILE__).'/fixtures/langtest';
+        $stringman = testable_core_string_manager::instance($otherroot);
+        $this->assertTrue(in_array('string_manager', class_implements($stringman)));
+    }
+
+    public function test_get_language_dependencies() {
+        global $CFG;
+        $this->resetAfterTest();
+
+        $otherroot = dirname(__FILE__).'/fixtures/langtest';
+        $stringman = testable_core_string_manager::instance($otherroot);
+
+        // There is no parent language for 'en'.
+        $this->assertSame(array(), $stringman->get_language_dependencies('en'));
+        // Language with no parent language declared.
+        $this->assertSame(array('aa'), $stringman->get_language_dependencies('aa'));
+        // Language with parent language explicitly set to English (en < de).
+        $this->assertSame(array('de'), $stringman->get_language_dependencies('de'));
+        // Language dependency hierarchy (de < de_du < de_kids).
+        $this->assertSame(array('de', 'de_du', 'de_kids'), $stringman->get_language_dependencies('de_kids'));
+        // Language with the parent language misconfigured to itself (sd < sd).
+        $this->assertSame(array('sd'), $stringman->get_language_dependencies('sd'));
+        // Language with circular dependency (cda < cdb < cdc < cda).
+        $this->assertSame(array('cda', 'cdb', 'cdc'), $stringman->get_language_dependencies('cdc'));
+        // Orphaned language (N/A < bb).
+        $this->assertSame(array('bb'), $stringman->get_language_dependencies('bb'));
+        // Descendant of an orphaned language (N/A < bb < bc).
+        $this->assertSame(array('bb', 'bc'), $stringman->get_language_dependencies('bc'));
+    }
+}
+
+
+/**
+ * Helper class providing testable string_manager
+ *
+ * @copyright 2013 David Mudrak <david@moodle.com>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class testable_core_string_manager extends core_string_manager {
+
+    /**
+     * Factory method
+     *
+     * @param string $otherroot full path to the location of installed upstream language packs
+     * @param string $localroot full path to the location of locally customized language packs, defaults to $otherroot
+     * @param bool $usecache use application permanent cache
+     * @param array $translist explicit list of visible translations
+     * @param string $menucache the location of a file that caches the list of available translations
+     * @return testable_core_string_manager
+     */
+    public static function instance($otherroot, $localroot = null, $usecache = false, array $translist = array(), $menucache = null) {
+        global $CFG;
+
+        if (is_null($localroot)) {
+            $localroot = $otherroot;
+        }
+
+        if (is_null($menucache)) {
+            $menucache = $CFG->cachedir.'/languages';
+        }
+
+        return new testable_core_string_manager($otherroot, $localroot, $usecache, $translist, $menucache);
+    }
+}
index 64097f5..46010ac 100644 (file)
@@ -37,7 +37,7 @@ M.mod_folder.init_tree = function(Y, id, expand_all) {
             tree.expandAll();
         } else {
             // Else just expand the top node.
-            tree.getNodeByIndex(1).expand();
+            tree.getRoot().children[0].expand();
         }
 
         tree.render();
index 374db3f..f1f08ca 100644 (file)
@@ -105,7 +105,7 @@ if ($lastattempt && ($lastattempt->state == quiz_attempt::IN_PROGRESS ||
 
 } else {
     // Get number for the next or unfinished attempt.
-    if ($lastattempt && !$lastattempt->preview && !$quizobj->is_preview_user()) {
+    if ($lastattempt) {
         $attemptnumber = $lastattempt->attempt + 1;
     } else {
         $lastattempt = false;
index 19bc26a..413c7cb 100644 (file)
@@ -130,6 +130,7 @@ class qtype_calculated_edit_form extends qtype_numerical_edit_form {
         $mform->addElement('hidden', 'initialcategory', 1);
         $mform->addElement('hidden', 'reload', 1);
         $mform->setType('initialcategory', PARAM_INT);
+        $mform->setType('reload', PARAM_BOOL);
         $html2 = $this->qtypeobj->print_dataset_definitions_category($this->question);
         $mform->insertElementBefore(
                 $mform->createElement('static', 'listcategory', $label, $html2), 'name');
index b0060b1..0cc9811 100644 (file)
@@ -86,6 +86,7 @@ class qtype_calculatedmulti_edit_form extends question_edit_form {
         $repeated[] = $mform->createElement('hidden', 'tolerancetype', 1);
         $repeatedoptions['tolerance']['type'] = PARAM_FLOAT;
         $repeatedoptions['tolerance']['default'] = 0.01;
+        $repeatedoptions['tolerancetype']['type'] = PARAM_INT;
 
         // Create display group.
         $answerdisplay = array();
@@ -115,6 +116,7 @@ class qtype_calculatedmulti_edit_form extends question_edit_form {
         $mform->addElement('hidden', 'initialcategory', 1);
         $mform->addElement('hidden', 'reload', 1);
         $mform->setType('initialcategory', PARAM_INT);
+        $mform->setType('reload', PARAM_BOOL);
 
         $html2 = '';
         $mform->insertElementBefore(
index e12a711..cd2f9e5 100644 (file)
@@ -292,6 +292,7 @@ class qtype_calculatedsimple_edit_form extends qtype_calculated_edit_form {
         $label = get_string("sharedwildcards", "qtype_calculated");
         $mform->addElement('hidden', 'synchronize', 0);
         $mform->addElement('hidden', 'initialcategory', 1);
+        $mform->setType('synchronize', PARAM_BOOL);
         $mform->setType('initialcategory', PARAM_INT);
         $mform->addElement('hidden', 'reload', 1);
         $mform->setType('reload', PARAM_INT);
index 9e6f930..3af9034 100644 (file)
@@ -60,6 +60,7 @@ class qtype_truefalse_edit_form extends question_edit_form {
                 get_string('settingsformultipletries', 'question'));
 
         $mform->addElement('hidden', 'penalty', 1);
+        $mform->setType('penalty', PARAM_FLOAT);
 
         $mform->addElement('static', 'penaltymessage',
                 get_string('penaltyforeachincorrecttry', 'question'), 1);
index 142ce5b..9813e5f 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2013040500.00;              // YYYYMMDD      = weekly release date of this DEV branch
+$version  = 2013040500.01;              // YYYYMMDD      = weekly release date of this DEV branch
                                         //         RR    = release increments - 00 in DEV branches
                                         //           .XX = incremental changes
 
-$release  = '2.5beta (Build: 20130405)'; // Human-friendly version name
+$release  = '2.5beta+ (Build: 20130405)';// Human-friendly version name
 
 $branch   = '25';                       // this version's branch
 $maturity = MATURITY_BETA;             // this version's maturity level