Merge branch 'MDL-62935-master' of git://github.com/bmbrands/moodle
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Tue, 24 Jul 2018 23:16:38 +0000 (01:16 +0200)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Tue, 24 Jul 2018 23:16:38 +0000 (01:16 +0200)
55 files changed:
admin/tool/behat/tests/manager_test.php [deleted file]
admin/tool/dataprivacy/tests/api_test.php
admin/tool/policy/tests/behat/consent.feature
auth/shibboleth/index_form.html
auth/shibboleth/login.php
blocks/myprofile/lang/en/block_myprofile.php
blocks/myprofile/lang/en/deprecated.txt
calendar/tests/behat/calendar.feature
comment/lib.php
enrol/manual/amd/build/form-potential-user-selector.min.js
enrol/manual/amd/src/form-potential-user-selector.js
enrol/manual/tests/behat/quickenrolment.feature [new file with mode: 0644]
enrol/self/lang/en/enrol_self.php
enrol/self/lib.php
enrol/self/settings.php
lang/en/admin.php
lang/en/calendar.php
lang/en/competency.php
lang/en/deprecated.txt
lang/en/media.php
lang/en/message.php
lang/en/moodle.php
lang/en/webservice.php
lib/amd/build/ajax.min.js
lib/amd/build/form-autocomplete.min.js
lib/amd/src/ajax.js
lib/amd/src/form-autocomplete.js
lib/behat/classes/behat_config_manager.php
lib/db/caches.php
lib/editor/atto/tests/behat/disablecontrol.feature [new file with mode: 0644]
lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js
lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js
lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js
lib/editor/atto/yui/src/editor/js/editor.js [changed mode: 0644->0755]
lib/editor/tests/fixtures/disable_control_example.php [new file with mode: 0644]
lib/editor/tests/fixtures/editor_form.php [new file with mode: 0644]
lib/editor/textarea/lib.php [changed mode: 0644->0755]
lib/editor/textarea/tests/behat/disablecontrol.feature [new file with mode: 0644]
lib/editor/tinymce/module.js [changed mode: 0644->0755]
lib/editor/tinymce/tests/behat/disablecontrol.feature [new file with mode: 0644]
lib/externallib.php
lib/form/form.js [changed mode: 0644->0755]
lib/tests/behat/behat_general.php
lib/tests/string_manager_standard_test.php
lib/upgrade.txt
mod/assign/lang/en/assign.php
mod/assign/lang/en/deprecated.txt
mod/data/lang/en/data.php
mod/data/lang/en/deprecated.txt
mod/feedback/lang/en/deprecated.txt
mod/feedback/lang/en/feedback.php
mod/wiki/lib.php
user/editlib.php
user/lib.php
version.php

