Merge branch 'MDL-57480-master' of https://github.com/snake/moodle
authorDan Poltawski <dan@moodle.com>
Tue, 10 Jan 2017 08:40:10 +0000 (08:40 +0000)
committerDan Poltawski <dan@moodle.com>
Tue, 10 Jan 2017 08:40:10 +0000 (08:40 +0000)
23 files changed:
admin/tool/langimport/classes/output/langimport_page.php [new file with mode: 0644]
admin/tool/langimport/classes/output/renderer.php [new file with mode: 0644]
admin/tool/langimport/index.php
admin/tool/langimport/styles.css
admin/tool/langimport/templates/langimport.mustache [new file with mode: 0644]
badges/mybackpack.php
badges/mybadges.php
cache/classes/loaders.php
cache/tests/cache_test.php
course/externallib.php
course/tests/courselib_test.php
course/tests/externallib_test.php
course/upgrade.txt
lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-debug.js
lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-min.js
lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button.js
lib/editor/atto/plugins/equation/yui/src/button/js/button.js
lib/formslib.php
lib/navigationlib.php
lib/tests/behat/behat_hooks.php
mod/forum/backup/moodle2/restore_forum_stepslib.php
repository/manage_instances.php
user/files.php

diff --git a/admin/tool/langimport/classes/output/langimport_page.php b/admin/tool/langimport/classes/output/langimport_page.php
new file mode 100644 (file)
index 0000000..97ff743
--- /dev/null
@@ -0,0 +1,110 @@
+<?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/>.
+
+/**
+ * Language import page.
+ *
+ * @package    tool_langimport
+ * @copyright  2016 Jun Pataleta
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace tool_langimport\output;
+defined('MOODLE_INTERNAL') || die();
+
+use moodle_url;
+use renderable;
+use renderer_base;
+use stdClass;
+use templatable;
+
+/**
+ * Language import page class.
+ *
+ * @package    tool_langimport
+ * @copyright  2016 Jun Pataleta
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class langimport_page implements renderable, templatable {
+
+    /** @var array Array of currently installed languages. */
+    protected $installedlanguages;
+
+    /** @var array Array of languages that can be installed. */
+    protected $availablelanguages;
+
+    /** @var moodle_url The URL to be used for uninstalling the selected existing language packs. */
+    protected $uninstallurl;
+
+    /** @var moodle_url The URL to be used for updating the installed language packs. */
+    protected $updateurl;
+
+    /** @var moodle_url The URL to be used for installing the selected language packs to be installed. */
+    protected $installurl;
+
+
+    /**
+     * langimport_page constructor.
+     *
+     * @param array $installedlanguages Array of currently installed languages.
+     * @param array $availablelanguages Array of languages that can be installed.
+     * @param moodle_url $uninstallurl The URL to be used for uninstalling the selected existing language packs.
+     * @param moodle_url $updateurl The URL to be used for updating the installed language packs.
+     * @param moodle_url $installurl The URL to be used for installing the selected language packs to be installed.
+     */
+    public function __construct($installedlanguages, $availablelanguages, $uninstallurl, $updateurl, $installurl) {
+        $this->installedlanguages = $installedlanguages;
+        $this->availablelanguages = $availablelanguages;
+        $this->uninstallurl = $uninstallurl;
+        $this->updateurl = $updateurl;
+        $this->installurl = $installurl;
+    }
+
+    /**
+     * Export the data.
+     *
+     * @param renderer_base $output
+     * @return stdClass
+     */
+    public function export_for_template(renderer_base $output) {
+        $data = new stdClass();
+        $data->uninstallurl = $this->uninstallurl;
+        $data->sesskey = sesskey();
+
+        $data->installedoptions = [];
+        foreach ($this->installedlanguages as $code => $language) {
+            $option = new stdClass();
+            $option->value = $code;
+            $option->text = $language;
+            $data->installedoptions[] = $option;
+        }
+
+        $data->updateurl = $this->updateurl;
+
+        if (!empty($this->availablelanguages)) {
+            $data->toinstalloptions = [];
+            foreach ($this->availablelanguages as $code => $language) {
+                $option = new stdClass();
+                $option->value = $code;
+                $option->text = $language;
+                $data->toinstalloptions[] = $option;
+            }
+            $data->installurl = $this->installurl;
+            $data->caninstall = true;
+        }
+
+        return $data;
+    }
+}
diff --git a/admin/tool/langimport/classes/output/renderer.php b/admin/tool/langimport/classes/output/renderer.php
new file mode 100644 (file)
index 0000000..f74b11e
--- /dev/null
@@ -0,0 +1,50 @@
+<?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/>.
+
+/**
+ * Renderers.
+ *
+ * @package    tool_langimport
+ * @copyright  2016 Jun Pataleta
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace tool_langimport\output;
+
+defined('MOODLE_INTERNAL') || die();
+
+use plugin_renderer_base;
+
+/**
+ * Renderer class.
+ *
+ * @package    tool_langimport
+ * @copyright  2016 Jun Pataleta
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class renderer extends plugin_renderer_base {
+
+    /**
+     * Defer to template.
+     *
+     * @param langimport_page $page
+     * @return string
+     */
+    public function render_langimport_page(langimport_page $page) {
+        $data = $page->export_for_template($this);
+        return parent::render_from_template('tool_langimport/langimport', $data);
+    }
+}
index c5f49da..0e98a5d 100644 (file)
@@ -124,23 +124,22 @@ if ($availablelangs = $controller->availablelangs) {
 } else {
     $remote = false;
     $availablelangs = array();
-    echo $OUTPUT->box_start();
     $a = [
         'src' => $controller->lang_pack_url(),
         'dest' => $CFG->dataroot.'/lang/',
     ];
-    print_string('downloadnotavailable', 'tool_langimport', $a);
-    echo $OUTPUT->box_end();
+    $errormessage = get_string('downloadnotavailable', 'tool_langimport', $a);
+    \core\notification::error($errormessage);
 }
 
 if ($controller->info) {
     $info = implode('<br />', $controller->info);
-    echo $OUTPUT->notification($info, 'notifysuccess');
+    \core\notification::success($info);
 }
 
 if ($controller->errors) {
     $info = implode('<br />', $controller->errors);
-    echo $OUTPUT->notification($info, 'notifyproblem');
+    \core\notification::error($info);
 }
 
 if ($missingparents) {
@@ -155,67 +154,29 @@ if ($missingparents) {
             }
         }
         $info = get_string('missinglangparent', 'tool_langimport', $a);
