+++ /dev/null
-<?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);
- }
-}
* @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],
];
}
* 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);
| 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"
<?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");
} ?>
</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>
$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'];
$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';
-display_un,block_myprofile
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"
$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';
* @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) {
search: query,
searchanywhere: true,
page: 0,
- perpage: 30
+ perpage: MAXUSERS + 1
}
}]);
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);
}
--- /dev/null
+@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"
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.
*/
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;
}
$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));
$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.';
$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';
$string['usercompetencystatus_inreview'] = 'In review';
$string['usercompetencystatus_waitingforreview'] = 'Waiting for review';
$string['userplans'] = 'Learning plans';
-
-// Deprecated since Moodle 3.2.
-$string['invalidpersistent'] = 'Invalid persistent';
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
$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.';
$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';
$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}';
$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';
$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';
* @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;
}
// 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);
+ }
}
}
};
});
// 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.
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);
}
/**
- * 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.');
}
/**
}
/**
- * 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.');
}
}
'simplekeys' => true,
'simpledata' => true,
'ttl' => 1800,
+ 'invalidationevents' => array(
+ 'createduser',
+ )
),
);
--- /dev/null
+@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"
// 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();
}
},
+ /**
+ * 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.
*
--- /dev/null
+<?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();
--- /dev/null
+<?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);
+ }
+}
--- /dev/null
+@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
if (item) {
item.parentNode.removeChild(item);
}
+
+ document.getElementById(editorid).addEventListener('form:editorUpdated', function() {
+ M.editor_tinymce.updateEditorState(editorid);
+ });
};
M.editor_tinymce.init_callback = function() {
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) {
};
--- /dev/null
+@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"
// 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();
}
* @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');
}
}
});
+ 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.
* @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');
}
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);
}
}
* @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();
$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');
}
=== 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 ===
$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.';
-changegradewarning,mod_assign
\ No newline at end of file
$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';
-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
-start,mod_feedback
-stop,mod_feedback
\ No newline at end of file
$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';
$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>';
}
$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)) {
\core\event\user_created::create_from_userid($newuserid)->trigger();
}
+ // Purge the associated caches.
+ cache_helper::purge_by_event('createduser');
+
return $newuserid;
}
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.