diff --git a/admin/tool/behat/tests/manager_test.php b/admin/tool/behat/tests/manager_test.php
deleted file mode 100644 (file)
index 7b88c80..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-<?php
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
-
-/**
- * Unit tests for behat manager.
- *
- * @package   tool_behat
- * @copyright  2012 David Monllaó
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-defined('MOODLE_INTERNAL') || die();
-
-global $CFG;
-require_once($CFG->dirroot . '/' . $CFG->admin .'/tool/behat/locallib.php');
-require_once($CFG->libdir . '/behat/classes/util.php');
-require_once($CFG->libdir . '/behat/classes/behat_config_manager.php');
-
-/**
- * Behat manager tests.
- *
- * @package    tool_behat
- * @copyright  2012 David Monllaó
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class tool_behat_manager_testcase extends advanced_testcase {
-
-    /**
-     * behat_config_manager tests.
-     */
-    public function test_merge_configs() {
-
-        // Simple default config.
-        $array1 = array(
-            'the' => 'same',
-            'simple' => 'value',
-            'array' => array(
-                'one' => 'arrayvalue1',
-                'two' => 'arrayvalue2'
-            )
-        );
-
-        // Simple override.
-        $array2 = array(
-            'simple' => 'OVERRIDDEN1',
-            'array' => array(
-                'one' => 'OVERRIDDEN2'
-            ),
-            'newprofile' => array(
-                'anotherlevel' => array(
-                    'andanotherone' => array(
-                        'list1',
-                        'list2'
-                    )
-                )
-            )
-        );
-
-        $array = testable_behat_config_manager::merge_config($array1, $array2);
-        $this->assertDebuggingCalled("Use of merge_config is deprecated, please see behat_config_util");
-
-        // Overrides are applied.
-        $this->assertEquals('OVERRIDDEN1', $array['simple']);
-        $this->assertEquals('OVERRIDDEN2', $array['array']['one']);
-
-        // Other values are respected.
-        $this->assertNotEmpty($array['array']['two']);
-
-        // Completely new nodes are added.
-        $this->assertNotEmpty($array['newprofile']);
-        $this->assertNotEmpty($array['newprofile']['anotherlevel']['andanotherone']);
-        $this->assertEquals('list1', $array['newprofile']['anotherlevel']['andanotherone'][0]);
-        $this->assertEquals('list2', $array['newprofile']['anotherlevel']['andanotherone'][1]);
-
-        // Complex override changing vectors to scalars and scalars to vectors.
-        $array2 = array(
-            'simple' => array(
-                'simple' => 'should',
-                'be' => 'overridden',
-                'by' => 'this-array'
-            ),
-            'array' => 'one'
-        );
-
-        $array = testable_behat_config_manager::merge_config($array1, $array2);
-        $this->assertDebuggingCalled("Use of merge_config is deprecated, please see behat_config_util");
-
-        // Overrides applied.
-        $this->assertNotEmpty($array['simple']);
-        $this->assertNotEmpty($array['array']);
-        $this->assertTrue(is_array($array['simple']));
-        $this->assertFalse(is_array($array['array']));
-
-        // Other values are maintained.
-        $this->assertEquals('same', $array['the']);
-    }
-
-    /**
-     * behat_config_manager tests.
-     */
-    public function test_config_file_contents() {
-        global $CFG;
-
-        $this->resetAfterTest(true);
-
-        // Skip tests if behat is not installed.
-        $vendorpath = $CFG->dirroot . '/vendor';
-        if (!file_exists($vendorpath . '/autoload.php') || !is_dir($vendorpath . '/behat')) {
-            $this->markTestSkipped('Behat not installed.');
-        }
-
-        // Add some fake test url.
-        $CFG->behat_wwwroot = 'http://example.com/behat';
-
-        // To avoid user value at config.php level.
-        unset($CFG->behat_config);
-
-        // List.
-        $features = array(
-            'feature1',
-            'feature2',
-            'feature3'
-        );
-
-        // Associative array.
-        $stepsdefinitions = array(
-            'micarro' => '/me/lo/robaron',
-            'anoche' => '/cuando/yo/dormia'
-        );
-
-        $contents = testable_behat_config_manager::get_config_file_contents($features, $stepsdefinitions);
-        $this->assertDebuggingCalled("Use of get_config_file_contents is deprecated, please see behat_config_util");
-
-        // YAML decides when is is necessary to wrap strings between single quotes, so not controlled
-        // values like paths should not be asserted including the key name as they would depend on the
-        // directories values.
-        $this->assertContains($CFG->dirroot,
-            $contents['default']['extensions']['Moodle\BehatExtension']['moodledirroot']);
-
-        // Not quoted strings.
-        $this->assertEquals('/me/lo/robaron',
-            $contents['default']['extensions']['Moodle\BehatExtension']['steps_definitions']['micarro']);
-
-        // YAML uses single quotes to wrap URL strings.
-        $this->assertEquals($CFG->behat_wwwroot, $contents['default']['extensions']['Behat\MinkExtension']['base_url']);
-
-        // Lists.
-        $this->assertEquals('feature1', $contents['default']['suites']['default']['paths'][0]);
-        $this->assertEquals('feature3', $contents['default']['suites']['default']['paths'][2]);
-
-        unset($CFG->behat_wwwroot);
-    }
-
-}
-
-/**
- * Allows access to internal methods without exposing them.
- *
- * @package    tool_behat
- * @copyright  2012 David Monllaó
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class testable_behat_config_manager extends behat_config_manager {
-
-    /**
-     * Allow access to protected method
-     * @see parent::merge_config()
-     * @param mixed $config
-     * @param mixed $localconfig
-     * @return mixed
-     */
-    public static function merge_config($config, $localconfig) {
-        return parent::merge_config($config, $localconfig);
-    }
-
-    /**
-     * Allow access to protected method
-     * @see parent::get_config_file_contents()
-     * @param array $features
-     * @param array $stepsdefinitions
-     * @return string
-     */
-    public static function get_config_file_contents($features, $stepsdefinitions) {
-        return parent::get_config_file_contents($features, $stepsdefinitions);
-    }
-}
index f4a7a66..e5b6b16 100644 (file)
@@ -417,27 +417,20 @@ class tool_dataprivacy_api_testcase extends advanced_testcase {
      * @return array
      */
     public function get_data_requests_provider() {
-        $generator = new testing_data_generator();
-        $user1 = $generator->create_user();
-        $user2 = $generator->create_user();
-        $user3 = $generator->create_user();
-        $user4 = $generator->create_user();
-        $user5 = $generator->create_user();
-        $users = [$user1, $user2, $user3, $user4, $user5];
         $completeonly = [api::DATAREQUEST_STATUS_COMPLETE];
         $completeandcancelled = [api::DATAREQUEST_STATUS_COMPLETE, api::DATAREQUEST_STATUS_CANCELLED];
 
         return [
             // Own data requests.
-            [$users, $user1, false, $completeonly],
+            ['user', false, $completeonly],
             // Non-DPO fetching all requets.
-            [$users, $user2, true, $completeonly],
+            ['user', true, $completeonly],
             // Admin fetching all completed and cancelled requests.
-            [$users, get_admin(), true, $completeandcancelled],
+            ['dpo', true, $completeandcancelled],
             // Admin fetching all completed requests.
-            [$users, get_admin(), true, $completeonly],
+            ['dpo', true, $completeonly],
             // Guest fetching all requests.
-            [$users, guest_user(), true, $completeonly],
+            ['guest', true, $completeonly],
         ];
     }
 
@@ -445,12 +438,31 @@ class tool_dataprivacy_api_testcase extends advanced_testcase {
      * Test for api::get_data_requests()
      *
      * @dataProvider get_data_requests_provider
-     * @param stdClass[] $users Array of users to create data requests for.
-     * @param stdClass $loggeduser The user logging in.
+     * @param string $usertype The type of the user logging in.
      * @param boolean $fetchall Whether to fetch all records.
      * @param int[] $statuses Status filters.
      */
-    public function test_get_data_requests($users, $loggeduser, $fetchall, $statuses) {
+    public function test_get_data_requests($usertype, $fetchall, $statuses) {
+        $generator = new testing_data_generator();
+        $user1 = $generator->create_user();
+        $user2 = $generator->create_user();
+        $user3 = $generator->create_user();
+        $user4 = $generator->create_user();
+        $user5 = $generator->create_user();
+        $users = [$user1, $user2, $user3, $user4, $user5];
+
+        switch ($usertype) {
+            case 'user':
+                $loggeduser = $user1;
+                break;
+            case 'dpo':
+                $loggeduser = get_admin();
+                break;
+            case 'guest':
+                $loggeduser = guest_user();
+                break;
+        }
+
         $comment = 'Data %s request comment by user %d';
         $exportstring = helper::get_shortened_request_type_string(api::DATAREQUEST_TYPE_EXPORT);
         $deletionstring = helper::get_shortened_request_type_string(api::DATAREQUEST_TYPE_DELETE);
index 6c504eb..d345b23 100644 (file)
@@ -460,6 +460,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
       | This privacy policy | 1    |          | full text3 | short text3 | active   | loggedin |
       | This guests policy  | 0    |          | full text4 | short text4 | active   | guest    |
     And I am on site homepage
+    And I change window size to "large"
     And I follow "Log in"
     When I press "Log in as a guest"
     Then I should see "If you continue browsing this website, you agree to our policies"
index 4d7e7df..144c1fd 100644 (file)
@@ -71,8 +71,8 @@ if ($show_instructions) {
 <?php     if (is_enabled_auth('none')) { // instructions override the rest for security reasons
               print_string("loginstepsnone");
           } else if ($CFG->registerauth == 'email') {
-              if (!empty($CFG->auth_instructions)) {
-                  echo format_text($CFG->auth_instructions);
+              if (!empty($config->auth_instructions)) {
+                  echo format_text($config->auth_instructions);
               } else {
                   print_string("loginsteps", "", "signup.php");
               } ?>
@@ -82,14 +82,14 @@ if ($show_instructions) {
                    </form>
                  </div>
 <?php     } else if (!empty($CFG->registerauth)) {
-              echo format_text($CFG->auth_instructions); ?>
+              echo format_text($config->auth_instructions); ?>
               <div class="signupform">
                 <form action="../../login/signup.php" method="get" id="signup">
                 <div><input type="submit" value="<?php print_string("startsignup") ?>" /></div>
                 </form>
               </div>
 <?php     } else {
-              echo format_text($CFG->auth_instructions);
+              echo format_text($config->auth_instructions);
           } ?>
       </div>
     </div>
index 721af80..2ed931a 100644 (file)
 
     $loginurl = (!empty($CFG->alternateloginurl)) ? $CFG->alternateloginurl : '';
 
-
-    if (!empty($CFG->registerauth) or is_enabled_auth('none') or !empty($CFG->auth_instructions)) {
+    $config = get_config('auth_shibboleth');
+    if (!empty($CFG->registerauth) or is_enabled_auth('none') or !empty($config->auth_instructions)) {
         $show_instructions = true;
     } else {
         $show_instructions = false;
     }
 
-    // Set SAML domain cookie
-    $config = get_config('auth_shibboleth');
-
-
     $IdPs = get_idp_list($config->organization_selection);
     if (isset($_POST['idp']) && isset($IdPs[$_POST['idp']])){
         $selectedIdP = $_POST['idp'];
index b7de027..5d886c2 100644 (file)
@@ -46,6 +46,3 @@ $string['myprofile:myaddinstance'] = 'Add a new logged in user block to Dashboar
 $string['myprofile_settings'] = 'Visible user information';
 $string['pluginname'] = 'Logged in user';
 $string['privacy:metadata'] = 'The Logged in user block only shows information about the logged in user and does not store data itself.';
-
-// Deprecated since Moodle 3.2.
-$string['display_un'] = 'Display name';
index 5603daa..5483edb 100644 (file)
@@ -170,8 +170,8 @@ Feature: Perform basic calendar functionality
     And I click on "New event" "button"
     When I click on "Save" "button"
     Then I should see "Required"
-    And I am on site homepage
-    And I follow "Calendar"
+    And I am on homepage
+    And I follow "This month"
     And I click on "New event" "button"
     And I set the field "Type of event" to "Course"
     When I click on "Save" "button"
index 9034c84..07f7a5b 100644 (file)
@@ -493,7 +493,8 @@ class comment {
                 $textareaattrs = array(
                     'name' => 'content',
                     'rows' => 2,
-                    'id' => 'dlg-content-'.$this->cid
+                    'id' => 'dlg-content-'.$this->cid,
+                    'aria-label' => get_string('addcomment')
                 );
                 if (!$this->fullwidth) {
                     $textareaattrs['cols'] = '20';
index d697a8b..2ced5d6 100644 (file)
Binary files a/enrol/manual/amd/build/form-potential-user-selector.min.js and b/enrol/manual/amd/build/form-potential-user-selector.min.js differ
index 49bdcbf..066f59d 100644 (file)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-define(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) {
+define(['jquery', 'core/ajax', 'core/templates', 'core/str'], function($, Ajax, Templates, Str) {
+
+    /** @var {Number} Maximum number of users to show. */
+    var MAXUSERS = 100;
 
     return /** @alias module:enrol_manual/form-potential-user-selector */ {
 
         processResults: function(selector, results) {
             var users = [];
-            $.each(results, function(index, user) {
-                users.push({
-                    value: user.id,
-                    label: user._label
+            if ($.isArray(results)) {
+                $.each(results, function(index, user) {
+                    users.push({
+                        value: user.id,
+                        label: user._label
+                    });
                 });
-            });
-            return users;
+                return users;
+
+            } else {
+                return results;
+            }
         },
 
         transport: function(selector, query, success, failure) {
@@ -57,7 +65,7 @@ define(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) {
                     search: query,
                     searchanywhere: true,
                     page: 0,
-                    perpage: 30
+                    perpage: MAXUSERS + 1
                 }
             }]);
 
@@ -65,30 +73,38 @@ define(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) {
                 var promises = [],
                     i = 0;
 
-                // Render the label.
-                $.each(results, function(index, user) {
-                    var ctx = user,
-                        identity = [];
-                    $.each(['idnumber', 'email', 'phone1', 'phone2', 'department', 'institution'], function(i, k) {
-                        if (typeof user[k] !== 'undefined' && user[k] !== '') {
-                            ctx.hasidentity = true;
-                            identity.push(user[k]);
-                        }
+                if (results.length <= MAXUSERS) {
+                    // Render the label.
+                    $.each(results, function(index, user) {
+                        var ctx = user,
+                            identity = [];
+                        $.each(['idnumber', 'email', 'phone1', 'phone2', 'department', 'institution'], function(i, k) {
+                            if (typeof user[k] !== 'undefined' && user[k] !== '') {
+                                ctx.hasidentity = true;
+                                identity.push(user[k]);
+                            }
+                        });
+                        ctx.identity = identity.join(', ');
+                        promises.push(Templates.render('enrol_manual/form-user-selector-suggestion', ctx));
                     });
-                    ctx.identity = identity.join(', ');
-                    promises.push(Templates.render('enrol_manual/form-user-selector-suggestion', ctx));
-                });
 
-                // Apply the label to the results.
-                return $.when.apply($.when, promises).then(function() {
-                    var args = arguments;
-                    $.each(results, function(index, user) {
-                        user._label = args[i];
-                        i++;
+                    // Apply the label to the results.
+                    return $.when.apply($.when, promises).then(function() {
+                        var args = arguments;
+                        $.each(results, function(index, user) {
+                            user._label = args[i];
+                            i++;
+                        });
+                        success(results);
+                        return;
                     });
-                    success(results);
-                    return;
-                });
+
+                } else {
+                    return Str.get_string('toomanyuserstoshow', 'core', '>' + MAXUSERS).then(function(toomanyuserstoshow) {
+                        success(toomanyuserstoshow);
+                        return;
+                    });
+                }
 
             }).fail(failure);
         }
diff --git a/enrol/manual/tests/behat/quickenrolment.feature b/enrol/manual/tests/behat/quickenrolment.feature
new file mode 100644 (file)
index 0000000..c5e3549
--- /dev/null
@@ -0,0 +1,155 @@
+@enrol @enrol_manual
+Feature: Teacher can search and enrol users one by one into the course
+  In order to quickly enrol particular students into my course
+  As a teacher
+  I can search for the students and enrol them into the course
+
+  Background:
+    Given the following "users" exist:
+      | username    | firstname | lastname | email                   |
+      | teacher001  | Teacher   | 001      | teacher001@example.com  |
+      | student001  | Student   | 001      | student001@example.com  |
+      | student002  | Student   | 002      | student002@example.com  |
+      | student003  | Student   | 003      | student003@example.com  |
+      | student004  | Student   | 004      | student004@example.com  |
+      | student005  | Student   | 005      | student005@example.com  |
+      | student006  | Student   | 006      | student006@example.com  |
+      | student007  | Student   | 007      | student007@example.com  |
+      | student008  | Student   | 008      | student008@example.com  |
+      | student009  | Student   | 009      | student009@example.com  |
+      | student010  | Student   | 010      | student010@example.com  |
+      | student011  | Student   | 011      | student011@example.com  |
+      | student012  | Student   | 012      | student012@example.com  |
+      | student013  | Student   | 013      | student013@example.com  |
+      | student014  | Student   | 014      | student014@example.com  |
+      | student015  | Student   | 015      | student015@example.com  |
+      | student016  | Student   | 016      | student016@example.com  |
+      | student017  | Student   | 017      | student017@example.com  |
+      | student018  | Student   | 018      | student018@example.com  |
+      | student019  | Student   | 019      | student019@example.com  |
+      | student020  | Student   | 020      | student020@example.com  |
+      | student021  | Student   | 021      | student021@example.com  |
+      | student022  | Student   | 022      | student022@example.com  |
+      | student023  | Student   | 023      | student023@example.com  |
+      | student024  | Student   | 024      | student024@example.com  |
+      | student025  | Student   | 025      | student025@example.com  |
+      | student026  | Student   | 026      | student026@example.com  |
+      | student027  | Student   | 027      | student027@example.com  |
+      | student028  | Student   | 028      | student028@example.com  |
+      | student029  | Student   | 029      | student029@example.com  |
+      | student030  | Student   | 030      | student030@example.com  |
+      | student031  | Student   | 031      | student031@example.com  |
+      | student032  | Student   | 032      | student032@example.com  |
+      | student033  | Student   | 033      | student033@example.com  |
+      | student034  | Student   | 034      | student034@example.com  |
+      | student035  | Student   | 035      | student035@example.com  |
+      | student036  | Student   | 036      | student036@example.com  |
+      | student037  | Student   | 037      | student037@example.com  |
+      | student038  | Student   | 038      | student038@example.com  |
+      | student039  | Student   | 039      | student039@example.com  |
+      | student040  | Student   | 040      | student040@example.com  |
+      | student041  | Student   | 041      | student041@example.com  |
+      | student042  | Student   | 042      | student042@example.com  |
+      | student043  | Student   | 043      | student043@example.com  |
+      | student044  | Student   | 044      | student044@example.com  |
+      | student045  | Student   | 045      | student045@example.com  |
+      | student046  | Student   | 046      | student046@example.com  |
+      | student047  | Student   | 047      | student047@example.com  |
+      | student048  | Student   | 048      | student048@example.com  |
+      | student049  | Student   | 049      | student049@example.com  |
+      | student050  | Student   | 050      | student050@example.com  |
+      | student051  | Student   | 051      | student051@example.com  |
+      | student052  | Student   | 052      | student052@example.com  |
+      | student053  | Student   | 053      | student053@example.com  |
+      | student054  | Student   | 054      | student054@example.com  |
+      | student055  | Student   | 055      | student055@example.com  |
+      | student056  | Student   | 056      | student056@example.com  |
+      | student057  | Student   | 057      | student057@example.com  |
+      | student058  | Student   | 058      | student058@example.com  |
+      | student059  | Student   | 059      | student059@example.com  |
+      | student060  | Student   | 060      | student060@example.com  |
+      | student061  | Student   | 061      | student061@example.com  |
+      | student062  | Student   | 062      | student062@example.com  |
+      | student063  | Student   | 063      | student063@example.com  |
+      | student064  | Student   | 064      | student064@example.com  |
+      | student065  | Student   | 065      | student065@example.com  |
+      | student066  | Student   | 066      | student066@example.com  |
+      | student067  | Student   | 067      | student067@example.com  |
+      | student068  | Student   | 068      | student068@example.com  |
+      | student069  | Student   | 069      | student069@example.com  |
+      | student070  | Student   | 070      | student070@example.com  |
+      | student071  | Student   | 071      | student071@example.com  |
+      | student072  | Student   | 072      | student072@example.com  |
+      | student073  | Student   | 073      | student073@example.com  |
+      | student074  | Student   | 074      | student074@example.com  |
+      | student075  | Student   | 075      | student075@example.com  |
+      | student076  | Student   | 076      | student076@example.com  |
+      | student077  | Student   | 077      | student077@example.com  |
+      | student078  | Student   | 078      | student078@example.com  |
+      | student079  | Student   | 079      | student079@example.com  |
+      | student080  | Student   | 080      | student080@example.com  |
+      | student081  | Student   | 081      | student081@example.com  |
+      | student082  | Student   | 082      | student082@example.com  |
+      | student083  | Student   | 083      | student083@example.com  |
+      | student084  | Student   | 084      | student084@example.com  |
+      | student085  | Student   | 085      | student085@example.com  |
+      | student086  | Student   | 086      | student086@example.com  |
+      | student087  | Student   | 087      | student087@example.com  |
+      | student088  | Student   | 088      | student088@example.com  |
+      | student089  | Student   | 089      | student089@example.com  |
+      | student090  | Student   | 090      | student090@example.com  |
+      | student091  | Student   | 091      | student091@example.com  |
+      | student092  | Student   | 092      | student092@example.com  |
+      | student093  | Student   | 093      | student093@example.com  |
+      | student094  | Student   | 094      | student094@example.com  |
+      | student095  | Student   | 095      | student095@example.com  |
+      | student096  | Student   | 096      | student096@example.com  |
+      | student097  | Student   | 097      | student097@example.com  |
+      | student098  | Student   | 098      | student098@example.com  |
+      | student099  | Student   | 099      | student099@example.com  |
+    And the following "courses" exist:
+      | fullname    | shortname |
+      | Course 001  | C001      |
+    And the following "course enrolments" exist:
+      | user        | course    | role            |
+      | teacher001  | C001      | editingteacher  |
+    And I log in as "teacher001"
+    And I am on "Course 001" course homepage
+
+  @javascript
+  Scenario: Teacher can search and enrol one particular student
+    Given I navigate to course participants
+    And I press "Enrol users"
+    When I set the field "Select users" to "student001"
+    And I should see "Student 001"
+    And I click on "Enrol users" "button" in the "Enrol users" "dialogue"
+    Then I should see "Active" in the "Student 001" "table_row"
+
+  @javascript
+  Scenario: Searching for a non-existing user
+    Given I navigate to course participants
+    And I press "Enrol users"
+    And I set the field "Select users" to "qwertyuiop"
+    And I click on ".form-autocomplete-downarrow" "css_element" in the "Select users" "form_row"
+    Then I should see "No suggestions"
+
+  @javascript
+  Scenario: If there are less than 100 matching users, all are displayed for selection
+    Given I navigate to course participants
+    And I press "Enrol users"
+    When I set the field "Select users" to "example.com"
+    And I click on ".form-autocomplete-downarrow" "css_element" in the "Select users" "form_row"
+    And I click on "Student 099" item in the autocomplete list
+    Then I should see "Student 099"
+
+  @javascript
+  Scenario: If there are more than 100 matching users, inform there are too many.
+    Given the following "users" exist:
+      | username    | firstname | lastname | email                   |
+      | student100  | Student   | 100      | student100@example.com  |
+      | student101  | Student   | 101      | student101@example.com  |
+    And I navigate to course participants
+    And I press "Enrol users"
+    When I set the field "Select users" to "example.com"
+    And I click on ".form-autocomplete-downarrow" "css_element" in the "Select users" "form_row"
+    Then I should see "Too many users (>100) to show"
index a52720f..509f04f 100644 (file)
@@ -65,6 +65,8 @@ $string['expirymessageenrolledbody'] = 'Dear {$a->user},
 This is a notification that your enrolment in the course \'{$a->course}\' is due to expire on {$a->timeend}.
 
 If you need help, please contact {$a->enroller}.';
+$string['expirynotifyall'] = 'Teacher and enrolled user';
+$string['expirynotifyenroller'] = 'Teacher only';
 $string['groupkey'] = 'Use group enrolment keys';
 $string['groupkey_desc'] = 'Use group enrolment keys by default.';
 $string['groupkey_help'] = 'In addition to restricting access to the course to only those who know the key, use of group enrolment keys means users are automatically added to groups when they enrol in the course.
index 87e9c14..bac3887 100644 (file)
@@ -657,8 +657,8 @@ class enrol_self_plugin extends enrol_plugin {
      */
     protected function get_expirynotify_options() {
         $options = array(0 => get_string('no'),
-                         1 => get_string('expirynotifyenroller', 'core_enrol'),
-                         2 => get_string('expirynotifyall', 'core_enrol'));
+                         1 => get_string('expirynotifyenroller', 'enrol_self'),
+                         2 => get_string('expirynotifyall', 'enrol_self'));
         return $options;
     }
 
index 25dadf0..6375ea2 100644 (file)
@@ -85,7 +85,9 @@ if ($ADMIN->fulltree) {
     $settings->add(new admin_setting_configduration('enrol_self/enrolperiod',
         get_string('enrolperiod', 'enrol_self'), get_string('enrolperiod_desc', 'enrol_self'), 0));
 
-    $options = array(0 => get_string('no'), 1 => get_string('expirynotifyenroller', 'core_enrol'), 2 => get_string('expirynotifyall', 'core_enrol'));
+    $options = array(0 => get_string('no'),
+                     1 => get_string('expirynotifyenroller', 'enrol_self'),
+                     2 => get_string('expirynotifyall', 'enrol_self'));
     $settings->add(new admin_setting_configselect('enrol_self/expirynotify',
         get_string('expirynotify', 'core_enrol'), get_string('expirynotify_help', 'core_enrol'), 0, $options));
 
index cf656d3..6c38f65 100644 (file)
@@ -1301,8 +1301,7 @@ $string['cachesession'] = 'Session cache';
 $string['cachesessionhelp'] = 'User specific cache that expires when the user\'s session ends. Designed to alleviate session bloat/strain.';
 $string['cacheapplication'] = 'Application cache';
 $string['cacheapplicationhelp'] = 'Cached items are shared among all users and expire by a determined time to live (ttl).';
-// Deprecated since Moodle 3.2.
-$string['mobile'] = 'Mobile';
+
 // Deprecated since Moodle 3.3.
 $string['loginpasswordautocomplete'] = 'Prevent password autocompletion on login form';
 $string['loginpasswordautocomplete_help'] = 'If enabled, users are not allowed to save their account password in their browser.';
index d93fb9c..6003668 100644 (file)
@@ -266,9 +266,6 @@ $string['when'] = 'When';
 $string['yesterday'] = 'Yesterday';
 $string['youcandeleteallrepeats'] = 'This event is part of a repeating event series. You can delete this event only, or all {$a} events in the series at once.';
 
-// Deprecated since Moodle 3.2.
-$string['for'] = 'for';
-
 // Deprecated since Moodle 3.4.
 $string['quickdownloadcalendar'] = 'Quick download / subscribe to calendar';
 $string['ical'] = 'iCal';
index 606cac2..ca114fc 100644 (file)
@@ -200,6 +200,3 @@ $string['usercompetencystatus_idle'] = 'Idle';
 $string['usercompetencystatus_inreview'] = 'In review';
 $string['usercompetencystatus_waitingforreview'] = 'Waiting for review';
 $string['userplans'] = 'Learning plans';
-
-// Deprecated since Moodle 3.2.
-$string['invalidpersistent'] = 'Invalid persistent';
index db1cf82..2297072 100644 (file)
@@ -5,34 +5,7 @@ myfilesmanage,core
 mypreferences,core_grades
 myprofile,core
 viewallmyentries,core_blog
-modchooserenable,core
-modchooserdisable,core
-invalidpersistent,core_competency
 revealpassword,core_form
-mediasettings,core_media
-legacyheading,core_media
-legacyheading_desc,core_media
-mobile,core_admin
-for,core_calendar
-context,core_message
-discussion,core_message
-emptysearchstring,core_message
-formorethan,core_message
-keywords,core_message
-messagehistory,core_message
-newsearch,core_message
-nosearchresults,core_message
-onlymycourses,core_message
-pagerefreshes,core_message
-page-message-x,core_message
-recent,core_message
-savemysettings,core_message
-search,core_message
-settingssaved,core_message
-strftimedaydatetime,core_message
-timenosee,core_message
-timesent,core_message
-userssearchresults,core_message
 loginpasswordautocomplete,core_admin
 loginpasswordautocomplete_help,core_admin
 deletecomment,core
index 03fe641..76372d5 100644 (file)
@@ -36,8 +36,3 @@ Where two players support the same format, enabling both increases compatibility
 $string['privacy:metadata'] = 'Media embedding does not store any personal data.';
 $string['supports'] = 'Supports';
 $string['videoextensions'] = 'Video: {$a}';
-
-// Deprecated since Moodle 3.2.
-$string['mediasettings'] = 'Media embedding';
-$string['legacyheading'] = 'Legacy media players';
-$string['legacyheading_desc'] = 'These players are not frequently used on the Web and require browser plugins that are less widely installed.';
index 93ec3a2..917d352 100644 (file)
@@ -76,7 +76,6 @@ $string['messagingdisabled'] = 'Messaging is disabled on this site, emails will
 $string['newonlymsg'] = 'Show only new';
 $string['newmessage'] = 'New message';
 $string['newmessagesearch'] = 'Select or search for a contact to send a new message.';
-$string['newsearch'] = 'New search';
 $string['noframesjs'] = 'Use more accessible interface';
 $string['nocontacts'] = 'No contacts';
 $string['nomessages'] = 'No messages';
@@ -180,24 +179,3 @@ $string['viewnotificationresource'] = 'Go to: {$a}';
 $string['viewunreadmessageswith'] = 'View unread messages with {$a}';
 $string['writeamessage'] = 'Write a message...';
 $string['you'] = 'You:';
-
-// Deprecated since Moodle 3.2.
-$string['context'] = 'context';
-$string['discussion'] = 'Discussion';
-$string['emptysearchstring'] = 'You must search for something';
-$string['formorethan'] = 'For more than';
-$string['keywords'] = 'Keywords';
-$string['messagehistory'] = 'Message history';
-$string['newsearch'] = 'New search';
-$string['nosearchresults'] = 'There were no results from your search';
-$string['onlymycourses'] = 'Only in my courses';
-$string['pagerefreshes'] = 'This page refreshes automatically every {$a} seconds';
-$string['page-message-x'] = 'Any message pages';
-$string['recent'] = 'Recent';
-$string['savemysettings'] = 'Save my settings';
-$string['search'] = 'Search';
-$string['settingssaved'] = 'Your settings have been saved';
-$string['strftimedaydatetime'] = '%A, %d %B %Y, %I:%M %p';
-$string['timenosee'] = 'Minutes since I was last seen online';
-$string['timesent'] = 'Time sent';
-$string['userssearchresults'] = 'Users found: {$a}';
index e3521f0..84b7020 100644 (file)
@@ -2205,10 +2205,6 @@ $string['yourwordforx'] = 'Your word for \'{$a}\'';
 $string['zippingbackup'] = 'Zipping backup';
 $string['deprecatedeventname'] = '{$a} (no longer in use)';
 
-// Deprecated since Moodle 3.2.
-$string['modchooserenable'] = 'Activity chooser on';
-$string['modchooserdisable'] = 'Activity chooser off';
-
 // Deprecated since Moodle 3.3.
 $string['deletecomment'] = 'Delete this comment';
 $string['sectionusedefaultname'] = 'Use default section name';
index b6cf1de..1aac870 100644 (file)
@@ -186,6 +186,7 @@ $string['service'] = 'Service';
 $string['servicehelpexplanation'] = 'A service is a set of functions. A service can be accessed by all users or just specified users.';
 $string['servicename'] = 'Service name';
 $string['servicenotavailable'] = 'Web service is not available (it doesn\'t exist or might be disabled)';
+$string['servicerequireslogin'] = 'Web service is not available (the session has been logged out or has expired)';
 $string['servicesbuiltin'] = 'Built-in services';
 $string['servicescustom'] = 'Custom services';
 $string['serviceusers'] = 'Authorised users';
index 8247f32..a585b99 100644 (file)
Binary files a/lib/amd/build/ajax.min.js and b/lib/amd/build/ajax.min.js differ
index 954829b..c59dc5d 100644 (file)
Binary files a/lib/amd/build/form-autocomplete.min.js and b/lib/amd/build/form-autocomplete.min.js differ
index 481247c..088deca 100644 (file)
@@ -25,7 +25,7 @@
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @since      2.9
  */
-define(['jquery', 'core/config', 'core/log'], function($, config, Log) {
+define(['jquery', 'core/config', 'core/log', 'core/url'], function($, config, Log, URL) {
 
     // Keeps track of when the user leaves the page so we know not to show an error.
     var unloading = false;
@@ -79,9 +79,14 @@ define(['jquery', 'core/config', 'core/log'], function($, config, Log) {
         }
         // Something failed, reject the remaining promises.
         if (exception !== null) {
-            for (; i < requests.length; i++) {
-                request = requests[i];
-                request.deferred.reject(exception);
+            // If the user isn't doing anything too important, redirect to the login page.
+            if (exception.errorcode === "servicerequireslogin") {
+                window.location = URL.relativeUrl("/login/index.php");
+            } else {
+                for (; i < requests.length; i++) {
+                    request = requests[i];
+                    request.deferred.reject(exception);
+                }
             }
         }
     };
index ea2fab3..afe6e3f 100644 (file)
@@ -355,7 +355,10 @@ define(['jquery', 'core/log', 'core/str', 'core/templates', 'core/notification']
             });
             // If we found any matches, show the list.
             inputElement.attr('aria-expanded', true);
-            if (matchingElements) {
+            if (originalSelect.attr('data-notice')) {
+                // Display a notice rather than actual suggestions.
+                suggestionsElement.html(originalSelect.attr('data-notice'));
+            } else if (matchingElements) {
                 // We only activate the first item in the list if tags is false,
                 // because otherwise "Enter" would select the first item, instead of
                 // creating a new tag.
@@ -512,15 +515,21 @@ define(['jquery', 'core/log', 'core/str', 'core/templates', 'core/notification']
                 var option = $('<option>');
                 originalSelect.append(option);
             }
-            // And add all the new ones returned from ajax.
-            $.each(processedResults, function(resultIndex, result) {
-                if (existingValues.indexOf(String(result.value)) === -1) {
-                    var option = $('<option>');
-                    option.append(result.label);
-                    option.attr('value', result.value);
-                    originalSelect.append(option);
-                }
-            });
+            if ($.isArray(processedResults)) {
+                // Add all the new ones returned from ajax.
+                $.each(processedResults, function(resultIndex, result) {
+                    if (existingValues.indexOf(String(result.value)) === -1) {
+                        var option = $('<option>');
+                        option.append(result.label);
+                        option.attr('value', result.value);
+                        originalSelect.append(option);
+                    }
+                });
+                originalSelect.attr('data-notice', '');
+            } else {
+                // The AJAX handler returned a string instead of the array.
+                originalSelect.attr('data-notice', processedResults);
+            }
             // Update the list of suggestions now from the new values in the select list.
             updateSuggestions(options, state, '', originalSelect);
             M.util.js_complete(pendingKey);
index 7285e39..75c727f 100644 (file)
@@ -132,37 +132,19 @@ class behat_config_manager {
     }
 
     /**
-     * Search feature files for set of tags.
-     *
-     * @param array $features set of feature files.
-     * @param string $tags list of tags (currently support && only.)
-     * @return array filtered list of feature files with tags.
-     * @deprecated since 3.2 MDL-55072 - please use behat_config_util.php
-     * @todo MDL-55365 This will be deleted in Moodle 3.6.
+     * @deprecated since 3.2 - please use behat_config_util.php
      */
-    public static function get_features_with_tags($features, $tags) {
-
-        debugging('Use of get_features_with_tags is deprecated, please see behat_config_util', DEBUG_DEVELOPER);
-        return self::get_behat_config_util()->filtered_features_with_tags($features, $tags);
+    public static function get_features_with_tags() {
+        throw new coding_exception('get_features_with_tags() can not be used anymore. ' .
+            'Please use behat_config_util instead.');
     }
 
     /**
-     * Gets the list of Moodle steps definitions
-     *
-     * Class name as a key and the filepath as value
-     *
-     * Externalized from update_config_file() to use
-     * it from the steps definitions web interface
-     *
-     * @return array
-     * @deprecated since 3.2 MDL-55072 - please use behat_config_util.php
-     * @todo MDL-55365 This will be deleted in Moodle 3.6.
+     * @deprecated since 3.2 - please use behat_config_util.php
      */
     public static function get_components_steps_definitions() {
-
-        debugging('Use of get_components_steps_definitions is deprecated, please see behat_config_util::get_components_contexts',
-            DEBUG_DEVELOPER);
-        return self::get_behat_config_util()->get_components_contexts();
+        throw new coding_exception('get_components_steps_definitions() can not be used anymore. ' .
+            'Please use behat_config_util instead.');
     }
 
     /**
@@ -321,160 +303,59 @@ class behat_config_manager {
     }
 
     /**
-     * Behat config file specifing the main context class,
-     * the required Behat extensions and Moodle test wwwroot.
-     *
-     * @param array $features The system feature files
-     * @param array $stepsdefinitions The system steps definitions
-     * @return string
-     * @deprecated since 3.2 MDL-55072 - please use behat_config_util.php
-     * @todo MDL-55365 This will be deleted in Moodle 3.6.
+     * @deprecated since 3.2 - please use behat_config_util.php
      */
-    protected static function get_config_file_contents($features, $stepsdefinitions) {
-
-        debugging('Use of get_config_file_contents is deprecated, please see behat_config_util', DEBUG_DEVELOPER);
-        return self::get_behat_config_util()->get_config_file_contents($features, $stepsdefinitions);
+    protected static function get_config_file_contents() {
+        throw new coding_exception('get_config_file_contents() can not be used anymore. ' .
+            'Please use behat_config_util instead.');
     }
 
     /**
-     * Parse $CFG->behat_config and return the array with required config structure for behat.yml
-     *
-     * @param string $profile profile name
-     * @param array $values values for profile
-     * @return array
-     * @deprecated since 3.2 MDL-55072 - please use behat_config_util.php
-     * @todo MDL-55365 This will be deleted in Moodle 3.6.
+     * @deprecated since 3.2 - please use behat_config_util.php
      */
-    protected static function merge_behat_config($profile, $values) {
-
-        debugging('Use of merge_behat_config is deprecated, please see behat_config_util', DEBUG_DEVELOPER);
-        self::get_behat_config_util()->get_behat_config_for_profile($profile, $values);
+    protected static function merge_behat_config() {
+        throw new coding_exception('merge_behat_config() can not be used anymore. ' .
+            'Please use behat_config_util instead.');
     }
 
     /**
-     * Parse $CFG->behat_profile and return the array with required config structure for behat.yml.
-     *
-     * $CFG->behat_profiles = array(
-     *     'profile' = array(
-     *         'browser' => 'firefox',
-     *         'tags' => '@javascript',
-     *         'wd_host' => 'http://127.0.0.1:4444/wd/hub',
-     *         'capabilities' => array(
-     *             'platform' => 'Linux',
-     *             'version' => 44
-     *         )
-     *     )
-     * );
-     *
-     * @param string $profile profile name
-     * @param array $values values for profile.
-     * @return array
+     * @deprecated since 3.2 - please use behat_config_util.php
      */
-    protected static function get_behat_profile($profile, $values) {
-        // Values should be an array.
-        if (!is_array($values)) {
-            return array();
-        }
-
-        // Check suite values.
-        $behatprofilesuites = array();
-        // Fill tags information.
-        if (isset($values['tags'])) {
-            $behatprofilesuites = array(
-                'suites' => array(
-                    'default' => array(
-                        'filters' => array(
-                            'tags' => $values['tags'],
-                        )
-                    )
-                )
-            );
-        }
-
-        // Selenium2 config values.
-        $behatprofileextension = array();
-        $seleniumconfig = array();
-        if (isset($values['browser'])) {
-            $seleniumconfig['browser'] = $values['browser'];
-        }
-        if (isset($values['wd_host'])) {
-            $seleniumconfig['wd_host'] = $values['wd_host'];
-        }
-        if (isset($values['capabilities'])) {
-            $seleniumconfig['capabilities'] = $values['capabilities'];
-        }
-        if (!empty($seleniumconfig)) {
-            $behatprofileextension = array(
-                'extensions' => array(
-                    'Behat\MinkExtension' => array(
-                        'selenium2' => $seleniumconfig,
-                    )
-                )
-            );
-        }
-
-        return array($profile => array_merge($behatprofilesuites, $behatprofileextension));
+    protected static function get_behat_profile() {
+        throw new coding_exception('get_behat_profile() can not be used anymore. ' .
+            'Please use behat_config_util instead.');
     }
 
     /**
-     * Attempt to split feature list into fairish buckets using timing information, if available.
-     * Simply add each one to lightest buckets until all files allocated.
-     * PGA = Profile Guided Allocation. I made it up just now.
-     * CAUTION: workers must agree on allocation, do not be random anywhere!
-     *
-     * @param array $features Behat feature files array
-     * @param int $nbuckets Number of buckets to divide into
-     * @param int $instance Index number of this instance
-     * @return array Feature files array, sorted into allocations
+     * @deprecated since 3.2 - please use behat_config_util.php
      */
-    protected static function profile_guided_allocate($features, $nbuckets, $instance) {
-
-        debugging('Use of profile_guided_allocate is deprecated, please see behat_config_util', DEBUG_DEVELOPER);
-        return self::get_behat_config_util()->profile_guided_allocate($features, $nbuckets, $instance);
+    protected static function profile_guided_allocate() {
+        throw new coding_exception('profile_guided_allocate() can not be used anymore. ' .
+            'Please use behat_config_util instead.');
     }
 
     /**
-     * Overrides default config with local config values
-     *
-     * array_merge does not merge completely the array's values
-     *
-     * @param mixed $config The node of the default config
-     * @param mixed $localconfig The node of the local config
-     * @return mixed The merge result
-     * @deprecated since 3.2 MDL-55072 - please use behat_config_util.php
-     * @todo MDL-55365 This will be deleted in Moodle 3.6.
+     * @deprecated since 3.2 - please use behat_config_util.php
      */
-    protected static function merge_config($config, $localconfig) {
-
-        debugging('Use of merge_config is deprecated, please see behat_config_util', DEBUG_DEVELOPER);
-        return self::get_behat_config_util()->merge_config($config, $localconfig);
+    protected static function merge_config() {
+        throw new coding_exception('merge_config() can not be used anymore. ' .
+            'Please use behat_config_util instead.');
     }
 
     /**
-     * Cleans the path returned by get_components_with_tests() to standarize it
-     *
-     * @see tests_finder::get_all_directories_with_tests() it returns the path including /tests/
-     * @param string $path
-     * @return string The string without the last /tests part
-     * @deprecated since 3.2 MDL-55072 - please use behat_config_util.php
-     * @todo MDL-55365 This will be deleted in Moodle 3.6.
+     * @deprecated since 3.2 - please use behat_config_util.php
      */
-    protected final static function clean_path($path) {
-
-        debugging('Use of clean_path is deprecated, please see behat_config_util', DEBUG_DEVELOPER);
-        return self::get_behat_config_util()->clean_path($path);
+    protected final static function clean_path() {
+        throw new coding_exception('clean_path() can not be used anymore. ' .
+            'Please use behat_config_util instead.');
     }
 
     /**
-     * The relative path where components stores their behat tests
-     *
-     * @return string
-     * @deprecated since 3.2 MDL-55072 - please use behat_config_util.php
-     * @todo MDL-55365 This will be deleted in Moodle 3.6.
+     * @deprecated since 3.2 - please use behat_config_util.php
      */
     protected final static function get_behat_tests_path() {
-        debugging('Use of get_behat_tests_path is deprecated, please see behat_config_util', DEBUG_DEVELOPER);
-        return self::get_behat_config_util()->get_behat_tests_path();
+        throw new coding_exception('get_behat_tests_path() can not be used anymore. ' .
+            'Please use behat_config_util instead.');
     }
 
 }
index 84ccd70..cd69bbc 100644 (file)
@@ -383,5 +383,8 @@ $definitions = array(
         'simplekeys' => true,
         'simpledata' => true,
         'ttl' => 1800,
+        'invalidationevents' => array(
+            'createduser',
+        )
     ),
 );
diff --git a/lib/editor/atto/tests/behat/disablecontrol.feature b/lib/editor/atto/tests/behat/disablecontrol.feature
new file mode 100644 (file)
index 0000000..491e6e1
--- /dev/null
@@ -0,0 +1,45 @@
+@editor @editor_atto @atto @editor_moodleform
+Feature: Atto with enable/disable function.
+  In order to test enable/disable function
+  I create a sample page to test this feature.
+  As a user
+  I need to enable/disable all buttons/plugins and content of editor if "enable/disable" feature enabled.
+
+  Background:
+    Given the following "courses" exist:
+      | fullname | shortname | format |
+      | Course 1 | C1        | topics |
+    And the following "activities" exist:
+      | activity | name | intro                                                                                              | course | idnumber |
+      | label    | L1   | <a href="../lib/editor/tests/fixtures/disable_control_example.php">Control Enable/Disable Atto</a> | C1     | label1   |
+    And I log in as "admin"
+    And I am on "Course 1" course homepage
+    And I follow "Control Enable/Disable Atto"
+
+  @javascript
+  Scenario: Check disable Atto editor.
+    When I set the field "mycontrol" to "Disable"
+    Then the "disabled" attribute of "button.atto_collapse_button" "css_element" should contain "disabled"
+    And the "disabled" attribute of "button.atto_title_button" "css_element" should contain "disabled"
+    And the "disabled" attribute of "button.atto_bold_button_bold" "css_element" should contain "disabled"
+    And the "disabled" attribute of "button.atto_italic_button_italic" "css_element" should contain "disabled"
+    And the "disabled" attribute of "button.atto_unorderedlist_button_insertUnorderedList" "css_element" should contain "disabled"
+    And the "disabled" attribute of "button.atto_orderedlist_button_insertOrderedList" "css_element" should contain "disabled"
+    And the "disabled" attribute of "button.atto_link_button" "css_element" should contain "disabled"
+    And the "disabled" attribute of "button.atto_link_button_unlink" "css_element" should contain "disabled"
+    And the "disabled" attribute of "button.atto_image_button" "css_element" should contain "disabled"
+    And the "contenteditable" attribute of "div#id_myeditoreditable" "css_element" should contain "false"
+
+  @javascript
+  Scenario: Check enable Atto editor.
+    When I set the field "mycontrol" to "Enable"
+    Then "button.atto_collapse_button[disabled]" "css_element" should not exist
+    And "button.atto_title_button[disabled]" "css_element" should not exist
+    And "button.atto_bold_button_bold[disabled]" "css_element" should not exist
+    And "button.atto_italic_button_italic[disabled]" "css_element" should not exist
+    And "button.atto_unorderedlist_button_insertUnorderedList[disabled]" "css_element" should not exist
+    And "button.atto_orderedlist_button_insertOrderedList[disabled]" "css_element" should not exist
+    And "button.atto_link_button[disabled]" "css_element" should not exist
+    And "button.atto_link_button_unlink[disabled]" "css_element" should not exist
+    And "button.atto_image_button[disabled]" "css_element" should not exist
+    And the "contenteditable" attribute of "div#id_myeditoreditable" "css_element" should contain "true"
index 90e0996..9fce41e 100644 (file)
Binary files a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js and b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js differ
index 22df82b..0bb1434 100644 (file)
Binary files a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js and b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js differ
index 1b88fea..cf12f6c 100644 (file)
Binary files a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js and b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js differ
old mode 100644 (file)
new mode 100755 (executable)
index a28e936..b846bcd
@@ -225,6 +225,12 @@ Y.extend(Editor, Y.Base, {
         // Hide the old textarea.
         this.textarea.hide();
 
+        // Set up custom event for editor updated.
+        Y.mix(Y.Node.DOM_EVENTS, {'form:editorUpdated': true});
+        this.textarea.on('form:editorUpdated', function() {
+            this.updateEditorState();
+        }, this);
+
         // Copy the text to the contenteditable div.
         this.updateFromTextArea();
 
@@ -387,6 +393,20 @@ Y.extend(Editor, Y.Base, {
         }
     },
 
+    /**
+     * Update the state of the editor.
+     */
+    updateEditorState: function() {
+        var disabled = this.textarea.hasAttribute('readonly'),
+            editorfield = Y.one('#' + this.get('elementid') + 'editable');
+        // Enable/Disable all plugins.
+        this._setPluginState(!disabled);
+        // Enable/Disable content of editor.
+        if (editorfield) {
+            editorfield.setAttribute('contenteditable', !disabled);
+        }
+    },
+
     /**
      * Register an event handle for disposal in the destructor.
      *
diff --git a/lib/editor/tests/fixtures/disable_control_example.php b/lib/editor/tests/fixtures/disable_control_example.php
new file mode 100644 (file)
index 0000000..752c0bc
--- /dev/null
@@ -0,0 +1,47 @@
+<?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/>.
+
+/**
+ * Demonstrates use of editor with enable/disable function.
+ *
+ * This fixture is only used by the Behat test.
+ *
+ * @package core_editor
+ * @copyright 2018 Jake Hau <phuchau1509@gmail.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require(__DIR__ . '/../../../../config.php');
+require_once('./editor_form.php');
+
+// Behat test fixture only.
+defined('BEHAT_SITE_RUNNING') || die('Only available on Behat test server');
+
+// Require login.
+require_login();
+
+$PAGE->set_url('/lib/editor/tests/fixtures/disable_control_example.php');
+$PAGE->set_context(context_system::instance());
+
+// Create moodle form.
+$mform = new editor_form();
+
+echo $OUTPUT->header();
+
+// Display moodle form.
+$mform->display();
+
+echo $OUTPUT->footer();
diff --git a/lib/editor/tests/fixtures/editor_form.php b/lib/editor/tests/fixtures/editor_form.php
new file mode 100644 (file)
index 0000000..645728a
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Provides {@link lib/editor/tests/fixtures/editor_form} class.
+ *
+ * @package core_editor
+ * @copyright 2018 Jake Hau <phuchau1509@gmail.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->libdir.'/formslib.php');
+
+/**
+ * Class editor_form
+ *
+ * Demonstrates use of editor with disabledIf function.
+ * This fixture is only used by the Behat test.
+ *
+ * @package core_editor
+ * @copyright 2018 Jake Hau <phuchau1509@gmail.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class editor_form extends moodleform {
+
+    /**
+     * Form definition. Abstract method - always override!
+     */
+    protected function definition() {
+        $mform = $this->_form;
+        $editoroptions = $this->_customdata['editoroptions'];
+
+        // Add header.
+        $mform->addElement('header', 'myheader', 'Editor in Moodle form');
+
+        // Add element control.
+        $mform->addElement('select', 'mycontrol', 'My control', ['Enable', 'Disable']);
+
+        // Add editor.
+        $mform->addElement('editor', 'myeditor', 'My Editor', null, $editoroptions);
+        $mform->setType('myeditor', PARAM_RAW);
+
+        // Add control.
+        $mform->disabledIf('myeditor', 'mycontrol', 'eq', 1);
+    }
+}
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/lib/editor/textarea/tests/behat/disablecontrol.feature b/lib/editor/textarea/tests/behat/disablecontrol.feature
new file mode 100644 (file)
index 0000000..0d82331
--- /dev/null
@@ -0,0 +1,31 @@
+@editor @editor_textarea @texarea @editor_moodleform
+Feature: Text area with enable/disable function.
+  In order to test enable/disable function
+  I set default editor is Text area editor, and I create a sample page to test this feature.
+  As a user
+  I need to enable/disable content of editor if "enable/disable" feature enabled.
+
+  Background:
+    Given the following "courses" exist:
+      | fullname | shortname | format |
+      | Course 1 | C1        | topics |
+    And the following "activities" exist:
+      | activity | name | intro                                                                                                   | course | idnumber |
+      | label    | L1   | <a href="../lib/editor/tests/fixtures/disable_control_example.php">Control Enable/Disable Text area</a> | C1     | label1   |
+    And I log in as "admin"
+    And I follow "Preferences" in the user menu
+    And I follow "Editor preferences"
+    And I set the field "Text editor" to "Plain text area"
+    And I press "Save changes"
+    And I am on "Course 1" course homepage
+    And I follow "Control Enable/Disable Text area"
+
+  @javascript
+  Scenario: Check disable Text area editor.
+    When I set the field "mycontrol" to "Disable"
+    Then the "readonly" attribute of "textarea#id_myeditor" "css_element" should contain "readonly"
+
+  @javascript
+  Scenario: Check enable Text area editor.
+    When I set the field "mycontrol" to "Enable"
+    Then "textarea#id_myeditor[readonly]" "css_element" should not exist
old mode 100644 (file)
new mode 100755 (executable)
index b7b7904..0bcfd47
@@ -96,6 +96,10 @@ M.editor_tinymce.init_editor = function(Y, editorid, options) {
     if (item) {
         item.parentNode.removeChild(item);
     }
+
+    document.getElementById(editorid).addEventListener('form:editorUpdated', function() {
+        M.editor_tinymce.updateEditorState(editorid);
+    });
 };
 
 M.editor_tinymce.init_callback = function() {
@@ -110,6 +114,25 @@ M.editor_tinymce.toggle = function(id) {
     tinyMCE.execCommand('mceToggleEditor', false, id);
 };
 
+/**
+ * Update the state of the editor.
+ * @param {String} id
+ */
+M.editor_tinymce.updateEditorState = function(id) {
+    var instance = window.tinyMCE.get(id),
+        content = instance.getBody(),
+        controls = instance.controlManager.controls,
+        disabled = instance.getElement().readOnly;
+    // Enable/Disable all plugins.
+    for (var key in controls) {
+        if (controls.hasOwnProperty(key)) {
+            controls[key].setDisabled(disabled);
+        }
+    }
+    // Enable/Disable body content.
+    content.setAttribute('contenteditable', !disabled);
+};
+
 M.editor_tinymce.filepicker_callback = function(args) {
 };
 
diff --git a/lib/editor/tinymce/tests/behat/disablecontrol.feature b/lib/editor/tinymce/tests/behat/disablecontrol.feature
new file mode 100644 (file)
index 0000000..d8cc6da
--- /dev/null
@@ -0,0 +1,55 @@
+@editor @editor_tinymce @tinymce @editor_moodleform
+Feature: Tinymce with enable/disable function.
+  In order to test enable/disable function
+  I set default editor is Tinymce editor, and I create a sample page to test this feature.
+  As a user
+  I need to enable/disable all buttons/plugins and content of editor if "enable/disable" feature enabled.
+
+  Background:
+    Given the following "courses" exist:
+      | fullname | shortname | format |
+      | Course 1 | C1        | topics |
+    And the following "activities" exist:
+      | activity | name | intro                                                                                                 | course | idnumber |
+      | label    | L1   | <a href="../lib/editor/tests/fixtures/disable_control_example.php">Control Enable/Disable Tinymce</a> | C1     | label1   |
+    And I log in as "admin"
+    And I follow "Preferences" in the user menu
+    And I follow "Editor preferences"
+    And I set the field "Text editor" to "TinyMCE HTML editor"
+    And I press "Save changes"
+    And I am on "Course 1" course homepage
+    And I follow "Control Enable/Disable Tinymce"
+
+  @javascript
+  Scenario: Check disable Tinymce editor.
+    When I click on "option[value=1]" "css_element" in the "select#id_mycontrol" "css_element"
+    Then the "class" attribute of "a#id_myeditor_pdw_toggle" "css_element" should contain "mceButtonDisabled"
+    And the "class" attribute of "table#id_myeditor_formatselect" "css_element" should contain "mceListBoxDisabled"
+    And the "class" attribute of "a#id_myeditor_bold" "css_element" should contain "mceButtonDisabled"
+    And the "class" attribute of "a#id_myeditor_italic" "css_element" should contain "mceButtonDisabled"
+    And the "class" attribute of "a#id_myeditor_bullist" "css_element" should contain "mceButtonDisabled"
+    And the "class" attribute of "a#id_myeditor_numlist" "css_element" should contain "mceButtonDisabled"
+    And the "class" attribute of "a#id_myeditor_link" "css_element" should contain "mceButtonDisabled"
+    And the "class" attribute of "a#id_myeditor_unlink" "css_element" should contain "mceButtonDisabled"
+    And the "class" attribute of "a#id_myeditor_moodlenolink" "css_element" should contain "mceButtonDisabled"
+    And the "class" attribute of "a#id_myeditor_image" "css_element" should contain "mceButtonDisabled"
+    And the "class" attribute of "a#id_myeditor_moodlemedia" "css_element" should contain "mceButtonDisabled"
+    And I switch to "id_myeditor_ifr" iframe
+    And the "contenteditable" attribute of "body" "css_element" should contain "false"
+
+  @javascript
+  Scenario: Check enable Tinymce editor.
+    When I click on "option[value=0]" "css_element" in the "select#id_mycontrol" "css_element"
+    Then the "class" attribute of "a#id_myeditor_pdw_toggle" "css_element" should contain "mceButtonEnabled"
+    And the "class" attribute of "table#id_myeditor_formatselect" "css_element" should contain "mceListBoxEnabled"
+    And the "class" attribute of "a#id_myeditor_bold" "css_element" should contain "mceButtonEnabled"
+    And the "class" attribute of "a#id_myeditor_italic" "css_element" should contain "mceButtonEnabled"
+    And the "class" attribute of "a#id_myeditor_bullist" "css_element" should contain "mceButtonEnabled"
+    And the "class" attribute of "a#id_myeditor_numlist" "css_element" should contain "mceButtonEnabled"
+    And the "class" attribute of "a#id_myeditor_link" "css_element" should contain "mceButtonDisabled"
+    And the "class" attribute of "a#id_myeditor_unlink" "css_element" should contain "mceButtonDisabled"
+    And the "class" attribute of "a#id_myeditor_moodlenolink" "css_element" should contain "mceButtonDisabled"
+    And the "class" attribute of "a#id_myeditor_image" "css_element" should contain "mceButtonEnabled"
+    And the "class" attribute of "a#id_myeditor_moodlemedia" "css_element" should contain "mceButtonEnabled"
+    And I switch to "id_myeditor_ifr" iframe
+    And the "contenteditable" attribute of "body" "css_element" should contain "true"
index 667eed8..44fbd29 100644 (file)
@@ -208,10 +208,10 @@ class external_api {
             // Do not allow access to write or delete webservices as a public user.
             if ($externalfunctioninfo->loginrequired) {
                 if (defined('NO_MOODLE_COOKIES') && NO_MOODLE_COOKIES && !PHPUNIT_TEST) {
-                    throw new moodle_exception('servicenotavailable', 'webservice');
+                    throw new moodle_exception('servicerequireslogin', 'webservice');
                 }
                 if (!isloggedin()) {
-                    throw new moodle_exception('servicenotavailable', 'webservice');
+                    throw new moodle_exception('servicerequireslogin', 'webservice');
                 } else {
                     require_sesskey();
                 }
old mode 100644 (file)
new mode 100755 (executable)
index 50f5960..1c6dacc
@@ -250,8 +250,10 @@ if (typeof M.form.dependencyManager === 'undefined') {
          * @param {Boolean} disabled True to disable, false to enable.
          */
         _disableElement: function(name, disabled) {
-            var els = this.elementsByName(name);
-            var filepicker = this.isFilePicker(name);
+            var els = this.elementsByName(name),
+                filepicker = this.isFilePicker(name),
+                editors = this.get('form').all('.fitem [data-fieldtype="editor"] textarea[name="' + name + '[text]"]');
+
             els.each(function(node) {
                 if (disabled) {
                     node.setAttribute('disabled', 'disabled');
@@ -271,6 +273,14 @@ if (typeof M.form.dependencyManager === 'undefined') {
                     }
                 }
             });
+            editors.each(function(editor) {
+                if (disabled) {
+                    editor.setAttribute('readonly', 'readonly');
+                } else {
+                    editor.removeAttribute('readonly', 'readonly');
+                }
+                editor.getDOMNode().dispatchEvent(new Event('form:editorUpdated'));
+            });
         },
         /**
          * Hides or shows all form elements with the given name.
index 6951b15..13ac090 100644 (file)
@@ -971,6 +971,9 @@ class behat_general extends behat_base {
      * @param string $taskname Name of task e.g. 'mod_whatever\task\do_something'
      */
     public function i_run_the_scheduled_task($taskname) {
+        global $CFG;
+        require_once("{$CFG->libdir}/cronlib.php");
+
         $task = \core\task\manager::get_scheduled_task($taskname);
         if (!$task) {
             throw new DriverException('The "' . $taskname . '" scheduled task does not exist');
@@ -997,16 +1000,26 @@ class behat_general extends behat_base {
         }
 
         try {
+            // Prepare the renderer.
+            cron_prepare_core_renderer();
+
             // Discard task output as not appropriate for Behat output!
             ob_start();
             $task->execute();
             ob_end_clean();
 
+            // Restore the previous renderer.
+            cron_prepare_core_renderer(true);
+
             // Mark task complete.
             \core\task\manager::scheduled_task_complete($task);
         } catch (Exception $e) {
+            // Restore the previous renderer.
+            cron_prepare_core_renderer(true);
+
             // Mark task failed and throw exception.
             \core\task\manager::scheduled_task_failed($task);
+
             throw new DriverException('The "' . $taskname . '" scheduled task failed', 0, $e);
         }
     }
@@ -1025,24 +1038,35 @@ class behat_general extends behat_base {
      * @throws DriverException
      */
     public function i_run_all_adhoc_tasks() {
+        global $CFG, $DB;
+        require_once("{$CFG->libdir}/cronlib.php");
+
         // Do setup for cron task.
         cron_setup_user();
 
-        // Run tasks. Locking is handled by get_next_adhoc_task.
-        $now = time();
-        ob_start(); // Discard task output as not appropriate for Behat output!
-        while (($task = \core\task\manager::get_next_adhoc_task($now)) !== null) {
-
-            try {
-                $task->execute();
-
-                // Mark task complete.
-                \core\task\manager::adhoc_task_complete($task);
-            } catch (Exception $e) {
-                // Mark task failed and throw exception.
-                \core\task\manager::adhoc_task_failed($task);
-                ob_end_clean();
-                throw new DriverException('An adhoc task failed', 0, $e);
+        // Discard task output as not appropriate for Behat output!
+        ob_start();
+
+        // Run all tasks which have a scheduled runtime of before now.
+        $timenow = time();
+
+        while (!\core\task\manager::static_caches_cleared_since($timenow) &&
+                $task = \core\task\manager::get_next_adhoc_task($timenow)) {
+            // Clean the output buffer between tasks.
+            ob_clean();
+
+            // Run the task.
+            cron_run_inner_adhoc_task($task);
+
+            // Check whether the task record still exists.
+            // If a task was successful it will be removed.
+            // If it failed then it will still exist.
+            if ($DB->record_exists('task_adhoc', ['id' => $task->get_id()])) {
+                // End ouptut buffering and flush the current buffer.
+                // This should be from just the current task.
+                ob_end_flush();
+
+                throw new DriverException('An adhoc task failed', 0);
             }
         }
         ob_end_clean();
index 3f12ad3..9389ffd 100644 (file)
@@ -75,11 +75,11 @@ class core_string_manager_standard_testcase extends advanced_testcase {
         $this->assertFalse($stringman->string_deprecated('hidden', 'grades'));
 
         // Check deprecated string.
-        $this->assertTrue($stringman->string_deprecated('modchooserenable', 'core'));
-        $this->assertTrue($stringman->string_exists('modchooserenable', 'core'));
+        $this->assertTrue($stringman->string_deprecated('groupextendenrol', 'core'));
+        $this->assertTrue($stringman->string_exists('groupextendenrol', 'core'));
         $this->assertDebuggingNotCalled();
-        $this->assertEquals('Activity chooser on', get_string('modchooserenable', 'core'));
-        $this->assertDebuggingCalled('String [modchooserenable,core] is deprecated. '.
+        $this->assertEquals('Extend enrolment (common)', get_string('groupextendenrol', 'core'));
+        $this->assertDebuggingCalled('String [groupextendenrol,core] is deprecated. '.
             'Either you should no longer be using that string, or the string has been incorrectly deprecated, in which case you should report this as a bug. '.
             'Please refer to https://docs.moodle.org/dev/String_deprecation');
     }
index be7297d..0e3a77a 100644 (file)
@@ -3,9 +3,21 @@ information provided here is intended especially for developers.
 
 === 3.6 ===
 
+* Custom AJAX handlers for the form autocomplete fields can now optionally return string in their processResults()
+  callback. If a string is returned, it is displayed instead of the list if suggested items. This can be used, for
+  example, to inform the user that there are too many items matching the current search criteria.
 * The following functions have been finally deprecated and can not be used any more:
-
-- external_function_info()
+  - external_function_info()
+* Following api's have been removed in behat_config_manager, please use behat_config_util instead.
+    - get_features_with_tags()
+    - get_components_steps_definitions()
+    - get_config_file_contents()
+    - merge_behat_config()
+    - get_behat_profile()
+    - profile_guided_allocate()
+    - merge_config()
+    - clean_path()
+    - get_behat_tests_path()
 
 === 3.5 ===
 
index 557f188..06775e5 100644 (file)
@@ -585,6 +585,3 @@ $string['viewsubmissiongradingtable'] = 'View submission grading table.';
 $string['viewrevealidentitiesconfirm'] = 'View reveal student identities confirmation page.';
 $string['workflowfilter'] = 'Workflow filter';
 $string['xofy'] = '{$a->x} of {$a->y}';
-
-// Deprecated since Moodle 3.2.
-$string['changegradewarning'] = 'This assignment has graded submissions and changing the grade will not automatically re-calculate existing submission grades. You must re-grade all existing submissions, if you wish to change the grade.';
index 76d8f54..e69de29 100644 (file)
@@ -1 +0,0 @@
-changegradewarning,mod_assign
\ No newline at end of file
index 6084a7f..28d233e 100644 (file)
@@ -400,17 +400,3 @@ $string['viewfromdate'] = 'Read only from';
 $string['viewtodate'] = 'Read only to';
 $string['viewtodatevalidation'] = 'The read only to date cannot be before the read only from date.';
 $string['wrongdataid'] = 'Wrong data id provided';
-
-// Deprecated since Moodle 3.2.
-$string['namedate'] = 'Date field';
-$string['namefile'] = 'File field';
-$string['namecheckbox'] = 'Checkbox field';
-$string['namelatlong'] = 'Latitude/longitude field';
-$string['namemenu'] = 'Menu field';
-$string['namemultimenu'] = 'Multiple-selection menu field';
-$string['namenumber'] = 'Number field';
-$string['namepicture'] = 'Picture field';
-$string['nameradiobutton'] = 'Radio button field';
-$string['nametext'] = 'Text field';
-$string['nametextarea'] = 'Textarea field';
-$string['nameurl'] = 'URL field';
index cf44132..e69de29 100644 (file)
@@ -1,12 +0,0 @@
-namedate,mod_data
-namefile,mod_data
-namecheckbox,mod_data
-namelatlong,mod_data
-namemenu,mod_data
-namemultimenu,mod_data
-namenumber,mod_data
-namepicture,mod_data
-nameradiobutton,mod_data
-nametext,mod_data
-nametextarea,mod_data
-nameurl,mod_data
\ No newline at end of file
index fe76fa7..e69de29 100644 (file)
@@ -1,2 +0,0 @@
-start,mod_feedback
-stop,mod_feedback
\ No newline at end of file
index f87fb98..23d1ab5 100644 (file)
@@ -284,6 +284,3 @@ $string['use_one_line_for_each_value'] = 'Use one line for each answer!';
 $string['use_this_template'] = 'Use this template';
 $string['using_templates'] = 'Use a template';
 $string['vertical'] = 'Vertical';
-// Deprecated since Moodle 3.2.
-$string['start'] = 'Start';
-$string['stop'] = 'End';
index db845c5..3634cb1 100644 (file)
@@ -484,7 +484,7 @@ function wiki_search_form($cm, $search = '', $subwiki = null) {
         $output .= '<input name="subwikiid" type="hidden" value="' . $subwiki->id . '" />';
     }
     $output .= '<input name="searchwikicontent" type="hidden" value="1" />';
-    $output .= '<input value="' . get_string('searchwikis', 'wiki') . '" type="submit" />';
+    $output .= '<input value="' . get_string('searchwikis', 'wiki') . '" class="btn btn-secondary" type="submit" />';
     $output .= '</fieldset>';
     $output .= '</form>';
     $output .= '</div>';
index 16fd168..b387464 100644 (file)
@@ -340,7 +340,7 @@ function useredit_shared_definition(&$mform, $editoroptions, $filemanageroptions
     }
 
     $mform->addElement('editor', 'description_editor', get_string('userdescription'), null, $editoroptions);
-    $mform->setType('description_editor', PARAM_CLEANHTML);
+    $mform->setType('description_editor', PARAM_RAW);
     $mform->addHelpButton('description_editor', 'userdescription');
 
     if (empty($USER->newadminuser)) {
index 44be4f4..985c402 100644 (file)
@@ -122,6 +122,9 @@ function user_create_user($user, $updatepassword = true, $triggerevent = true) {
         \core\event\user_created::create_from_userid($newuserid)->trigger();
     }
 
+    // Purge the associated caches.
+    cache_helper::purge_by_event('createduser');
+
     return $newuserid;
 }
 
index 94c5931..c7589be 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2018072000.00;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2018072000.01;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.