-        echo $OUTPUT->notification($info, 'notifyproblem');
+        \core\notification::error($info);
     }
 }
 
-echo $OUTPUT->box_start();
-
-echo html_writer::start_tag('table');
-echo html_writer::start_tag('tr');
-
-// list of installed languages
-$url = new moodle_url('/admin/tool/langimport/index.php', array('mode' => DELETION_OF_SELECTED_LANG));
-echo html_writer::start_tag('td', array('valign' => 'top'));
-echo html_writer::start_tag('form', array('id' => 'uninstallform', 'action' => $url->out(), 'method' => 'post'));
-echo html_writer::start_tag('fieldset');
-echo html_writer::label(get_string('installedlangs', 'tool_langimport'), 'menuuninstalllang');
-echo html_writer::empty_tag('br');
-echo html_writer::select($installedlangs, 'uninstalllang[]', '', false, array('size' => 15, 'multiple' => 'multiple'));
-echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
-echo html_writer::empty_tag('br');
-echo html_writer::empty_tag('input', array('id' => 'languninstallbutton',
-                                         'type' => 'submit',
-                                         'value' => get_string('uninstall', 'tool_langimport'))
-                            );
-echo html_writer::end_tag('fieldset');
-echo html_writer::end_tag('form');
+$uninstallurl = new moodle_url('/admin/tool/langimport/index.php', array('mode' => DELETION_OF_SELECTED_LANG));
+$updateurl = null;
 if ($remote) {
-    $url = new moodle_url('/admin/tool/langimport/index.php', array('mode' => UPDATE_ALL_LANG));
-    echo html_writer::start_tag('form', array('id' => 'updateform', 'action' => $url->out(), 'method' => 'post'));
-    echo html_writer::tag('fieldset', html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('updatelangs','tool_langimport'))));
-    echo html_writer::end_tag('form');
+    $updateurl = new moodle_url('/admin/tool/langimport/index.php', array('mode' => UPDATE_ALL_LANG));
 }
-echo html_writer::end_tag('td');
+$installurl = new moodle_url('/admin/tool/langimport/index.php', array('mode' => INSTALLATION_OF_SELECTED_LANG));
 
-// list of available languages
+// List of available languages.
 $options = array();
 foreach ($availablelangs as $alang) {
     if (!empty($alang[0]) and trim($alang[0]) !== 'en' and !$controller->is_installed_lang($alang[0], $alang[1])) {
         $options[$alang[0]] = $alang[2].' &lrm;('.$alang[0].')&lrm;';
     }
 }
-if (!empty($options)) {
-    echo html_writer::start_tag('td', array('valign' => 'top'));
-    $url = new moodle_url('/admin/tool/langimport/index.php', array('mode' => INSTALLATION_OF_SELECTED_LANG));
-    echo html_writer::start_tag('form', array('id' => 'installform', 'action' => $url->out(), 'method' => 'post'));
-    echo html_writer::start_tag('fieldset');
-    echo html_writer::label(get_string('availablelangs','install'), 'menupack');
-    echo html_writer::empty_tag('br');
-    echo html_writer::select($options, 'pack[]', '', false, array('size' => 15, 'multiple' => 'multiple'));
-    echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
-    echo html_writer::empty_tag('br');
-    echo html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('install','tool_langimport')));
-    echo html_writer::end_tag('fieldset');
-    echo html_writer::end_tag('form');
-    echo html_writer::end_tag('td');
-}
 
-echo html_writer::end_tag('tr');
-echo html_writer::end_tag('table');
-echo $OUTPUT->box_end();
+$renderable = new \tool_langimport\output\langimport_page($installedlangs, $options, $uninstallurl, $updateurl, $installurl);
+$output = $PAGE->get_renderer('tool_langimport');
+echo $output->render($renderable);
 
-$uninstallurl = new moodle_url('/admin/tool/langimport/index.php');
 $PAGE->requires->strings_for_js(array('uninstallconfirm', 'uninstall', 'selectlangs', 'noenglishuninstall'),
                                 'tool_langimport');
 $PAGE->requires->yui_module('moodle-core-languninstallconfirm',
@@ -223,4 +184,3 @@ $PAGE->requires->yui_module('moodle-core-languninstallconfirm',
                              array(array('uninstallUrl' => $uninstallurl->out()))
                             );
 echo $OUTPUT->footer();
-die();
index 42d8a69..f23c99b 100644 (file)
@@ -1,9 +1,5 @@
-#page-admin-tool-langimport-index .generalbox table {
+#page-admin-tool-langimport-index .langimport {
     margin: auto;
+    float: none;
     width: 100%;
 }
-
-#page-admin-tool-langimport-index .generalbox,
-#page-admin-tool-langimport-index .generalbox table {
-    text-align: center;
-}
diff --git a/admin/tool/langimport/templates/langimport.mustache b/admin/tool/langimport/templates/langimport.mustache
new file mode 100644 (file)
index 0000000..25dc700
--- /dev/null
@@ -0,0 +1,117 @@
+{{!
+    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/>.
+}}
+{{!
+    @template tool_langimport/langimport
+
+    Template for the language import page.
+
+    Classes required for JS:
+    * none
+
+    Data attributes required for JS:
+    * none
+
+    Context variables required for this template:
+    * sesskey string The session key.
+    * uninstallurl string The URL for the uninstall action.
+    * updateurl string The URL for the update-language-packs action.
+    * installurl string The URL for the install action.
+    * installedoptions array The list of languages installed.
+    * toinstalloptions array The list of languages to be installed.
+    * caninstall boolean Flag to indicate if there are language packs that can be installed.
+
+    Example context (json):
+    {
+        "sesskey": "sesskey",
+        "uninstallurl": "#",
+        "updateurl": "#",
+        "installurl": "#",
+        "installedoptions": [
+            {
+                "value": "en",
+                "text": "English",
+                "selected": true
+            }
+        ],
+        "toinstalloptions": [
+            {
+                "value": "ja",
+                "text": "Japanese"
+            },
+            {
+                "value": "fr",
+                "text": "French"
+            },
+            {
+                "value": "es",
+                "text": "Spanish"
+            }
+        ],
+        "caninstall": true
+    }
+}}
+<div class="container-fluid langimport">
+    <div class="row row-fluid rtl-compatible">
+        <div class="col-md-{{#caninstall}}6{{/caninstall}}{{^caninstall}}12{{/caninstall}} span{{#caninstall}}6{{/caninstall}}{{^caninstall}}12{{/caninstall}} m-b-1">
+            <form id="uninstallform" action="{{uninstallurl}}" method="post">
+                <fieldset>
+                    <div class="form-group">
+                        <label for="menuuninstalllang">{{#str}}installedlangs, tool_langimport{{/str}}</label>
+                        <select size="15" multiple="multiple" id="menuuninstalllang" class="form-control input-block-level" name="uninstalllang[]">
+                            {{#installedoptions}}
+                                <option value="{{value}}" {{#selected}}selected="selected"{{/selected}}>{{{text}}}‎</option>
+                            {{/installedoptions}}
+                        </select>
+                    </div>
+                    <div class="form-group">
+                        <input type="hidden" name="sesskey" value="{{sesskey}}">
+                        <input id="languninstallbutton" type="submit" value="{{#str}}uninstall, tool_langimport{{/str}}" class="btn btn-default">
+                    </div>
+                </fieldset>
+            </form>
+            {{#updateurl}}
+                <div>
+                    <form id="updateform" action="{{updateurl}}" method="post">
+                        <fieldset>
+                            <input type="submit" value="{{#str}}updatelangs, tool_langimport{{/str}}" class="btn btn-default">
+                        </fieldset>
+                    </form>
+                </div>
+            {{/updateurl}}
+        </div>
+        {{#caninstall}}
+            <div class="col-md-6 span6 m-b-1">
+                <form id="installform" action="{{installurl}}" method="post">
+                    <fieldset>
+                        <div class="form-group">
+                            <label for="menupack">{{#str}}availablelangs, install{{/str}}</label>
+                            <select size="15" multiple="multiple" class="form-control input-block-level" id="menupack" name="pack[]">
+                                {{#toinstalloptions}}
+                                    <option value="{{value}}" {{#selected}}selected="selected"{{/selected}}>{{{text}}}‎</option>
+                                {{/toinstalloptions}}
+                            </select>
+                        </div>
+                        <div class="form-group">
+                            <input type="hidden" name="sesskey" value="{{sesskey}}">
+                            <input type="submit" value="{{#str}}install, tool_langimport{{/str}}" class="btn btn-default">
+                        </div>
+                    </fieldset>
+                </form>
+            </div>
+        {{/caninstall}}
+    </div>
+</div>
index d9baedd..7343d92 100644 (file)
@@ -50,7 +50,7 @@ $PAGE->set_context($context);
 $title = get_string('backpackdetails', 'badges');
 $PAGE->set_title($title);
 $PAGE->set_heading(fullname($USER));
-$PAGE->set_pagelayout('mydashboard');
+$PAGE->set_pagelayout('standard');
 
 $backpack = $DB->get_record('badge_backpack', array('userid' => $USER->id));
 $badgescache = cache::make('core', 'externalbadges');
index 0ef4f68..8437ad4 100644 (file)
@@ -89,7 +89,7 @@ $PAGE->set_context($context);
 $title = get_string('badges', 'badges');
 $PAGE->set_title($title);
 $PAGE->set_heading(fullname($USER));
-$PAGE->set_pagelayout('mydashboard');
+$PAGE->set_pagelayout('standard');
 
 // Include JS files for backpack support.
 badges_setup_backpack_js();
index 7a0adc6..3c5bd42 100644 (file)
@@ -213,7 +213,7 @@ class cache implements cache_loader {
         $this->definition = $definition;
         $this->store = $store;
         $this->storetype = get_class($store);
-        $this->perfdebug = !empty($CFG->perfdebug);
+        $this->perfdebug = (!empty($CFG->perfdebug) and $CFG->perfdebug > 7);
         if ($loader instanceof cache_loader) {
             $this->loader = $loader;
             // Mark the loader as a sub (chained) loader.
index 965a61b..ac6bfed 100644 (file)
@@ -2172,4 +2172,57 @@ class core_cache_testcase extends advanced_testcase {
         $this->assertEquals(0, $endstats[$requestid]['stores']['cachestore_static']['sets'] -
             $startstats[$requestid]['stores']['cachestore_static']['sets']);
     }
+
+    public function test_performance_debug_off() {
+        global $CFG;
+        $this->resetAfterTest(true);
+        $CFG->perfdebug = 7;
+
+        $instance = cache_config_testing::instance();
+        $applicationid = 'phpunit/applicationperfoff';
+        $instance->phpunit_add_definition($applicationid, array(
+            'mode' => cache_store::MODE_APPLICATION,
+            'component' => 'phpunit',
+            'area' => 'applicationperfoff'
+        ));
+        $sessionid = 'phpunit/sessionperfoff';
+        $instance->phpunit_add_definition($sessionid, array(
+            'mode' => cache_store::MODE_SESSION,
+            'component' => 'phpunit',
+            'area' => 'sessionperfoff'
+        ));
+        $requestid = 'phpunit/requestperfoff';
+        $instance->phpunit_add_definition($requestid, array(
+            'mode' => cache_store::MODE_REQUEST,
+            'component' => 'phpunit',
+            'area' => 'requestperfoff'
+        ));
+
+        $application = cache::make('phpunit', 'applicationperfoff');
+        $session = cache::make('phpunit', 'sessionperfoff');
+        $request = cache::make('phpunit', 'requestperfoff');
+
+        // Check that no stats are recorded for these definitions yet.
+        $stats = cache_helper::get_stats();
+        $this->assertArrayNotHasKey($applicationid, $stats);
+        $this->assertArrayNotHasKey($sessionid, $stats);
+        $this->assertArrayNotHasKey($requestid, $stats);
+
+        // Trigger cache misses, cache sets and cache hits.
+        $this->assertFalse($application->get('missMe'));
+        $this->assertTrue($application->set('setMe', 1));
+        $this->assertEquals(1, $application->get('setMe'));
+        $this->assertFalse($session->get('missMe'));
+        $this->assertTrue($session->set('setMe', 3));
+        $this->assertEquals(3, $session->get('setMe'));
+        $this->assertFalse($request->get('missMe'));
+        $this->assertTrue($request->set('setMe', 4));
+        $this->assertEquals(4, $request->get('setMe'));
+
+        // Check that no stats are being recorded for these definitions.
+        $endstats = cache_helper::get_stats();
+        $this->assertArrayNotHasKey($applicationid, $endstats);
+        $this->assertArrayNotHasKey($sessionid, $endstats);
+        $this->assertArrayNotHasKey($requestid, $endstats);
+    }
 }
index 73277e0..4a57ae5 100644 (file)
@@ -2398,6 +2398,16 @@ class core_course_external extends external_api {
                 'timemodified' => new external_value(PARAM_INT, 'Last time  the course was updated', VALUE_OPTIONAL),
                 'requested' => new external_value(PARAM_INT, 'If is a requested course', VALUE_OPTIONAL),
                 'cacherev' => new external_value(PARAM_INT, 'Cache revision number', VALUE_OPTIONAL),
+                'filters' => new external_multiple_structure(
+                    new external_single_structure(
+                        array(
+                            'filter'  => new external_value(PARAM_PLUGIN, 'Filter plugin name'),
+                            'localstate' => new external_value(PARAM_INT, 'Filter state: 1 for on, -1 for off, 0 if inherit'),
+                            'inheritedstate' => new external_value(PARAM_INT, '1 or 0 to use when localstate is set to inherit'),
+                        )
+                    ),
+                    'Course filters', VALUE_OPTIONAL
+                ),
             );
             $coursestructure = array_merge($coursestructure, $extra);
         }
@@ -2923,6 +2933,7 @@ class core_course_external extends external_api {
     public static function get_courses_by_field($field = '', $value = '') {
         global $DB, $CFG;
         require_once($CFG->libdir . '/coursecatlib.php');
+        require_once($CFG->libdir . '/filterlib.php');
 
         $params = self::validate_parameters(self::get_courses_by_field_parameters(),
             array(
@@ -2985,6 +2996,9 @@ class core_course_external extends external_api {
                 'groupmode', 'groupmodeforce', 'defaultgroupingid', 'enablecompletion', 'completionnotify', 'lang', 'theme',
                 'sortorder', 'marker');
 
+            // Course filters.
+            $coursesdata[$course->id]['filters'] = filter_get_available_in_context($context);
+
             // Information for managers only.
             if ($canupdatecourse) {
                 $managerfields = array('idnumber', 'legacyfiles', 'calendartype', 'timecreated', 'timemodified', 'requested',
index b6a9045..e67ec73 100644 (file)
@@ -2019,7 +2019,7 @@ class core_course_courselib_testcase extends advanced_testcase {
 
         // Create the course with sections.
         $course = $this->getDataGenerator()->create_course(array('numsections' => 10), array('createsections' => true));
-        $sections = $DB->get_records('course_sections', array('course' => $course->id));
+        $sections = $DB->get_records('course_sections', array('course' => $course->id), 'section');
         $coursecontext = context_course::instance($course->id);
         $section = array_pop($sections);
         course_delete_section($course, $section);
index 70d25af..7d732b0 100644 (file)
@@ -1976,16 +1976,16 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(3, $result['courses']);
         // Expect to receive all the fields.
-        $this->assertCount(35, $result['courses'][0]);
-        $this->assertCount(35, $result['courses'][1]);
-        $this->assertCount(35, $result['courses'][2]);
+        $this->assertCount(36, $result['courses'][0]);
+        $this->assertCount(36, $result['courses'][1]);
+        $this->assertCount(36, $result['courses'][2]);
 
         $result = core_course_external::get_courses_by_field('id', $course1->id);
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(1, $result['courses']);
         $this->assertEquals($course1->id, $result['courses'][0]['id']);
         // Expect to receive all the fields.
-        $this->assertCount(35, $result['courses'][0]);
+        $this->assertCount(36, $result['courses'][0]);
 
         $result = core_course_external::get_courses_by_field('id', $course2->id);
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
@@ -1996,6 +1996,10 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(2, $result['courses']);
 
+        // Check default filters.
+        $this->assertCount(3, $result['courses'][0]['filters']);
+        $this->assertCount(3, $result['courses'][1]['filters']);
+
         $result = core_course_external::get_courses_by_field('category', $category1->id);
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(1, $result['courses']);
@@ -2015,20 +2019,34 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(0, $result['courses']);
 
+        // Change filter value.
+        filter_set_local_state('mediaplugin', context_course::instance($course1->id)->id, TEXTFILTER_OFF);
+
         self::setUser($student1);
         // All visible courses  (including front page) for normal student.
         $result = core_course_external::get_courses_by_field();
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(2, $result['courses']);
-        $this->assertCount(28, $result['courses'][0]);
-        $this->assertCount(28, $result['courses'][1]);
+        $this->assertCount(29, $result['courses'][0]);
+        $this->assertCount(29, $result['courses'][1]);
 
         $result = core_course_external::get_courses_by_field('id', $course1->id);
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(1, $result['courses']);
         $this->assertEquals($course1->id, $result['courses'][0]['id']);
         // Expect to receive all the files that a student can see.
-        $this->assertCount(28, $result['courses'][0]);
+        $this->assertCount(29, $result['courses'][0]);
+
+        // Check default filters.
+        $filters = $result['courses'][0]['filters'];
+        $this->assertCount(3, $filters);
+        $found = false;
+        foreach ($filters as $filter) {
+            if ($filter['filter'] == 'mediaplugin' and $filter['localstate'] == TEXTFILTER_OFF) {
+                $found = true;
+            }
+        }
+        $this->assertTrue($found);
 
         // Course 2 is not visible.
         $result = core_course_external::get_courses_by_field('id', $course2->id);
@@ -2062,7 +2080,7 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $result = core_course_external::get_courses_by_field();
         $result = external_api::clean_returnvalue(core_course_external::get_courses_by_field_returns(), $result);
         $this->assertCount(2, $result['courses']);
-        $this->assertCount(28, $result['courses'][0]);  // Site course.
+        $this->assertCount(29, $result['courses'][0]);  // Site course.
         $this->assertCount(12, $result['courses'][1]);  // Only public information, not enrolled.
 
         $result = core_course_external::get_courses_by_field('id', $course1->id);
index 047e0be..b38361f 100644 (file)
@@ -1,6 +1,10 @@
 This files describes API changes in /course/*,
 information provided here is intended especially for developers.
 
+=== 3.3 ===
+
+ * External function core_course_external::get_courses_by_field now returns the course filters list and status.
+
 === 3.2 ===
 
  * External function core_course_external::get_course_contents now returns the section's number in the course (new section field).
index 4afc696..ae1d92c 100644 (file)
Binary files a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-debug.js and b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-debug.js differ
index 5740db9..a5ff287 100644 (file)
Binary files a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-min.js and b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-min.js differ
index 0f955ef..f98b58c 100644 (file)
Binary files a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button.js and b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button.js differ
index 45e90d3..849a967 100644 (file)
@@ -448,13 +448,15 @@ Y.namespace('M.atto_equation').Button = Y.Base.create('button', Y.M.editor_atto.
         while (equation.charAt(currentPos) === '\\' && currentPos >= 0) {
             currentPos -= 1;
         }
-        isChar = /[a-zA-Z\{\}]/;
+        isChar = /[a-zA-Z\{]/;
         if (currentPos !== 0) {
-            // Now match to the end of the line.
-            while (isChar.test(equation.charAt(currentPos)) &&
-                   currentPos < equation.length &&
-                   isChar.test(equation.charAt(currentPos - 1))) {
-                currentPos += 1;
+            if (equation.charAt(currentPos - 1) != '{') {
+                // Now match to the end of the line.
+                while (isChar.test(equation.charAt(currentPos)) &&
+                       currentPos < equation.length &&
+                       isChar.test(equation.charAt(currentPos - 1))) {
+                    currentPos += 1;
+                }
             }
         }
         // Save the cursor position - for insertion from the library.
index 2c8a3ea..1f7d4f4 100644 (file)
@@ -2165,12 +2165,14 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless {
                     }
                     //for editor element, [text] is appended to the name.
                     $fullelementname = $elementName;
-                    if ($element->getType() == 'editor') {
-                        $fullelementname .= '[text]';
-                        //Add format to rule as moodleform check which format is supported by browser
-                        //it is not set anywhere... So small hack to make sure we pass it down to quickform
-                        if (is_null($rule['format'])) {
-                            $rule['format'] = $element->getFormat();
+                    if (is_object($element) && $element->getType() == 'editor') {
+                        if ($element->getType() == 'editor') {
+                            $fullelementname .= '[text]';
+                            // Add format to rule as moodleform check which format is supported by browser
+                            // it is not set anywhere... So small hack to make sure we pass it down to quickform.
+                            if (is_null($rule['format'])) {
+                                $rule['format'] = $element->getFormat();
+                            }
                         }
                     }
                     // Fix for bug displaying errors for elements in a group
@@ -2263,7 +2265,12 @@ require(["core/event", "jquery"], function(Event, $) {
                 $elementName);
             $valFunc = 'validate_' . $this->_formName . '_' . $escapedElementName . '(ev.target, \''.$escapedElementName.'\')';
 
-            $js .= '
+            if (!is_array($element)) {
+                $element = [$element];
+            }
+            foreach ($element as $elem) {
+                if (key_exists('id', $elem->_attributes)) {
+                    $js .= '
     function validate_' . $this->_formName . '_' . $escapedElementName . '(element, escapedName) {
       if (undefined == element) {
          //required element was not found, then let form be submitted without client side validation
@@ -2286,13 +2293,15 @@ require(["core/event", "jquery"], function(Event, $) {
       }
     }
 
-    document.getElementById(\'' . $element->_attributes['id'] . '\').addEventListener(\'blur\', function(ev) {
+    document.getElementById(\'' . $elem->_attributes['id'] . '\').addEventListener(\'blur\', function(ev) {
         ' . $valFunc . '
     });
-    document.getElementById(\'' . $element->_attributes['id'] . '\').addEventListener(\'change\', function(ev) {
+    document.getElementById(\'' . $elem->_attributes['id'] . '\').addEventListener(\'change\', function(ev) {
         ' . $valFunc . '
     });
 ';
+                }
+            }
             $validateJS .= '
       ret = validate_' . $this->_formName . '_' . $escapedElementName.'(frm.elements[\''.$elementName.'\'], \''.$escapedElementName.'\') && ret;
       if (!ret && !first_focus) {
index 8d1859c..e5955b4 100644 (file)
@@ -3748,7 +3748,14 @@ class flat_navigation extends navigation_node_collection {
         if ($course->id > 1) {
             // It's a real course.
             $url = new moodle_url('/course/view.php', array('id' => $course->id));
-            $flat = new flat_navigation_node(navigation_node::create($course->shortname, $url), 0);
+
+            $coursecontext = context_course::instance($course->id, MUST_EXIST);
+            // This is the name that will be shown for the course.
+            $coursename = empty($CFG->navshowfullcoursenames) ?
+                format_string($course->shortname, true, array('context' => $coursecontext)) :
+                format_string($course->fullname, true, array('context' => $coursecontext));
+
+            $flat = new flat_navigation_node(navigation_node::create($coursename, $url), 0);
             $flat->key = 'coursehome';
 
             $courseformat = course_get_format($course);
index d25f29c..239dd99 100644 (file)
@@ -581,11 +581,23 @@ class behat_hooks extends behat_base {
         // The scenario title + the failed step text.
         // We want a i-am-the-scenario-title_i-am-the-failed-step.$filetype format.
         $filename = $scope->getFeature()->getTitle() . '_' . $scope->getStep()->getText();
-        $filename = preg_replace('/([^a-zA-Z0-9\_]+)/', '-', $filename);
 
-        // File name limited to 255 characters. Leaving 5 chars for line number and 4 chars for the file.
+        // As file name is limited to 255 characters. Leaving 5 chars for line number and 4 chars for the file.
         // extension as we allow .png for images and .html for DOM contents.
-        $filename = substr($filename, 0, 245) . '_' . $scope->getStep()->getLine() . '.' . $filetype;
+        $filenamelen = 245;
+
+        // Suffix suite name to faildump file, if it's not default suite.
+        $suitename = $scope->getSuite()->getName();
+        if ($suitename != 'default') {
+            $suitename = '_' . $suitename;
+            $filenamelen = $filenamelen - strlen($suitename);
+        } else {
+            // No need to append suite name for default.
+            $suitename = '';
+        }
+
+        $filename = preg_replace('/([^a-zA-Z0-9\_]+)/', '-', $filename);
+        $filename = substr($filename, 0, $filenamelen) . $suitename . '_' . $scope->getStep()->getLine() . '.' . $filetype;
 
         return array($dir, $filename);
     }
index 1ece799..de8b038 100644 (file)
@@ -67,6 +67,11 @@ class restore_forum_activity_structure_step extends restore_activity_structure_s
 
         $newitemid = $DB->insert_record('forum', $data);
         $this->apply_activity_instance($newitemid);
+
+        // Add current enrolled user subscriptions if necessary.
+        $data->id = $newitemid;
+        $ctx = context_module::instance($this->task->get_moduleid());
+        forum_instance_created($ctx, $data);
     }
 
     protected function process_forum_discussion($data) {
index bd1f62b..172d050 100644 (file)
@@ -91,7 +91,6 @@ if ($context->contextlevel == CONTEXT_COURSE) {
         print_error('notyourinstances', 'repository');
     }
     $user = $USER;
-    $PAGE->set_pagelayout('mydashboard');
 } else {
     print_error('invalidcontext');
 }
index 5ff6f84..32c99f4 100644 (file)
@@ -48,7 +48,7 @@ $PAGE->set_url('/user/files.php');
 $PAGE->set_context($context);
 $PAGE->set_title($title);
 $PAGE->set_heading(fullname($USER));
-$PAGE->set_pagelayout('mydashboard');
+$PAGE->set_pagelayout('standard');
 $PAGE->set_pagetype('user-files');
 
 $maxbytes = $CFG->userquota;