Compare commits
375 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fad0937a82 | |||
| c1106792b1 | |||
| 44b789cc6d | |||
| 8533cba2ae | |||
| b855cfcfee | |||
| 94218cb1af | |||
| 5c6dd1dc5b | |||
| 25327eecff | |||
| 2924ba1c73 | |||
| b707f76f64 | |||
| 7f8230f8df | |||
| 5a96b851a2 | |||
| 5e9a15e516 | |||
| e8e4d45620 | |||
| 1456b2674d | |||
| fb53bebd1d | |||
| ceab40d186 | |||
| daab241a0b | |||
| cf5cc056b4 | |||
| b45ff8b856 | |||
| 7042dfe5f3 | |||
| 629df3afd0 | |||
| 5e89c05368 | |||
| 74a2c781f7 | |||
| 48213fc8ad | |||
| 81e8eb60a9 | |||
| 379c492a98 | |||
| bfc0273f12 | |||
| 72bb4ca411 | |||
| 84f9f60b67 | |||
| a47aabc783 | |||
| 76da7e9bc8 | |||
| 1bdc5cc997 | |||
| 429aa0f321 | |||
| da53b55002 | |||
| 67957f5683 | |||
| cd060b5fe2 | |||
| b0abcbda17 | |||
| 1a344ea46f | |||
| 3a89cea7f7 | |||
| 3657649aaa | |||
| 12ba38e725 | |||
| fdab8c0a51 | |||
| 1bf41ebcd8 | |||
| 70d5d05c0e | |||
| 2ceee45b76 | |||
| 952db2245b | |||
| 4d6cfa8e4f | |||
| 845ecec21e | |||
| bf6c92065d | |||
| f0ecdada22 | |||
| deea56cf6f | |||
| ff6092696c | |||
| 56479e0721 | |||
| 8012d5ad5e | |||
| a9558a0559 | |||
| e2abf6048c | |||
| 8527a343e1 | |||
| 4b4466e559 | |||
| b70c6fcf87 | |||
| 98b1c93d11 | |||
| 0aadd59a87 | |||
| e742ba8b7e | |||
| 938d6e9def | |||
| 0396e811bb | |||
| 0eaac55d01 | |||
| 7cbb09aaa3 | |||
| 933fa26e63 | |||
| d0284fe719 | |||
| 2017880f90 | |||
| 8bcfbda511 | |||
| a06527d280 | |||
| d830e39f28 | |||
| bb323b1876 | |||
| 6253df7309 | |||
| 817837bdd1 | |||
| 1cf194adaa | |||
| 93f6e83dce | |||
| 4bc553ab04 | |||
| 1092970fda | |||
| 12e121ed33 | |||
| 6e040c0593 | |||
| 0488bd92cd | |||
| 036bf6ec37 | |||
| 772ec0a6e3 | |||
| b01f29882b | |||
| 89b06d239f | |||
| fcf8a305ea | |||
| 327272881a | |||
| 21d6db9b77 | |||
| 86d20a95c8 | |||
| fd77d51e5d | |||
| 992a8a42d5 | |||
| bd3332ff6e | |||
| 94c912d7c4 | |||
| 3692b5dd8b | |||
| f423902be7 | |||
| e0312ddb49 | |||
| 636eb3726c | |||
| 98e374b38f | |||
| a698a4d1f2 | |||
| edbe1e67f1 | |||
| e9265276b8 | |||
| e530410232 | |||
| e282453aea | |||
| 6a03a96e47 | |||
| 0df2edf254 | |||
| 73d3d0d37f | |||
| 71ae878ca9 | |||
| 21e6dc4d52 | |||
| 3adfe5f72f | |||
| 62baf63445 | |||
| 685fba3ffe | |||
| 113a06cd95 | |||
| 175883c223 | |||
| 00ce45b9aa | |||
| 21929ef07d | |||
| 049943b708 | |||
| 27548ec845 | |||
| c33fdb5834 | |||
| 3bd8407407 | |||
| 91b8101c16 | |||
| 822c4b9c40 | |||
| 476fa05c08 | |||
| 2a7241b3a1 | |||
| 5e5b5b393d | |||
| 5fe6298a05 | |||
| 56e9f5c166 | |||
| f65b1f10ad | |||
| a16e03df3f | |||
| b516be1d7e | |||
| 85a61d783e | |||
| 48b7540b31 | |||
| 3d3b2669c9 | |||
| 497e25d8f4 | |||
| 8cb2cbbf98 | |||
| cfab858010 | |||
| 298aa05da8 | |||
| 20b114ec27 | |||
| 5bae4138e9 | |||
| 46471489f5 | |||
| 7a6581f6c2 | |||
| 76b5719bbb | |||
| e314024bdd | |||
| 4d65e9527e | |||
| d612b63001 | |||
| 9bec924781 | |||
| 812ed49a93 | |||
| a43200104c | |||
| 9e0b0f76bb | |||
| c7b96ac18a | |||
| 9c95bd6d03 | |||
| cc980d0197 | |||
| 0370128f35 | |||
| 00e8070f00 | |||
| 42559a9df0 | |||
| 078e04775e | |||
| 4cd7c56432 | |||
| 8bc846ff7a | |||
| 33446800b7 | |||
| 4f0874c0cf | |||
| 19e7fb0ca0 | |||
| 62f5dc3fdc | |||
| b2792006aa | |||
| f5d47e3648 | |||
| abb41a5363 | |||
| 77d4380533 | |||
| 3be4c8751c | |||
| 4582c3d4fa | |||
| a6ba98c2c9 | |||
| 2b8b2e876e | |||
| 102d449fa9 | |||
| f702287188 | |||
| b7b0a28dc6 | |||
| 9443735f27 | |||
| 52b817b6ba | |||
| d025f8a226 | |||
| ddbc062458 | |||
| 76f1a72720 | |||
| ba9a541797 | |||
| 40020334e3 | |||
| 232a79c81c | |||
| 87914aa407 | |||
| 2df1e26d6b | |||
| af5f6b7300 | |||
| 3ba01c11b4 | |||
| 0402c8c069 | |||
| 6b6125b949 | |||
| 734df0d567 | |||
| c14e541347 | |||
| a07b461a4a | |||
| d9985cf497 | |||
| 4a21f1b58b | |||
| ae2faed37d | |||
| 47dfdfcfbe | |||
| a84ea4944a | |||
| 27ccaa5f29 | |||
| 82d8e53dec | |||
| a2b22dd5df | |||
| cb4f747758 | |||
| 4d70a24d32 | |||
| 5c5559abb8 | |||
| 068925e251 | |||
| 8d3e6e385d | |||
| 1030084f6e | |||
| 7f866e3c18 | |||
| 9e4f60924c | |||
| 36d81e9ef2 | |||
| 1ad756e4ed | |||
| 5e4ddeab88 | |||
| 51f931fea7 | |||
| 61cff2855e | |||
| f25f4caffd | |||
| 3d10a0b762 | |||
| 40c809b83e | |||
| 14fe039d20 | |||
| a9d59d433a | |||
| 379a362bca | |||
| b6fcba4636 | |||
| d9e865148d | |||
| fef4361142 | |||
| bdc6977dc7 | |||
| edcb9e619f | |||
| 9196786861 | |||
| f554a14205 | |||
| 904883b08f | |||
| 20e9ca0faa | |||
| ff936081dc | |||
| 788a4e112d | |||
| 3db52fd27f | |||
| 1ffc405936 | |||
| 0289be1321 | |||
| 365e0555ee | |||
| ef76325dda | |||
| 8cda566640 | |||
| d09c57ee33 | |||
| fe3c75ae36 | |||
| 848dd93bf2 | |||
| 86799aa49f | |||
| 5869dbfc4c | |||
| 731251f405 | |||
| 0a5543cb55 | |||
| ec711d5bbd | |||
| f321e5a222 | |||
| 358c48ff27 | |||
| cecc812fa0 | |||
| 7956f0c3af | |||
| f53e024291 | |||
| 3f4c39004d | |||
| a0adb4195e | |||
| d55e5bb821 | |||
| 4cd289ae45 | |||
| db8977f209 | |||
| af65e0db33 | |||
| 083fe32ba3 | |||
| 32f0ad84c6 | |||
| 73502d6464 | |||
| 33f9b3b1e1 | |||
| 20ef0b4257 | |||
| fd7100a221 | |||
| 73841c3908 | |||
| ce534d5dfa | |||
| cccb0c0722 | |||
| c5363d38d2 | |||
| 74783abd8d | |||
| b44e802eaf | |||
| d02eaee727 | |||
| 5bb19510ab | |||
| 5634dcb828 | |||
| 90ef484cec | |||
| e47d85fadb | |||
| 68e1853422 | |||
| a6a73abf88 | |||
| f4ebb7eb0a | |||
| 990854c17b | |||
| 4758a64934 | |||
| ca1b2405c4 | |||
| 02528f3266 | |||
| b20e80fb67 | |||
| 3fdfc48a44 | |||
| 85b77c7ea4 | |||
| 13125610aa | |||
| 981464e4ba | |||
| 29972512c1 | |||
| 41be0b4e02 | |||
| 68a5cc75a6 | |||
| b70a4b3e61 | |||
| 85ea64f5ee | |||
| 1db2e142a2 | |||
| a56ec068ed | |||
| 39922f8029 | |||
| 67ae93f917 | |||
| 93bfaf4fa8 | |||
| 589fb8e7b3 | |||
| 125c11d3f0 | |||
| 17c0747edd | |||
| fa9e5b5709 | |||
| 919fd9433b | |||
| 0256434964 | |||
| 55316d0b0d | |||
| 77bb001602 | |||
| 04f14e3047 | |||
| 1031133cce | |||
| 5f5c2b846d | |||
| 5aa4150f4a | |||
| fa51ff9969 | |||
| 82e95407eb | |||
| 9369b2167f | |||
| 08116bf552 | |||
| 13f6652060 | |||
| 8705f0f9ea | |||
| 807c71c0bd | |||
| c665480063 | |||
| ead9f6c78d | |||
| e5f2f54920 | |||
| fc05d527e4 | |||
| da36d32ef7 | |||
| c8410c245c | |||
| 59e724cfa1 | |||
| 60802d3a1c | |||
| 4047bebb65 | |||
| 146c80d338 | |||
| ced23f8a50 | |||
| 13ad716894 | |||
| 9beca92ae6 | |||
| eedfb32ea0 | |||
| 52d7933eec | |||
| 261cb39eca | |||
| 3d383a7da5 | |||
| e048e9f1ab | |||
| 0dc79af9c6 | |||
| 7cda92f09c | |||
| f88fc2bb85 | |||
| 8ef170b1cc | |||
| 953601bcb0 | |||
| 308bca3b39 | |||
| ac5f381992 | |||
| 8a15f3d25f | |||
| d3e6254b40 | |||
| 492e583328 | |||
| d86285fb80 | |||
| e1dab7082d | |||
| 287986340f | |||
| 28b6d8949c | |||
| ad028c1ea0 | |||
| e3d7ab13ed | |||
| 154685629a | |||
| 56eb183b01 | |||
| 1ffb2f5e2e | |||
| cb04c9cb1e | |||
| c7a0ba9623 | |||
| aef5f4d5a3 | |||
| 0be93791cb | |||
| 6eb4a6bd28 | |||
| a476d04ce5 | |||
| e119e084ec | |||
| 61266a15e9 | |||
| 7e6411aae5 | |||
| 8818f55a75 | |||
| d8b26e11dd | |||
| 4655dedf1f | |||
| 96ed0694ef | |||
| 895b61d6e6 | |||
| 227b31ccbe | |||
| 127210170d | |||
| 0b2e01db96 | |||
| 0d71d809e6 | |||
| e2a3ea029a | |||
| 3cae9f4d13 | |||
| 5ce6beca15 | |||
| b2fb93f89b | |||
| 719c2dac88 | |||
| ad43491248 | |||
| afca27a6dc | |||
| 1fdfd7127c |
+1
-2
@@ -67,7 +67,6 @@ if ($data = data_submitted() and confirm_sesskey()) {
|
||||
$errormsg = get_string('errorwithsettings', 'admin');
|
||||
$firsterror = reset($adminroot->errors);
|
||||
}
|
||||
$adminroot = admin_get_root(true); //reload tree
|
||||
$settingspage = $adminroot->locate($category, true);
|
||||
}
|
||||
|
||||
@@ -156,4 +155,4 @@ echo $outputhtml;
|
||||
echo html_writer::end_tag('fieldset');
|
||||
echo html_writer::end_tag('form');
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
@@ -41,15 +41,24 @@ class core_role_existing_role_holders extends core_role_assign_user_selector_bas
|
||||
list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext);
|
||||
$params = array_merge($params, $sortparams);
|
||||
|
||||
$sql = "SELECT ra.id AS raid," . $this->required_fields_sql('u') . ",ra.contextid,ra.component
|
||||
FROM {role_assignments} ra
|
||||
$fields = "SELECT ra.id AS raid," . $this->required_fields_sql('u') . ",ra.contextid,ra.component ";
|
||||
$countfields = "SELECT COUNT(1) ";
|
||||
$sql = "FROM {role_assignments} ra
|
||||
JOIN {user} u ON u.id = ra.userid
|
||||
JOIN {context} ctx ON ra.contextid = ctx.id
|
||||
WHERE $wherecondition
|
||||
AND ctx.id $ctxcondition
|
||||
AND ra.roleid = :roleid
|
||||
ORDER BY ctx.depth DESC, ra.component, $sort";
|
||||
$contextusers = $DB->get_records_sql($sql, $params);
|
||||
AND ra.roleid = :roleid";
|
||||
$order = " ORDER BY ctx.depth DESC, ra.component, $sort";
|
||||
|
||||
if (!$this->is_validating()) {
|
||||
$existinguserscount = $DB->count_records_sql($countfields . $sql, $params);
|
||||
if ($existinguserscount > $this->maxusersperpage) {
|
||||
return $this->too_many_results($search, $existinguserscount);
|
||||
}
|
||||
}
|
||||
|
||||
$contextusers = $DB->get_records_sql($fields . $sql . $order, $params);
|
||||
|
||||
// No users at all.
|
||||
if (empty($contextusers)) {
|
||||
|
||||
+1
-3
@@ -22,7 +22,6 @@ if ($data = data_submitted() and confirm_sesskey()) {
|
||||
if (admin_write_settings($data)) {
|
||||
$statusmsg = get_string('changessaved');
|
||||
}
|
||||
$adminroot = admin_get_root(true); //reload tree
|
||||
|
||||
if (!empty($adminroot->errors)) {
|
||||
$errormsg = get_string('errorwithsettings', 'admin');
|
||||
@@ -44,10 +43,9 @@ if ($errormsg !== '') {
|
||||
|
||||
$resultshtml = admin_search_settings_html($query); // case insensitive search only
|
||||
|
||||
echo '<form action="search.php" method="post" id="adminsettings">';
|
||||
echo '<form action="' . $PAGE->url->out(true) . '" method="post" id="adminsettings">';
|
||||
echo '<div>';
|
||||
echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
|
||||
echo '<input type="hidden" name="query" value="'.s($query).'" />';
|
||||
echo '</div>';
|
||||
echo '<fieldset>';
|
||||
echo '<div class="clearer"><!-- --></div>';
|
||||
|
||||
@@ -48,7 +48,6 @@ if ($data = data_submitted() and confirm_sesskey()) {
|
||||
$errormsg = get_string('errorwithsettings', 'admin');
|
||||
$firsterror = reset($adminroot->errors);
|
||||
}
|
||||
$adminroot = admin_get_root(true); //reload tree
|
||||
$settingspage = $adminroot->locate($section, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -278,9 +278,6 @@ if ($hassiteconfig) {
|
||||
$ADMIN->add('webservicesettings', new admin_externalpage('webservicedocumentation', new lang_string('wsdocapi', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/documentation.php", 'moodle/site:config', false));
|
||||
/// manage service
|
||||
$temp = new admin_settingpage('externalservices', new lang_string('externalservices', 'webservice'));
|
||||
$temp->add(new admin_setting_enablemobileservice('enablemobilewebservice',
|
||||
new lang_string('enablemobilewebservice', 'admin'),
|
||||
new lang_string('configenablemobilewebservice', 'admin', $enablemobiledoclink), 0));
|
||||
$temp->add(new admin_setting_heading('manageserviceshelpexplaination', new lang_string('information', 'webservice'), new lang_string('servicehelpexplanation', 'webservice')));
|
||||
$temp->add(new admin_setting_manageexternalservices());
|
||||
$ADMIN->add('webservicesettings', $temp);
|
||||
|
||||
@@ -308,8 +308,7 @@ class tool_generator_course_backend extends tool_generator_backend {
|
||||
$username = 'tool_generator_' . $textnumber;
|
||||
|
||||
// Create user account.
|
||||
$record = array('firstname' => get_string('firstname', 'tool_generator'),
|
||||
'lastname' => $number, 'username' => $username);
|
||||
$record = array('username' => $username, 'idnumber' => $number);
|
||||
|
||||
// We add a user password if it has been specified.
|
||||
if (!empty($CFG->tool_generator_users_password)) {
|
||||
|
||||
@@ -62,7 +62,6 @@ $string['error_nonexistingcourse'] = 'The specified course does not exist';
|
||||
$string['error_nopageinstances'] = 'The selected course does not contain page module instances';
|
||||
$string['error_notdebugging'] = 'Not available on this server because debugging is not set to DEVELOPER';
|
||||
$string['error_nouserspassword'] = 'You need to set $CFG->tool_generator_users_password in config.php to generate the test plan';
|
||||
$string['firstname'] = 'Test course user';
|
||||
$string['fullname'] = 'Test course: {$a->size}';
|
||||
$string['maketestcourse'] = 'Make test course';
|
||||
$string['maketestplan'] = 'Make JMeter test plan';
|
||||
|
||||
@@ -136,7 +136,7 @@ class tool_generator_maketestcourse_testcase extends advanced_testcase {
|
||||
$lastusernumber = 0;
|
||||
$discussionstarters = array();
|
||||
foreach ($discussions as $discussion) {
|
||||
$usernumber = intval($discussion->lastname);
|
||||
$usernumber = core_user::get_user($discussion->userid, 'id, idnumber')->idnumber;
|
||||
|
||||
// Checks that the users are odd numbers.
|
||||
$this->assertEquals(1, $usernumber % 2);
|
||||
|
||||
@@ -164,33 +164,6 @@ if ($mode == UPDATE_ALL_LANG) {
|
||||
make_temp_directory('');
|
||||
make_upload_directory('lang');
|
||||
|
||||
// clean-up currently installed versions of the packs
|
||||
foreach ($neededlangs as $packindex => $pack) {
|
||||
if ($pack == 'en') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// delete old directories
|
||||
$dest1 = $CFG->dataroot.'/lang/'.$pack;
|
||||
$dest2 = $CFG->dirroot.'/lang/'.$pack;
|
||||
$rm1 = false;
|
||||
$rm2 = false;
|
||||
if (file_exists($dest1)) {
|
||||
if (!remove_dir($dest1)) {
|
||||
$notice_error[] = 'Could not delete old directory '.$dest1.', update of '.$pack.' failed, please check permissions.';
|
||||
unset($neededlangs[$packindex]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (file_exists($dest2)) {
|
||||
if (!remove_dir($dest2)) {
|
||||
$notice_error[] = 'Could not delete old directory '.$dest2.', update of '.$pack.' failed, please check permissions.';
|
||||
unset($neededlangs[$packindex]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// install all needed language packs
|
||||
$installer->set_queue($neededlangs);
|
||||
$results = $installer->run();
|
||||
|
||||
@@ -53,27 +53,22 @@ class tool_task_edit_scheduled_task_form extends moodleform {
|
||||
$mform->addElement('text', 'minute', get_string('taskscheduleminute', 'tool_task'));
|
||||
$mform->setType('minute', PARAM_RAW);
|
||||
$mform->addHelpButton('minute', 'taskscheduleminute', 'tool_task');
|
||||
$mform->addRule('minute', get_string('required'), 'required');
|
||||
|
||||
$mform->addElement('text', 'hour', get_string('taskschedulehour', 'tool_task'));
|
||||
$mform->setType('hour', PARAM_RAW);
|
||||
$mform->addHelpButton('hour', 'taskschedulehour', 'tool_task');
|
||||
$mform->addRule('hour', get_string('required'), 'required');
|
||||
|
||||
$mform->addElement('text', 'day', get_string('taskscheduleday', 'tool_task'));
|
||||
$mform->setType('day', PARAM_RAW);
|
||||
$mform->addHelpButton('day', 'taskscheduleday', 'tool_task');
|
||||
$mform->addRule('day', get_string('required'), 'required');
|
||||
|
||||
$mform->addElement('text', 'month', get_string('taskschedulemonth', 'tool_task'));
|
||||
$mform->setType('month', PARAM_RAW);
|
||||
$mform->addHelpButton('month', 'taskschedulemonth', 'tool_task');
|
||||
$mform->addRule('month', get_string('required'), 'required');
|
||||
|
||||
$mform->addElement('text', 'dayofweek', get_string('taskscheduledayofweek', 'tool_task'));
|
||||
$mform->setType('dayofweek', PARAM_RAW);
|
||||
$mform->addHelpButton('dayofweek', 'taskscheduledayofweek', 'tool_task');
|
||||
$mform->addRule('dayofweek', get_string('required'), 'required');
|
||||
|
||||
$mform->addElement('advcheckbox', 'disabled', get_string('disabled', 'tool_task'));
|
||||
$mform->addHelpButton('disabled', 'disabled', 'tool_task');
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
@tool @tool_task @javascript
|
||||
Feature: Manage scheduled tasks
|
||||
In order to configure scheduled tasks
|
||||
As an admin
|
||||
I need to be able to disable, enable, edit and reset to default scheduled tasks
|
||||
|
||||
Background:
|
||||
Given I log in as "admin"
|
||||
And I navigate to "Scheduled tasks" node in "Site administration > Server"
|
||||
|
||||
Scenario: Disable scheduled task
|
||||
When I click on "Edit task schedule: Log table cleanup" "link" in the "Log table cleanup" "table_row"
|
||||
Then I should see "Edit task schedule: Log table cleanup"
|
||||
And I set the following fields to these values:
|
||||
| disabled | 1 |
|
||||
And I press "Save changes"
|
||||
Then I should see "Changes saved"
|
||||
And I should see "Disabled" in the "Log table cleanup" "table_row"
|
||||
|
||||
Scenario: Enable scheduled task
|
||||
When I click on "Edit task schedule: Log table cleanup" "link" in the "Log table cleanup" "table_row"
|
||||
Then I should see "Edit task schedule: Log table cleanup"
|
||||
And I set the following fields to these values:
|
||||
| disabled | 0 |
|
||||
And I press "Save changes"
|
||||
Then I should see "Changes saved"
|
||||
And I should not see "Task disabled" in the "Log table cleanup" "table_row"
|
||||
|
||||
Scenario: Edit scheduled task
|
||||
When I click on "Edit task schedule: Log table cleanup" "link" in the "Log table cleanup" "table_row"
|
||||
Then I should see "Edit task schedule: Log table cleanup"
|
||||
And I set the following fields to these values:
|
||||
| minute | */5 |
|
||||
| hour | 1 |
|
||||
| day | 2 |
|
||||
| month | 3 |
|
||||
| dayofweek | 4 |
|
||||
And I press "Save changes"
|
||||
Then I should see "Changes saved"
|
||||
And the following should exist in the "admintable" table:
|
||||
| Component | Minute | Hour | Day | Day of week | Month |
|
||||
| Standard log | */5 | 1 | 2 | 4 | 3 |
|
||||
|
||||
Scenario: Reset scheduled task to default
|
||||
When I click on "Edit task schedule: Log table cleanup" "link" in the "Log table cleanup" "table_row"
|
||||
Then I should see "Edit task schedule: Log table cleanup"
|
||||
And I set the following fields to these values:
|
||||
| resettodefaults | 1 |
|
||||
And I press "Save changes"
|
||||
Then I should see "Changes saved"
|
||||
And the following should not exist in the "admintable" table:
|
||||
| Name | Component | Minute | Hour | Day | Day of week | Month |
|
||||
| Log table cleanup | Standard log | */5 | 1 | 2 | 4 | 3 |
|
||||
@@ -24,7 +24,6 @@ $adminroot = admin_get_root(); // need all settings
|
||||
// now we'll deal with the case that the admin has submitted the form with new settings
|
||||
if ($data = data_submitted() and confirm_sesskey()) {
|
||||
$count = admin_write_settings($data);
|
||||
$adminroot = admin_get_root(true); //reload tree
|
||||
}
|
||||
|
||||
$newsettings = admin_output_new_settings_by_page($adminroot);
|
||||
|
||||
@@ -157,6 +157,13 @@ class external_service_form extends moodleform {
|
||||
|
||||
$errors = parent::validation($data, $files);
|
||||
|
||||
// Add field validation check for duplicate name.
|
||||
if ($webservice = $DB->get_record('external_services', array('name' => $data['name']))) {
|
||||
if (empty($data['id']) || $webservice->id != $data['id']) {
|
||||
$errors['name'] = get_string('nameexists', 'webservice');
|
||||
}
|
||||
}
|
||||
|
||||
// Add field validation check for duplicate shortname.
|
||||
// Allow duplicated "empty" shortnames.
|
||||
if (!empty($data['shortname'])) {
|
||||
|
||||
@@ -113,6 +113,12 @@ class auth_plugin_cas extends auth_plugin_ldap {
|
||||
|
||||
// If the multi-authentication setting is used, check for the param before connecting to CAS.
|
||||
if ($this->config->multiauth) {
|
||||
|
||||
// If there is an authentication error, stay on the default authentication page.
|
||||
if (!empty($SESSION->loginerrormsg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$authCAS = optional_param('authCAS', '', PARAM_RAW);
|
||||
if ($authCAS == 'NOCAS') {
|
||||
return;
|
||||
|
||||
@@ -143,7 +143,8 @@ class auth_plugin_shibboleth extends auth_plugin_base {
|
||||
$configarray = (array) $this->config;
|
||||
|
||||
$moodleattributes = array();
|
||||
foreach ($this->userfields as $field) {
|
||||
$userfields = array_merge($this->userfields, $this->get_custom_user_profile_fields());
|
||||
foreach ($userfields as $field) {
|
||||
if (isset($configarray["field_map_$field"])) {
|
||||
$moodleattributes[$field] = $configarray["field_map_$field"];
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ urn:mace:organization2:providerID, Example Organization 2, /Shibboleth.sso/WAYF/
|
||||
|
||||
<?php
|
||||
|
||||
print_auth_lock_options($this->authtype, $user_fields, '<!-- empty help -->', true, false);
|
||||
print_auth_lock_options($this->authtype, $user_fields, '<!-- empty help -->', true, false, $this->get_custom_user_profile_fields());
|
||||
|
||||
?>
|
||||
</table>
|
||||
|
||||
@@ -608,12 +608,34 @@ abstract class info {
|
||||
}
|
||||
$tree = $this->get_availability_tree();
|
||||
$checker = new capability_checker($this->get_context());
|
||||
|
||||
// Filter using availability tree.
|
||||
$this->modinfo = get_fast_modinfo($this->get_course());
|
||||
$result = $tree->filter_user_list($users, false, $this, $checker);
|
||||
$filtered = $tree->filter_user_list($users, false, $this, $checker);
|
||||
$this->modinfo = null;
|
||||
|
||||
// Include users in the result if they're either in the filtered list,
|
||||
// or they have viewhidden. This logic preserves ordering of the
|
||||
// passed users array.
|
||||
$result = array();
|
||||
$canviewhidden = $checker->get_users_by_capability($this->get_view_hidden_capability());
|
||||
foreach ($users as $userid => $data) {
|
||||
if (array_key_exists($userid, $filtered) || array_key_exists($userid, $canviewhidden)) {
|
||||
$result[$userid] = $users[$userid];
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the capability used to view hidden activities/sections (as
|
||||
* appropriate).
|
||||
*
|
||||
* @return string Name of capability used to view hidden items of this type
|
||||
*/
|
||||
protected abstract function get_view_hidden_capability();
|
||||
|
||||
/**
|
||||
* Formats the $cm->availableinfo string for display. This includes
|
||||
* filling in the names of any course-modules that might be mentioned.
|
||||
|
||||
@@ -109,6 +109,10 @@ class info_module extends info {
|
||||
return parent::filter_user_list($filtered);
|
||||
}
|
||||
|
||||
protected function get_view_hidden_capability() {
|
||||
return 'moodle/course:viewhiddenactivities';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an activity is visible to the given user.
|
||||
*
|
||||
@@ -157,7 +161,12 @@ class info_module extends info {
|
||||
if (is_object($cmorid)) {
|
||||
$cmorid = $cmorid->id;
|
||||
}
|
||||
$cm = $DB->get_record('course_modules', array('id' => $cmorid), '*', MUST_EXIST);
|
||||
$cm = $DB->get_record('course_modules', array('id' => $cmorid));
|
||||
if (!$cm) {
|
||||
// In some error cases, the course module may not exist.
|
||||
debugging('info_module::is_user_visible called with invalid cmid ' . $cmorid, DEBUG_DEVELOPER);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the groupmembersonly feature.
|
||||
|
||||
@@ -56,6 +56,10 @@ class info_section extends info {
|
||||
return \context_course::instance($this->get_course()->id);
|
||||
}
|
||||
|
||||
protected function get_view_hidden_capability() {
|
||||
return 'moodle/course:viewhiddensections';
|
||||
}
|
||||
|
||||
protected function set_in_database($availability) {
|
||||
global $DB;
|
||||
$DB->set_field('course_sections', 'availability', $availability,
|
||||
|
||||
@@ -139,7 +139,8 @@ abstract class tree_node {
|
||||
|
||||
/**
|
||||
* Tests this condition against a user list. Users who do not meet the
|
||||
* condition will be removed from the list.
|
||||
* condition will be removed from the list, unless they have the ability
|
||||
* to view hidden activities/sections.
|
||||
*
|
||||
* This function must be implemented if is_applied_to_user_lists returns
|
||||
* true. Otherwise it will not be called.
|
||||
@@ -150,6 +151,10 @@ abstract class tree_node {
|
||||
* Within this function, if you need to check capabilities, please use
|
||||
* the provided checker which caches results where possible.
|
||||
*
|
||||
* Conditions do not need to check the viewhiddenactivities or
|
||||
* viewhiddensections capabilities. These are handled by
|
||||
* core_availability\info::filter_user_list.
|
||||
*
|
||||
* @param array $users Array of userid => object
|
||||
* @param bool $not True if this condition is applying in negative mode
|
||||
* @param \core_availability\info $info Item we're checking
|
||||
|
||||
@@ -55,7 +55,7 @@ class frontend extends \core_availability\frontend {
|
||||
&& $item->itemtype == 'mod') {
|
||||
continue;
|
||||
}
|
||||
$gradeoptions[$id] = $item->get_name();
|
||||
$gradeoptions[$id] = $item->get_name(true);
|
||||
}
|
||||
\core_collator::asort($gradeoptions);
|
||||
|
||||
|
||||
@@ -109,17 +109,17 @@ Feature: display_availability
|
||||
|
||||
# Page 1 display still there but should be dimmed and not a link.
|
||||
Then I should see "Page 1" in the "#section-1 .dimmed_text" "css_element"
|
||||
And ".activityinstance a" "css_element" should not exist in the "#section-1" "css_element"
|
||||
And ".activityinstance a" "css_element" should not exist in the "Topic 1" "section"
|
||||
|
||||
# Date display should be present.
|
||||
And I should see "Available until" in the "#section-1" "css_element"
|
||||
And I should see "Available until" in the "Topic 1" "section"
|
||||
|
||||
# Page 2 display not there at all
|
||||
And I should not see "Page 2" in the "region-main" "region"
|
||||
|
||||
# Page 3 display and link
|
||||
And I should see "Page 3" in the "region-main" "region"
|
||||
And ".activityinstance a" "css_element" should exist in the "#section-3" "css_element"
|
||||
And ".activityinstance a" "css_element" should exist in the "Topic 3" "section"
|
||||
|
||||
@javascript
|
||||
Scenario: Section availability display
|
||||
|
||||
+4
@@ -60,6 +60,10 @@ class mock_info extends info {
|
||||
return \context_course::instance($this->get_course()->id);
|
||||
}
|
||||
|
||||
protected function get_view_hidden_capability() {
|
||||
return 'moodle/course:viewhiddensections';
|
||||
}
|
||||
|
||||
protected function set_in_database($availability) {
|
||||
}
|
||||
|
||||
|
||||
@@ -421,7 +421,14 @@ class info_testcase extends \advanced_testcase {
|
||||
$u1 = $generator->create_user();
|
||||
$u2 = $generator->create_user();
|
||||
$u3 = $generator->create_user();
|
||||
$studentroleid = $DB->get_field('role', 'id', array('shortname' => 'student'), MUST_EXIST);
|
||||
$allusers = array($u1->id => $u1, $u2->id => $u2, $u3->id => $u3);
|
||||
$generator->enrol_user($u1->id, $course->id, $studentroleid);
|
||||
$generator->enrol_user($u2->id, $course->id, $studentroleid);
|
||||
$generator->enrol_user($u3->id, $course->id, $studentroleid);
|
||||
|
||||
// Page 2 allows access to users 2 and 3, while section 2 allows access
|
||||
// to users 1 and 2.
|
||||
$pagegen = $generator->get_plugin_generator('mod_page');
|
||||
$page = $pagegen->create_instance(array('course' => $course));
|
||||
$page2 = $pagegen->create_instance(array('course' => $course,
|
||||
@@ -477,5 +484,19 @@ class info_testcase extends \advanced_testcase {
|
||||
$info = new info_module($modinfo->get_cm($page2->cmid));
|
||||
$this->assertEquals(array($u2->id),
|
||||
array_keys($info->filter_user_list($allusers)));
|
||||
|
||||
// If the students have viewhiddenactivities, they get past the module
|
||||
// restriction.
|
||||
role_change_permission($studentroleid, context_module::instance($page2->cmid),
|
||||
'moodle/course:viewhiddenactivities', CAP_ALLOW);
|
||||
$expected = array($u1->id, $u2->id);
|
||||
$this->assertEquals($expected, array_keys($info->filter_user_list($allusers)));
|
||||
|
||||
// If they have viewhiddensections, they also get past the section
|
||||
// restriction.
|
||||
role_change_permission($studentroleid, context_course::instance($course->id),
|
||||
'moodle/course:viewhiddensections', CAP_ALLOW);
|
||||
$expected = array($u1->id, $u2->id, $u3->id);
|
||||
$this->assertEquals($expected, array_keys($info->filter_user_list($allusers)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ abstract class backup_factory {
|
||||
|
||||
// Create database_logger, observing $CFG->backup_database_logger_level and defaulting to LOG_WARNING
|
||||
// and pointing to the backup_logs table
|
||||
$dllevel = isset($CFG->backup_database_logger_level) ? $CFG->backup_database_logger_level : backup::LOG_WARNING;
|
||||
$dllevel = isset($CFG->backup_database_logger_level) ? $CFG->backup_database_logger_level : $dfltloglevel;
|
||||
$columns = array('backupid' => $backupid);
|
||||
$enabledloggers[] = new database_logger($dllevel, 'timecreated', 'loglevel', 'message', 'backup_logs', $columns);
|
||||
|
||||
|
||||
@@ -33,6 +33,19 @@ require_once($CFG->dirroot . '/backup/util/helper/backup_cron_helper.class.php')
|
||||
*/
|
||||
class backup_cron_helper_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* @var String keep system default timezone.
|
||||
*/
|
||||
protected $systemdefaulttimezone;
|
||||
|
||||
/**
|
||||
* Setup.
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->systemdefaulttimezone = date_default_timezone_get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test {@link backup_cron_automated_helper::calculate_next_automated_backup}.
|
||||
*/
|
||||
@@ -457,4 +470,12 @@ class backup_cron_helper_testcase extends advanced_testcase {
|
||||
$this->assertEquals($expected, date('w-H:i', $next));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set timezone back to default.
|
||||
*/
|
||||
protected function tearDown() {
|
||||
date_default_timezone_set($this->systemdefaulttimezone);
|
||||
parent::tearDown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,6 @@ Feature: Duplicate activities
|
||||
| Name | Duplicated database name |
|
||||
| Description | Duplicated database description |
|
||||
And I press "Save and return to course"
|
||||
Then I should see "Original database name" in the "#section-1" "css_element"
|
||||
And I should see "Duplicated database name" in the "#section-1" "css_element"
|
||||
Then I should see "Original database name" in the "Topic 1" "section"
|
||||
And I should see "Duplicated database name" in the "Topic 1" "section"
|
||||
And "Original database name" "link" should appear before "Duplicated database name" "link"
|
||||
|
||||
@@ -129,5 +129,5 @@ Feature: Restore Moodle 2 course backups
|
||||
And section "3" should be hidden
|
||||
And section "7" should be hidden
|
||||
And section "15" should be visible
|
||||
And I should see "Test URL name" in the "#section-3" "css_element"
|
||||
And I should see "Test forum name" in the "#section-1" "css_element"
|
||||
And I should see "Test URL name" in the "Topic 3" "section"
|
||||
And I should see "Test forum name" in the "Topic 1" "section"
|
||||
|
||||
@@ -49,7 +49,7 @@ $assertion = filter_input(
|
||||
// Audience is the site url scheme + host + port only.
|
||||
$wwwparts = parse_url($CFG->wwwroot);
|
||||
$audience = $wwwparts['scheme'] . '://' . $wwwparts['host'];
|
||||
$audience .= isset($wwwparts['port']) ? $wwwparts['port'] : '';
|
||||
$audience .= isset($wwwparts['port']) ? ':' . $wwwparts['port'] : '';
|
||||
$params = 'assertion=' . urlencode($assertion) . '&audience=' .
|
||||
urlencode($audience);
|
||||
|
||||
|
||||
+5
-6
@@ -26,6 +26,7 @@
|
||||
|
||||
require_once(dirname(dirname(__FILE__)) . '/config.php');
|
||||
require_once($CFG->libdir . '/badgeslib.php');
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
|
||||
$id = required_param('hash', PARAM_ALPHANUM);
|
||||
$bake = optional_param('bake', 0, PARAM_BOOL);
|
||||
@@ -37,12 +38,10 @@ $badge = new issued_badge($id);
|
||||
|
||||
if ($bake && ($badge->recipient->id == $USER->id)) {
|
||||
$name = str_replace(' ', '_', $badge->badgeclass['name']) . '.png';
|
||||
ob_start();
|
||||
$file = badges_bake($id, $badge->badgeid);
|
||||
header('Content-Type: image/png');
|
||||
header('Content-Disposition: attachment; filename="'. $name .'"');
|
||||
readfile($file);
|
||||
ob_flush();
|
||||
$filehash = badges_bake($id, $badge->badgeid, $USER->id, true);
|
||||
$fs = get_file_storage();
|
||||
$file = $fs->get_file_by_hash($filehash);
|
||||
send_stored_file($file, 0, 0, true, array('filename' => $name));
|
||||
}
|
||||
|
||||
$PAGE->set_url('/badges/badge.php', array('hash' => $id));
|
||||
|
||||
+5
-8
@@ -26,6 +26,7 @@
|
||||
|
||||
require_once(dirname(dirname(__FILE__)) . '/config.php');
|
||||
require_once($CFG->libdir . '/badgeslib.php');
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
|
||||
$page = optional_param('page', 0, PARAM_INT);
|
||||
$search = optional_param('search', '', PARAM_CLEAN);
|
||||
@@ -71,17 +72,13 @@ if ($hide) {
|
||||
require_sesskey();
|
||||
$badge = new badge($download);
|
||||
$name = str_replace(' ', '_', $badge->name) . '.png';
|
||||
ob_start();
|
||||
$file = badges_bake($hash, $download);
|
||||
header('Content-Type: image/png');
|
||||
header('Content-Disposition: attachment; filename="'. $name .'"');
|
||||
readfile($file);
|
||||
ob_flush();
|
||||
$filehash = badges_bake($hash, $download, $USER->id, true);
|
||||
$fs = get_file_storage();
|
||||
$file = $fs->get_file_by_hash($filehash);
|
||||
send_stored_file($file, 0, 0, true, array('filename' => $name));
|
||||
} else if ($downloadall) {
|
||||
require_sesskey();
|
||||
ob_start();
|
||||
badges_download($USER->id);
|
||||
ob_flush();
|
||||
}
|
||||
|
||||
$context = context_user::instance($USER->id);
|
||||
|
||||
@@ -180,6 +180,95 @@ class core_badges_badgeslib_testcase extends advanced_testcase {
|
||||
$this->assertCount(2, $badge->get_awards());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the {@link badges_get_user_badges()} function in lib/badgeslib.php
|
||||
*/
|
||||
public function test_badges_get_user_badges() {
|
||||
global $DB;
|
||||
|
||||
// Messaging is not compatible with transactions.
|
||||
$this->preventResetByRollback();
|
||||
|
||||
$badges = array();
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
|
||||
// Record the current time, we need to be precise about a couple of things.
|
||||
$now = time();
|
||||
// Create 11 badges with which to test.
|
||||
for ($i = 1; $i <= 11; $i++) {
|
||||
// Mock up a badge.
|
||||
$badge = new stdClass();
|
||||
$badge->id = null;
|
||||
$badge->name = "Test badge $i";
|
||||
$badge->description = "Testing badges $i";
|
||||
$badge->timecreated = $now - 12;
|
||||
$badge->timemodified = $now - 12;
|
||||
$badge->usercreated = $user1->id;
|
||||
$badge->usermodified = $user1->id;
|
||||
$badge->issuername = "Test issuer";
|
||||
$badge->issuerurl = "http://issuer-url.domain.co.nz";
|
||||
$badge->issuercontact = "issuer@example.com";
|
||||
$badge->expiredate = null;
|
||||
$badge->expireperiod = null;
|
||||
$badge->type = BADGE_TYPE_SITE;
|
||||
$badge->courseid = null;
|
||||
$badge->messagesubject = "Test message subject for badge $i";
|
||||
$badge->message = "Test message body for badge $i";
|
||||
$badge->attachment = 1;
|
||||
$badge->notification = 0;
|
||||
$badge->status = BADGE_STATUS_INACTIVE;
|
||||
|
||||
$badgeid = $DB->insert_record('badge', $badge, true);
|
||||
$badges[$badgeid] = new badge($badgeid);
|
||||
$badges[$badgeid]->issue($user2->id, true);
|
||||
// Check it all actually worked.
|
||||
$this->assertCount(1, $badges[$badgeid]->get_awards());
|
||||
|
||||
// Hack the database to adjust the time each badge was issued.
|
||||
// The alternative to this is sleep which is a no-no in unit tests.
|
||||
$DB->set_field('badge_issued', 'dateissued', $now - 11 + $i, array('userid' => $user2->id, 'badgeid' => $badgeid));
|
||||
}
|
||||
|
||||
// Make sure the first user has no badges.
|
||||
$result = badges_get_user_badges($user1->id);
|
||||
$this->assertInternalType('array', $result);
|
||||
$this->assertCount(0, $result);
|
||||
|
||||
// Check that the second user has the expected 11 badges.
|
||||
$result = badges_get_user_badges($user2->id);
|
||||
$this->assertCount(11, $result);
|
||||
|
||||
// Test pagination.
|
||||
// Ordering is by time issued desc, so things will come out with the last awarded badge first.
|
||||
$result = badges_get_user_badges($user2->id, 0, 0, 4);
|
||||
$this->assertCount(4, $result);
|
||||
$lastbadgeissued = reset($result);
|
||||
$this->assertSame('Test badge 11', $lastbadgeissued->name);
|
||||
// Page 2. Expecting 4 results again.
|
||||
$result = badges_get_user_badges($user2->id, 0, 1, 4);
|
||||
$this->assertCount(4, $result);
|
||||
$lastbadgeissued = reset($result);
|
||||
$this->assertSame('Test badge 7', $lastbadgeissued->name);
|
||||
// Page 3. Expecting just three results here.
|
||||
$result = badges_get_user_badges($user2->id, 0, 2, 4);
|
||||
$this->assertCount(3, $result);
|
||||
$lastbadgeissued = reset($result);
|
||||
$this->assertSame('Test badge 3', $lastbadgeissued->name);
|
||||
// Page 4.... there is no page 4.
|
||||
$result = badges_get_user_badges($user2->id, 0, 3, 4);
|
||||
$this->assertCount(0, $result);
|
||||
|
||||
// Test search.
|
||||
$result = badges_get_user_badges($user2->id, 0, 0, 0, 'badge 1');
|
||||
$this->assertCount(3, $result);
|
||||
$lastbadgeissued = reset($result);
|
||||
$this->assertSame('Test badge 11', $lastbadgeissued->name);
|
||||
// The term Totara doesn't appear anywhere in the badges.
|
||||
$result = badges_get_user_badges($user2->id, 0, 0, 0, 'Totara');
|
||||
$this->assertCount(0, $result);
|
||||
}
|
||||
|
||||
public function data_for_message_from_template() {
|
||||
return array(
|
||||
array(
|
||||
|
||||
@@ -212,8 +212,7 @@ Feature: Award badges
|
||||
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
|
||||
And I press "Create badge"
|
||||
And I set the field "type" to "Course completion"
|
||||
And I set the following fields to these values:
|
||||
| grade_2 | 0 |
|
||||
And I set the field with xpath "//fieldset/input[1]" to "0"
|
||||
And I press "Save"
|
||||
And I press "Enable access"
|
||||
When I press "Continue"
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
$string['activityoverview'] = 'You have {$a}s that need attention';
|
||||
$string['alwaysshowall'] = 'Always show all';
|
||||
$string['collapseall'] = 'Collapse all course lists';
|
||||
$string['configotherexpanded'] = 'If enabled, other courses will be expanded by default unless overriden by user preferences.';
|
||||
$string['configotherexpanded'] = 'If enabled, other courses will be expanded by default unless overridden by user preferences.';
|
||||
$string['configpreservestates'] = 'If enabled, the collapsed/expanded states set by the user are stored and used on each load.';
|
||||
$string['course_overview:addinstance'] = 'Add a new course overview block';
|
||||
$string['course_overview:myaddinstance'] = 'Add a new course overview block to My home';
|
||||
|
||||
@@ -584,9 +584,21 @@ class block_base {
|
||||
&& $page->context->contextlevel == CONTEXT_USER // Page belongs to a user
|
||||
&& $page->context->instanceid == $USER->id // Page belongs to this user
|
||||
&& $page->pagetype == 'my-index') { // Ensure we are on the My Moodle page
|
||||
$capability = 'block/' . $this->name() . ':myaddinstance';
|
||||
return $this->has_add_block_capability($page, $capability)
|
||||
&& has_capability('moodle/my:manageblocks', $page->context);
|
||||
|
||||
// If the block cannot be displayed on /my it is ok if the myaddinstance capability is not defined.
|
||||
$formats = $this->applicable_formats();
|
||||
// Is 'my' explicitly forbidden?
|
||||
// If 'all' has not been allowed, has 'my' been explicitly allowed?
|
||||
if ((isset($formats['my']) && $formats['my'] == false)
|
||||
|| (empty($formats['all']) && empty($formats['my']))) {
|
||||
|
||||
// Block cannot be added to /my regardless of capabilities.
|
||||
return false;
|
||||
} else {
|
||||
$capability = 'block/' . $this->name() . ':myaddinstance';
|
||||
return $this->has_add_block_capability($page, $capability)
|
||||
&& has_capability('moodle/my:manageblocks', $page->context);
|
||||
}
|
||||
}
|
||||
|
||||
$capability = 'block/' . $this->name() . ':addinstance';
|
||||
|
||||
@@ -56,3 +56,16 @@ Feature: Add and configure blocks throughout the site
|
||||
And I follow "Course 1"
|
||||
And I follow "Turn editing on"
|
||||
Then I should see "Assign roles in Search forums block"
|
||||
|
||||
@javascript
|
||||
Scenario: Blocks can safely be customised
|
||||
Given I log in as "admin"
|
||||
And I click on "My home" "link" in the "Navigation" "block"
|
||||
And I press "Customise this page"
|
||||
And I add the "HTML" block
|
||||
And I configure the "(new HTML block)" block
|
||||
And I set the following fields to these values:
|
||||
| Block title | Foo " onload="document.getElementsByTagName('body')[0].remove()" alt="
|
||||
| Content | Example
|
||||
When I press "Save changes"
|
||||
Then I should see "Course overview"
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
@core @core_block
|
||||
Feature: Show hidden blocks in a docked block region when editing
|
||||
In order to edit blocks in a hidden region
|
||||
As a teacher
|
||||
I need to be able to see the blocks when editing is on
|
||||
|
||||
Background:
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | format |
|
||||
| Course 1 | C1 | topics |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| admin | C1 | editingteacher |
|
||||
And I log in as "admin"
|
||||
And I follow "Course 1"
|
||||
And I turn editing mode on
|
||||
# Hide all the blocks in the non-default region
|
||||
And I configure the "Search forums" block
|
||||
And I set the following fields to these values:
|
||||
| Visible | No |
|
||||
And I click on "Save changes" "button"
|
||||
And I configure the "Latest news" block
|
||||
And I set the following fields to these values:
|
||||
| Visible | No |
|
||||
And I click on "Save changes" "button"
|
||||
And I configure the "Upcoming events" block
|
||||
And I set the following fields to these values:
|
||||
| Visible | No |
|
||||
And I click on "Save changes" "button"
|
||||
And I configure the "Recent activity" block
|
||||
And I set the following fields to these values:
|
||||
| Visible | No |
|
||||
When I click on "Save changes" "button"
|
||||
# Editing is on so they should be visible
|
||||
Then I should see "Search forums"
|
||||
And I should see "Latest news"
|
||||
And I should see "Upcoming events"
|
||||
And I should see "Recent activity"
|
||||
And I turn editing mode off
|
||||
# Editing is off, so they should no longer be visible
|
||||
And I should not see "Search forums"
|
||||
And I should not see "Latest news"
|
||||
And I should not see "Upcoming events"
|
||||
And I should not see "Recent activity"
|
||||
|
||||
@javascript
|
||||
Scenario: Check that a region with only hidden blocks is not docked in editing mode (javascript enabled)
|
||||
|
||||
Scenario: Check that a region with only hidden blocks is not docked in editing mode (javascript disabled)
|
||||
@@ -0,0 +1,28 @@
|
||||
@core @core_block
|
||||
Feature: Block visibility
|
||||
In order to configure blocks visibility
|
||||
As a teacher
|
||||
I need to show and hide blocks on a page
|
||||
|
||||
Background:
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And I log in as "admin"
|
||||
And I am on homepage
|
||||
And I follow "Course 1"
|
||||
And I follow "Turn editing on"
|
||||
|
||||
@javascript
|
||||
Scenario: Hiding all blocks on the page should remove the column they're in
|
||||
Given I open the "Search forums" blocks action menu
|
||||
And I click on "Hide Search forums block" "link" in the "Search forums" "block"
|
||||
And I open the "Latest news" blocks action menu
|
||||
And I click on "Hide Latest news block" "link" in the "Latest news" "block"
|
||||
And I open the "Upcoming events" blocks action menu
|
||||
And I click on "Hide Upcoming events block" "link" in the "Upcoming events" "block"
|
||||
And I open the "Recent activity" blocks action menu
|
||||
When I click on "Hide Recent activity block" "link" in the "Recent activity" "block"
|
||||
Then ".empty-region-side-post" "css_element" should not exist in the "body" "css_element"
|
||||
And I follow "Turn editing off"
|
||||
And ".empty-region-side-post" "css_element" should exist in the "body" "css_element"
|
||||
+3
-2
@@ -991,7 +991,7 @@ function calendar_filter_controls_element(moodle_url $url, $type) {
|
||||
$str = get_string('show'.$typeforhumans.'events', 'calendar');
|
||||
}
|
||||
$content = html_writer::start_tag('li', array('class' => 'calendar_event'));
|
||||
$content .= html_writer::start_tag('a', array('href' => $url));
|
||||
$content .= html_writer::start_tag('a', array('href' => $url, 'rel' => 'nofollow'));
|
||||
$content .= html_writer::tag('span', $icon, array('class' => $class));
|
||||
$content .= html_writer::tag('span', $str, array('class' => 'eventname'));
|
||||
$content .= html_writer::end_tag('a');
|
||||
@@ -2953,11 +2953,12 @@ function calendar_add_icalendar_event($event, $courseid, $subscriptionid, $timez
|
||||
$description = '';
|
||||
} else {
|
||||
$description = $event->properties['DESCRIPTION'][0]->value;
|
||||
$description = clean_param($description, PARAM_NOTAGS);
|
||||
$description = str_replace('\n', '<br />', $description);
|
||||
$description = str_replace('\\', '', $description);
|
||||
$description = preg_replace('/\s+/', ' ', $description);
|
||||
}
|
||||
$eventrecord->description = clean_param($description, PARAM_NOTAGS);
|
||||
$eventrecord->description = $description;
|
||||
|
||||
// Probably a repeating event with RRULE etc. TODO: skip for now.
|
||||
if (empty($event->properties['DTSTART'][0]->value)) {
|
||||
|
||||
+1
-1
@@ -8,6 +8,6 @@
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "3.7.*",
|
||||
"phpunit/dbUnit": "1.2.*",
|
||||
"moodlehq/behat-extension": "1.27.12"
|
||||
"moodlehq/behat-extension": "1.27.13"
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -242,7 +242,7 @@ $CFG->admin = 'admin';
|
||||
// $CFG->session_memcached_save_path = '127.0.0.1:11211';
|
||||
// $CFG->session_memcached_prefix = 'memc.sess.key.';
|
||||
// $CFG->session_memcached_acquire_lock_timeout = 120;
|
||||
// $CFG->session_memcached_lock_expire = 7200; // Ignored if memcached extension <= 2.1.0
|
||||
// $CFG->session_memcached_lock_expire = 7200; // Ignored if PECL memcached is below version 2.2.0
|
||||
//
|
||||
// Memcache session handler (requires memcached server and memcache extension):
|
||||
// $CFG->session_handler_class = '\core\session\memcache';
|
||||
@@ -507,7 +507,7 @@ $CFG->admin = 'admin';
|
||||
// Uses lock files stored by default in the dataroot. Whether this
|
||||
// works on clusters depends on the file system used for the dataroot.
|
||||
//
|
||||
// "\\core\\lock\\db_row_lock_factory" - DB locking based on table rows.
|
||||
// "\\core\\lock\\db_record_lock_factory" - DB locking based on table rows.
|
||||
//
|
||||
// "\\core\\lock\\postgres_lock_factory" - DB locking based on postgres advisory locks.
|
||||
//
|
||||
|
||||
+12
-6
@@ -77,11 +77,14 @@ class core_course_external extends external_api {
|
||||
//retrieve the course
|
||||
$course = $DB->get_record('course', array('id' => $params['courseid']), '*', MUST_EXIST);
|
||||
|
||||
//check course format exist
|
||||
if (!file_exists($CFG->dirroot . '/course/format/' . $course->format . '/lib.php')) {
|
||||
throw new moodle_exception('cannotgetcoursecontents', 'webservice', '', null, get_string('courseformatnotfound', 'error', '', $course->format));
|
||||
} else {
|
||||
require_once($CFG->dirroot . '/course/format/' . $course->format . '/lib.php');
|
||||
if ($course->id != SITEID) {
|
||||
// Check course format exist.
|
||||
if (!file_exists($CFG->dirroot . '/course/format/' . $course->format . '/lib.php')) {
|
||||
throw new moodle_exception('cannotgetcoursecontents', 'webservice', '', null,
|
||||
get_string('courseformatnotfound', 'error', $course->format));
|
||||
} else {
|
||||
require_once($CFG->dirroot . '/course/format/' . $course->format . '/lib.php');
|
||||
}
|
||||
}
|
||||
|
||||
// now security checks
|
||||
@@ -217,6 +220,7 @@ class core_course_external extends external_api {
|
||||
'id' => new external_value(PARAM_INT, 'activity id'),
|
||||
'url' => new external_value(PARAM_URL, 'activity url', VALUE_OPTIONAL),
|
||||
'name' => new external_value(PARAM_RAW, 'activity module name'),
|
||||
'instance' => new external_value(PARAM_INT, 'instance id', VALUE_OPTIONAL),
|
||||
'description' => new external_value(PARAM_RAW, 'activity description', VALUE_OPTIONAL),
|
||||
'visible' => new external_value(PARAM_INT, 'is the module visible', VALUE_OPTIONAL),
|
||||
'modicon' => new external_value(PARAM_URL, 'activity icon url'),
|
||||
@@ -849,6 +853,7 @@ class core_course_external extends external_api {
|
||||
|
||||
// Check if the current user has enought permissions.
|
||||
if (!can_delete_course($courseid)) {
|
||||
fix_course_sortorder();
|
||||
throw new moodle_exception('cannotdeletecategorycourse', 'error',
|
||||
'', format_string($course->fullname)." (id: $courseid)");
|
||||
}
|
||||
@@ -857,6 +862,7 @@ class core_course_external extends external_api {
|
||||
}
|
||||
|
||||
$transaction->allow_commit();
|
||||
fix_course_sortorder();
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -1028,7 +1034,7 @@ class core_course_external extends external_api {
|
||||
|
||||
// Check if we need to unzip the file because the backup temp dir does not contains backup files.
|
||||
if (!file_exists($backupbasepath . "/moodle_backup.xml")) {
|
||||
$file->extract_to_pathname(get_file_packer(), $backupbasepath);
|
||||
$file->extract_to_pathname(get_file_packer('application/vnd.moodle.backup'), $backupbasepath);
|
||||
}
|
||||
|
||||
// Create new course.
|
||||
|
||||
@@ -473,7 +473,9 @@ class behat_course extends behat_base {
|
||||
|
||||
// The activity should not be dimmed.
|
||||
try {
|
||||
$this->find('css', 'a.dimmed', false, $activitynode);
|
||||
$xpath = "/descendant-or-self::a[contains(concat(' ', normalize-space(@class), ' '), ' dimmed ')] | ".
|
||||
"/descendant-or-self::div[contains(concat(' ', normalize-space(@class), ' '), ' dimmed_text ')]";
|
||||
$this->find('xpath', $xpath, false, $activitynode);
|
||||
throw new ExpectationException('"' . $activityname . '" is hidden', $this->getSession());
|
||||
} catch (ElementNotFoundException $e) {
|
||||
// All ok.
|
||||
@@ -501,7 +503,9 @@ class behat_course extends behat_base {
|
||||
|
||||
// Should be hidden.
|
||||
$exception = new ExpectationException('"' . $activityname . '" is not dimmed', $this->getSession());
|
||||
$this->find('css', 'a.dimmed', $exception, $activitynode);
|
||||
$xpath = "/descendant-or-self::a[contains(concat(' ', normalize-space(@class), ' '), ' dimmed ')] | ".
|
||||
"/descendant-or-self::div[contains(concat(' ', normalize-space(@class), ' '), ' dimmed_text ')]";
|
||||
$this->find('xpath', $xpath, $exception, $activitynode);
|
||||
|
||||
// Also 'Show' icon.
|
||||
$noshowexception = new ExpectationException('"' . $activityname . '" don\'t have a "' . get_string('show') . '" icon', $this->getSession());
|
||||
|
||||
@@ -42,18 +42,18 @@ Feature: Course activity controls works as expected
|
||||
And I click on "Actions" "link" in the "Recent activity" "block"
|
||||
And I click on "Delete Recent activity block" "link"
|
||||
And I press "Yes"
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I add a "Forum" to section "1" and I fill the form with:
|
||||
| Forum name | Test forum name 1 |
|
||||
| Description | Test forum description 1 |
|
||||
And I add a "Forum" to section "1" and I fill the form with:
|
||||
| Forum name | Test forum name 2 |
|
||||
| Description | Test forum description 2 |
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I indent right "Test forum name 1" activity
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I indent left "Test forum name 1" activity
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I open "Test forum name 1" actions menu
|
||||
And I click on "Edit settings" "link" in the "Test forum name 1" activity
|
||||
And I should see "Updating Forum"
|
||||
@@ -63,38 +63,38 @@ Feature: Course activity controls works as expected
|
||||
| Description | Just to check that I can edit the description |
|
||||
| Display description on course page | 1 |
|
||||
And I click on "Cancel" "button"
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I open "Test forum name 1" actions menu
|
||||
And I click on "Hide" "link" in the "Test forum name 1" activity
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I delete "Test forum name 1" activity
|
||||
And I should not see "Test forum name 1" in the "#region-main" "css_element"
|
||||
And I duplicate "Test forum name 2" activity editing the new copy with:
|
||||
| Forum name | Edited test forum name 2 |
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I should see "Test forum name 2"
|
||||
And I should see "Edited test forum name 2"
|
||||
And I hide section "1"
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And section "1" should be hidden
|
||||
And all activities in section "1" should be hidden
|
||||
And I show section "1"
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And section "1" should be visible
|
||||
And I add the "Section links" block
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I should see "1 2 3 4 5" in the "Section links" "block"
|
||||
And I click on "2" "link" in the "Section links" "block"
|
||||
And I <should_see_other_sections_following_block_sections_links> see "Test forum name 2"
|
||||
|
||||
Examples:
|
||||
| courseformat | coursedisplay | targetpage | should_see_other_sections | should_see_other_sections_following_block_sections_links |
|
||||
| topics | 0 | "Course 1" | should | should |
|
||||
| topics | 1 | "Topic 1" | should not | should not |
|
||||
| topics | 1 | "Course 1" | should | should not |
|
||||
| weeks | 0 | "Course 1" | should | should |
|
||||
| weeks | 1 | "1 January - 7 January" | should not | should not |
|
||||
| weeks | 1 | "Course 1" | should | should not |
|
||||
| courseformat | coursedisplay | targetpage | should_see_other_sections | should_see_other_sections_following_block_sections_links | belowpage |
|
||||
| topics | 0 | "Course 1" | should | should | "Topic 2" |
|
||||
| topics | 1 | "Topic 1" | should not | should not | "Topic 2" |
|
||||
| topics | 1 | "Course 1" | should | should not | "Topic 2" |
|
||||
| weeks | 0 | "Course 1" | should | should | "8 January - 14 January" |
|
||||
| weeks | 1 | "1 January - 7 January" | should not | should not | "8 January - 14 January" |
|
||||
| weeks | 1 | "Course 1" | should | should not | "8 January - 14 January" |
|
||||
|
||||
Scenario Outline: General activities course controls using topics and weeks formats, and paged mode and not paged mode works as expected
|
||||
Given the following "users" exist:
|
||||
@@ -122,51 +122,51 @@ Feature: Course activity controls works as expected
|
||||
And I click on "Actions" "link" in the "Recent activity" "block"
|
||||
And I click on "Delete Recent activity block" "link"
|
||||
And I press "Yes"
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I add a "Forum" to section "1" and I fill the form with:
|
||||
| Forum name | Test forum name 1 |
|
||||
| Description | Test forum description 1 |
|
||||
And I add a "Forum" to section "1" and I fill the form with:
|
||||
| Forum name | Test forum name 2 |
|
||||
| Description | Test forum description 2 |
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I indent right "Test forum name 1" activity
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I indent left "Test forum name 1" activity
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I click on "Edit settings" "link" in the "Test forum name 1" activity
|
||||
And I should see "Updating Forum"
|
||||
And I should see "Display description on course page"
|
||||
And I press "Save and return to course"
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I click on "Hide" "link" in the "Test forum name 1" activity
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I delete "Test forum name 1" activity
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I should not see "Test forum name 1" in the "#region-main" "css_element"
|
||||
And I duplicate "Test forum name 2" activity editing the new copy with:
|
||||
| Forum name | Edited test forum name 2 |
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I should see "Test forum name 2"
|
||||
And I should see "Edited test forum name 2"
|
||||
And I hide section "1"
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And section "1" should be hidden
|
||||
And all activities in section "1" should be hidden
|
||||
And I show section "1"
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And section "1" should be visible
|
||||
And I add the "Section links" block
|
||||
And "#section-2" "css_element" <should_see_other_sections> exist
|
||||
And <belowpage> "section" <should_see_other_sections> exist
|
||||
And I should see "1 2 3 4 5" in the "Section links" "block"
|
||||
And I click on "2" "link" in the "Section links" "block"
|
||||
And I <should_see_other_sections_following_block_sections_links> see "Test forum name 2"
|
||||
|
||||
Examples:
|
||||
| courseformat | coursedisplay | targetpage | should_see_other_sections | should_see_other_sections_following_block_sections_links |
|
||||
| topics | 0 | "Course 1" | should | should |
|
||||
| topics | 1 | "Topic 1" | should not | should not |
|
||||
| topics | 1 | "Course 1" | should | should not |
|
||||
| weeks | 0 | "Course 1" | should | should |
|
||||
| weeks | 1 | "1 January - 7 January" | should not | should not |
|
||||
| weeks | 1 | "Course 1" | should | should not |
|
||||
| courseformat | coursedisplay | targetpage | should_see_other_sections | should_see_other_sections_following_block_sections_links | belowpage |
|
||||
| topics | 0 | "Course 1" | should | should | "Topic 2" |
|
||||
| topics | 1 | "Topic 1" | should not | should not | "Topic 2" |
|
||||
| topics | 1 | "Course 1" | should | should not | "Topic 2" |
|
||||
| weeks | 0 | "Course 1" | should | should | "8 January - 14 January" |
|
||||
| weeks | 1 | "1 January - 7 January" | should not | should not | "8 January - 14 January" |
|
||||
| weeks | 1 | "Course 1" | should | should not | "8 January - 14 January" |
|
||||
|
||||
@@ -29,8 +29,8 @@ Feature: Activities can be moved between sections
|
||||
|
||||
Scenario: Move activities in a single page course with Javascript disabled
|
||||
When I move "Test forum name" activity to section "2"
|
||||
Then I should see "Test forum name" in the "#section-2" "css_element"
|
||||
And I should not see "Test forum name" in the "#section-1" "css_element"
|
||||
Then I should see "Test forum name" in the "Topic 2" "section"
|
||||
And I should not see "Test forum name" in the "Topic 1" "section"
|
||||
|
||||
Scenario: Move activities in the course home with Javascript disabled using paged mode
|
||||
Given I click on "Edit settings" "link" in the "Administration" "block"
|
||||
@@ -38,8 +38,8 @@ Feature: Activities can be moved between sections
|
||||
| Course layout | Show one section per page |
|
||||
And I press "Save changes"
|
||||
When I move "Test forum name" activity to section "2"
|
||||
Then I should see "Test forum name" in the "#section-2" "css_element"
|
||||
And I should not see "Test forum name" in the "#section-1" "css_element"
|
||||
Then I should see "Test forum name" in the "Topic 2" "section"
|
||||
And I should not see "Test forum name" in the "Topic 1" "section"
|
||||
|
||||
Scenario: Move activities in a course section with Javascript disabled using paged mode
|
||||
Given I click on "Edit settings" "link" in the "Administration" "block"
|
||||
|
||||
@@ -23,9 +23,9 @@ Feature: Sections can be moved
|
||||
| Forum name | Test forum name |
|
||||
| Description | Test forum description |
|
||||
When I move down section "1"
|
||||
Then I should see "Test forum name" in the "#section-2" "css_element"
|
||||
Then I should see "Test forum name" in the "Topic 2" "section"
|
||||
And I move up section "2"
|
||||
And I should see "Test forum name" in the "#section-1" "css_element"
|
||||
And I should see "Test forum name" in the "Topic 1" "section"
|
||||
|
||||
Scenario: Move up and down a section with Javascript disabled in the course home of a course using paged mode
|
||||
Given I click on "Edit settings" "link" in the "Administration" "block"
|
||||
@@ -36,9 +36,9 @@ Feature: Sections can be moved
|
||||
| Forum name | Test forum name |
|
||||
| Description | Test forum description |
|
||||
When I move down section "1"
|
||||
Then I should see "Test forum name" in the "#section-2" "css_element"
|
||||
Then I should see "Test forum name" in the "Topic 2" "section"
|
||||
And I move up section "2"
|
||||
And I should see "Test forum name" in the "#section-1" "css_element"
|
||||
And I should see "Test forum name" in the "Topic 1" "section"
|
||||
|
||||
Scenario: Sections can not be moved with Javascript disabled in a section page of a course using paged mode
|
||||
Given I click on "Edit settings" "link" in the "Administration" "block"
|
||||
@@ -49,7 +49,7 @@ Feature: Sections can be moved
|
||||
| Forum name | Test forum name |
|
||||
| Description | Test forum description |
|
||||
When I follow "Topic 2"
|
||||
Then "#section-1" "css_element" should not exist
|
||||
And "#section-3" "css_element" should not exist
|
||||
Then "Topic 1" "section" should not exist
|
||||
And "Topic 3" "section" should not exist
|
||||
And "Move down" "link" should not exist
|
||||
And "Move up" "link" should not exist
|
||||
|
||||
@@ -11,11 +11,11 @@ Feature: Course paged mode
|
||||
| Course 1 | C1 | 0 | <courseformat> | 1 | 3 |
|
||||
And I log in as "admin"
|
||||
And I follow "Course 1"
|
||||
Then I click on <section2> "link" in the "#section-2" "css_element"
|
||||
Then I click on <section2> "link" in the <section2> "section"
|
||||
And I follow "C1"
|
||||
And I click on <section3> "link" in the "#section-3" "css_element"
|
||||
And I click on <section3> "link" in the <section3> "section"
|
||||
And I follow "C1"
|
||||
And I click on <section1> "link" in the "#section-1" "css_element"
|
||||
And I click on <section1> "link" in the <section1> "section"
|
||||
And I should see <section1> in the "div.single-section" "css_element"
|
||||
And I should see <section2> in the ".single-section span.mdl-right" "css_element"
|
||||
And I should not see <prevunexistingsection> in the ".single-section" "css_element"
|
||||
@@ -44,11 +44,11 @@ Feature: Course paged mode
|
||||
| Course 1 | C1 | 0 | <courseformat> | 1 | 3 |
|
||||
And I log in as "admin"
|
||||
And I follow "Course 1"
|
||||
Then I click on <section2> "link" in the "#section-2" "css_element"
|
||||
Then I click on <section2> "link" in the <section2> "section"
|
||||
And I follow "C1"
|
||||
And I click on <section3> "link" in the "#section-3" "css_element"
|
||||
And I click on <section3> "link" in the <section3> "section"
|
||||
And I follow "C1"
|
||||
And I click on <section1> "link" in the "#section-1" "css_element"
|
||||
And I click on <section1> "link" in the <section1> "section"
|
||||
And I should see <section1> in the "div.single-section" "css_element"
|
||||
And I should see <section2> in the ".single-section span.mdl-right" "css_element"
|
||||
And I should not see <prevunexistingsection> in the ".single-section" "css_element"
|
||||
|
||||
@@ -1731,7 +1731,7 @@ class core_course_courselib_testcase extends advanced_testcase {
|
||||
$bc->execute_plan();
|
||||
$results = $bc->get_results();
|
||||
$file = $results['backup_destination'];
|
||||
$fp = get_file_packer();
|
||||
$fp = get_file_packer('application/vnd.moodle.backup');
|
||||
$filepath = $CFG->dataroot . '/temp/backup/test-restore-course-event';
|
||||
$file->extract_to_pathname($fp, $filepath);
|
||||
$bc->destroy();
|
||||
|
||||
@@ -611,12 +611,14 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
|
||||
$formattedtext = format_text($cm->content, FORMAT_HTML,
|
||||
array('noclean' => true, 'para' => false, 'filter' => false));
|
||||
$this->assertEquals($formattedtext, $module['description']);
|
||||
$this->assertEquals($forumcm->instance, $module['instance']);
|
||||
$testexecuted = $testexecuted + 1;
|
||||
} else if ($module['id'] == $labelcm->id and $module['modname'] == 'label') {
|
||||
$cm = $modinfo->cms[$labelcm->id];
|
||||
$formattedtext = format_text($cm->content, FORMAT_HTML,
|
||||
array('noclean' => true, 'para' => false, 'filter' => false));
|
||||
$this->assertEquals($formattedtext, $module['description']);
|
||||
$this->assertEquals($labelcm->instance, $module['instance']);
|
||||
$testexecuted = $testexecuted + 1;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -240,8 +240,8 @@ foreach ($instances as $instance) {
|
||||
}
|
||||
}
|
||||
|
||||
// add a row to the table
|
||||
$table->data[] = array($displayname, $users, implode(' ', $updown), implode(' ', $edit));
|
||||
// Add a row to the table.
|
||||
$table->data[] = array($displayname, $users, implode('', $updown), implode('', $edit));
|
||||
|
||||
}
|
||||
echo html_writer::table($table);
|
||||
|
||||
+1
-1
@@ -894,7 +894,7 @@ class course_enrolment_manager {
|
||||
$args['search'] = $this->searchfilter;
|
||||
}
|
||||
if (!empty($this->groupfilter)) {
|
||||
$args['group'] = $this->groupfilter;
|
||||
$args['filtergroup'] = $this->groupfilter;
|
||||
}
|
||||
if ($this->statusfilter !== -1) {
|
||||
$args['status'] = $this->statusfilter;
|
||||
|
||||
@@ -251,7 +251,7 @@ if (strlen($result) > 0) {
|
||||
$eventdata->modulename = 'moodle';
|
||||
$eventdata->component = 'enrol_paypal';
|
||||
$eventdata->name = 'paypal_enrolment';
|
||||
$eventdata->userfrom = empty($teacher) ? get_admin() : $teacher;
|
||||
$eventdata->userfrom = empty($teacher) ? core_user::get_support_user() : $teacher;
|
||||
$eventdata->userto = $user;
|
||||
$eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname);
|
||||
$eventdata->fullmessage = get_string('welcometocoursetext', '', $a);
|
||||
|
||||
@@ -38,8 +38,10 @@ class enrol_self_edit_form extends moodleform {
|
||||
|
||||
$mform->addElement('header', 'header', get_string('pluginname', 'enrol_self'));
|
||||
|
||||
$mform->addElement('text', 'name', get_string('custominstancename', 'enrol'));
|
||||
$nameattribs = array('size' => '20', 'maxlength' => '255');
|
||||
$mform->addElement('text', 'name', get_string('custominstancename', 'enrol'), $nameattribs);
|
||||
$mform->setType('name', PARAM_TEXT);
|
||||
$mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'server');
|
||||
|
||||
$options = array(ENROL_INSTANCE_ENABLED => get_string('yes'),
|
||||
ENROL_INSTANCE_DISABLED => get_string('no'));
|
||||
@@ -51,11 +53,13 @@ class enrol_self_edit_form extends moodleform {
|
||||
$mform->addHelpButton('customint6', 'newenrols', 'enrol_self');
|
||||
$mform->disabledIf('customint6', 'status', 'eq', ENROL_INSTANCE_DISABLED);
|
||||
|
||||
$mform->addElement('passwordunmask', 'password', get_string('password', 'enrol_self'));
|
||||
$passattribs = array('size' => '20', 'maxlength' => '50');
|
||||
$mform->addElement('passwordunmask', 'password', get_string('password', 'enrol_self'), $passattribs);
|
||||
$mform->addHelpButton('password', 'password', 'enrol_self');
|
||||
if (empty($instance->id) and $plugin->get_config('requirepassword')) {
|
||||
$mform->addRule('password', get_string('required'), 'required', null, 'client');
|
||||
}
|
||||
$mform->addRule('password', get_string('maximumchars', '', 50), 'maxlength', 50, 'server');
|
||||
|
||||
$options = array(1 => get_string('yes'),
|
||||
0 => get_string('no'));
|
||||
|
||||
+3
-1
@@ -248,6 +248,8 @@ class enrol_self_plugin extends enrol_plugin {
|
||||
$form->display();
|
||||
$output = ob_get_clean();
|
||||
return $OUTPUT->box($output);
|
||||
} else {
|
||||
return $OUTPUT->box($enrolstatus);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +267,7 @@ class enrol_self_plugin extends enrol_plugin {
|
||||
if ($checkuserenrolment) {
|
||||
if (isguestuser()) {
|
||||
// Can not enrol guest.
|
||||
return get_string('canntenrol', 'enrol_self');
|
||||
return get_string('noguestaccess', 'enrol');
|
||||
}
|
||||
// Check if user is already enroled.
|
||||
if ($DB->get_record('user_enrolments', array('userid' => $USER->id, 'enrolid' => $instance->id))) {
|
||||
|
||||
@@ -602,7 +602,7 @@ class enrol_self_testcase extends advanced_testcase {
|
||||
$selfplugin->enrol_user($instance1, $user2->id, $editingteacherrole->id);
|
||||
|
||||
$this->setUser($guest);
|
||||
$this->assertSame($expectederrorstring, $selfplugin->can_self_enrol($instance1, true));
|
||||
$this->assertSame(get_string('noguestaccess', 'enrol'), $selfplugin->can_self_enrol($instance1, true));
|
||||
|
||||
$this->setUser($user1);
|
||||
$this->assertTrue($selfplugin->can_self_enrol($instance1, true));
|
||||
|
||||
+1
-1
@@ -205,7 +205,7 @@ if (!has_capability('moodle/course:viewhiddenuserfields', $context)) {
|
||||
|
||||
$filterform = new enrol_users_filter_form('users.php', array('manager' => $manager, 'id' => $id),
|
||||
'get', '', array('id' => 'filterform'));
|
||||
$filterform->set_data(array('search' => $search, 'ifilter' => $filter, 'role' => $role));
|
||||
$filterform->set_data(array('search' => $search, 'ifilter' => $filter, 'role' => $role, 'filtergroup' => $fgroup));
|
||||
|
||||
$table->set_fields($fields, $renderer);
|
||||
|
||||
|
||||
@@ -87,7 +87,8 @@ if (!$file = $fs->get_file_by_hash(sha1($fullpath))) {
|
||||
if (strrpos($fullpath, '/') !== strlen($fullpath) -1 ) {
|
||||
$fullpath .= '/';
|
||||
}
|
||||
if (!$file = $fs->get_file_by_hash(sha1($fullpath.'/.'))) {
|
||||
// Try to fallback to the directory named as the supposed file.
|
||||
if (!$file = $fs->get_file_by_hash(sha1($fullpath.'.'))) {
|
||||
send_file_not_found();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,5 +44,47 @@ function xmldb_filter_mathjaxloader_upgrade($oldversion) {
|
||||
upgrade_plugin_savepoint(true, 2014051201, 'filter', 'mathjaxloader');
|
||||
}
|
||||
|
||||
if ($oldversion < 2014051202) {
|
||||
|
||||
$oldconfig = get_config('filter_mathjaxloader', 'mathjaxconfig');
|
||||
$olddefault = 'MathJax.Hub.Config({
|
||||
config: ["MMLorHTML.js", "Safe.js"],
|
||||
jax: ["input/TeX","input/MathML","output/HTML-CSS","output/NativeMML"],
|
||||
extensions: ["tex2jax.js","mml2jax.js","MathMenu.js","MathZoom.js"],
|
||||
TeX: {
|
||||
extensions: ["AMSmath.js","AMSsymbols.js","noErrors.js","noUndefined.js"]
|
||||
},
|
||||
menuSettings: {
|
||||
zoom: "Double-Click",
|
||||
mpContext: true,
|
||||
mpMouse: true
|
||||
},
|
||||
errorSettings: { message: ["!"] },
|
||||
skipStartupTypeset: true,
|
||||
messageStyle: "none"
|
||||
});
|
||||
';
|
||||
$newdefault = '
|
||||
MathJax.Hub.Config({
|
||||
config: ["Accessible.js", "Safe.js"],
|
||||
errorSettings: { message: ["!"] },
|
||||
skipStartupTypeset: true,
|
||||
messageStyle: "none"
|
||||
});
|
||||
';
|
||||
|
||||
// Ignore white space changes.
|
||||
$oldconfig = trim(preg_replace('/\s+/', ' ', $oldconfig));
|
||||
$olddefault = trim(preg_replace('/\s+/', ' ', $olddefault));
|
||||
|
||||
// Update the default config for mathjax only if it has not been customised.
|
||||
|
||||
if ($oldconfig == $olddefault) {
|
||||
set_config('mathjaxconfig', $newdefault, 'filter_mathjaxloader');
|
||||
}
|
||||
|
||||
upgrade_plugin_savepoint(true, 2014051202, 'filter', 'mathjaxloader');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ class filter_mathjaxloader extends moodle_text_filter {
|
||||
$text = str_replace('[tex]', '\\(', $text);
|
||||
$text = str_replace('[/tex]', '\\)', $text);
|
||||
// E.g. "$$ blah $$".
|
||||
$text = preg_replace('|\$\$[\S\s]\$\$|u', '\\(\1\\)', $text);
|
||||
$text = preg_replace('|\$\$([\S\s]*?)\$\$|u', '\\(\1\\)', $text);
|
||||
// E.g. "\[ blah \]".
|
||||
$text = str_replace('\\[', '\\(', $text);
|
||||
$text = str_replace('\\]', '\\)', $text);
|
||||
|
||||
@@ -52,17 +52,7 @@ if ($ADMIN->fulltree) {
|
||||
|
||||
$default = '
|
||||
MathJax.Hub.Config({
|
||||
config: ["MMLorHTML.js", "Safe.js"],
|
||||
jax: ["input/TeX","input/MathML","output/HTML-CSS","output/NativeMML"],
|
||||
extensions: ["tex2jax.js","mml2jax.js","MathMenu.js","MathZoom.js"],
|
||||
TeX: {
|
||||
extensions: ["AMSmath.js","AMSsymbols.js","noErrors.js","noUndefined.js"]
|
||||
},
|
||||
menuSettings: {
|
||||
zoom: "Double-Click",
|
||||
mpContext: true,
|
||||
mpMouse: true
|
||||
},
|
||||
config: ["Accessible.js", "Safe.js"],
|
||||
errorSettings: { message: ["!"] },
|
||||
skipStartupTypeset: true,
|
||||
messageStyle: "none"
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2014051201;
|
||||
$plugin->version = 2014051202;
|
||||
$plugin->requires = 2014050800; // Requires this Moodle version
|
||||
$plugin->component= 'filter_mathjaxloader';
|
||||
|
||||
@@ -134,10 +134,9 @@ class filter_urltolink extends moodle_text_filter {
|
||||
|
||||
// Lookbehind assertions.
|
||||
// Is not HTML attribute or CSS URL property. Unfortunately legit text like "url(http://...)" will not be a link.
|
||||
$lookbehindstart = "(?<!=[\"']|\burl\([\"' ]|\burl\()";
|
||||
$lookbehindend = "(?<![]),.;])";
|
||||
|
||||
$regex = "$lookbehindstart$urlstart((?:$domainsegment\.)+$domainsegment|$numericip)" .
|
||||
$regex = "$urlstart((?:$domainsegment\.)+$domainsegment|$numericip)" .
|
||||
"($port?$path$querystring?$fragment?)$lookbehindend";
|
||||
if ($unicoderegexp) {
|
||||
$regex = '#' . $regex . '#ui';
|
||||
@@ -145,7 +144,38 @@ class filter_urltolink extends moodle_text_filter {
|
||||
$regex = '#' . preg_replace(array('\pLl', '\PL'), 'a-z', $regex) . '#i';
|
||||
}
|
||||
|
||||
$text = preg_replace($regex, '<a href="http$1://$2$3$4" class="_blanktarget">$0</a>', $text);
|
||||
// Locate any HTML tags.
|
||||
$matches = preg_split('/(<[^<|>]*>)/i', $text, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
// Iterate through the tokenized text to handle chunks (html and content).
|
||||
foreach ($matches as $idx => $chunk) {
|
||||
// Nothing to do. We skip completely any html chunk.
|
||||
if (strpos(trim($chunk), '<') === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Nothing to do. We skip any content chunk having any of these attributes.
|
||||
if (preg_match('#(background=")|(action=")|(style="background)|(href=")|(src=")|(url [(])#', $chunk)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Arrived here, we want to process every word in this chunk.
|
||||
$text = $chunk;
|
||||
$words = explode(' ', $text);
|
||||
|
||||
foreach ($words as $idx2 => $word) {
|
||||
// ReDoS protection. Stop processing if a word is too large.
|
||||
if (strlen($word) < 4096) {
|
||||
$words[$idx2] = preg_replace($regex, '<a href="http$1://$2$3$4" class="_blanktarget">$0</a>', $word);
|
||||
}
|
||||
}
|
||||
$text = implode(' ', $words);
|
||||
|
||||
// Copy the result back to the array.
|
||||
$matches[$idx] = $text;
|
||||
}
|
||||
|
||||
$text = implode('', $matches);
|
||||
|
||||
if (!empty($ignoretags)) {
|
||||
$ignoretags = array_reverse($ignoretags); /// Reversed so "progressive" str_replace() will solve some nesting problems.
|
||||
|
||||
@@ -29,9 +29,13 @@ global $CFG;
|
||||
require_once($CFG->dirroot . '/filter/urltolink/filter.php'); // Include the code to test
|
||||
|
||||
|
||||
class filter_urltolink_testcase extends basic_testcase {
|
||||
class filter_urltolink_filter_testcase extends basic_testcase {
|
||||
|
||||
function get_convert_urls_into_links_test_cases() {
|
||||
// Create a 4095 and 4096 long URLs.
|
||||
$superlong4095 = str_pad('http://www.superlong4095.com?this=something', 4095, 'a');
|
||||
$superlong4096 = str_pad('http://www.superlong4096.com?this=something', 4096, 'a');
|
||||
|
||||
$texts = array (
|
||||
//just a url
|
||||
'http://moodle.org - URL' => '<a href="http://moodle.org" class="_blanktarget">http://moodle.org</a> - URL',
|
||||
@@ -130,6 +134,7 @@ class filter_urltolink_testcase extends basic_testcase {
|
||||
'<td background="http://moodle.org"> </td>' => '<td background="http://moodle.org"> </td>',
|
||||
'<td background="www.moodle.org"> </td>' => '<td background="www.moodle.org"> </td>',
|
||||
'<form name="input" action="http://moodle.org/submit.asp" method="get">'=>'<form name="input" action="http://moodle.org/submit.asp" method="get">',
|
||||
'<input type="submit" value="Go to http://moodle.org">' => '<input type="submit" value="Go to http://moodle.org">',
|
||||
'<td background="https://www.moodle.org"> </td>' => '<td background="https://www.moodle.org"> </td>',
|
||||
// CSS URLs.
|
||||
'<table style="background-image: url(\'http://moodle.org/pic.jpg\');">' => '<table style="background-image: url(\'http://moodle.org/pic.jpg\');">',
|
||||
@@ -148,6 +153,27 @@ class filter_urltolink_testcase extends basic_testcase {
|
||||
//Encoded URLs in the query
|
||||
'URL: http://127.0.0.1/path/to?param=value_with%28parenthesis%29¶m2=1' => 'URL: <a href="http://127.0.0.1/path/to?param=value_with%28parenthesis%29¶m2=1" class="_blanktarget">http://127.0.0.1/path/to?param=value_with%28parenthesis%29¶m2=1</a>',
|
||||
'URL: www.localhost.com/path/to?param=value_with%28parenthesis%29¶m2=1' => 'URL: <a href="http://www.localhost.com/path/to?param=value_with%28parenthesis%29¶m2=1" class="_blanktarget">www.localhost.com/path/to?param=value_with%28parenthesis%29¶m2=1</a>',
|
||||
// Test URL less than 4096 characters in size is converted to link.
|
||||
'URL: ' . $superlong4095 => 'URL: <a href="' . $superlong4095 . '" class="_blanktarget">' . $superlong4095 . '</a>',
|
||||
// Test URL equal to or greater than 4096 characters in size is not converted to link.
|
||||
'URL: ' . $superlong4096 => 'URL: ' . $superlong4096,
|
||||
// Testing URL within a span tag.
|
||||
'URL: <span style="kasd"> my link to http://google.com </span>' => 'URL: <span style="kasd"> my link to <a href="http://google.com" class="_blanktarget">http://google.com</a> </span>',
|
||||
// Nested tags test.
|
||||
'<b><i>www.google.com</i></b>' => '<b><i><a href="http://www.google.com" class="_blanktarget">www.google.com</a></i></b>',
|
||||
'<input type="submit" value="Go to http://moodle.org">' => '<input type="submit" value="Go to http://moodle.org">',
|
||||
// Test realistic content.
|
||||
'<p><span style="color: rgb(37, 37, 37); font-family: sans-serif; line-height: 22.3999996185303px;">Lorem ipsum amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut http://google.com aliquip ex ea <a href="http://google.com">commodo consequat</a>. Duis aute irure in reprehenderit in excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia https://docs.google.com/document/d/BrokenLinkPleaseAyacDHc_Ov8aoskoSVQsfmLHP_jYAkRMk/edit?usp=sharing https://docs.google.com/document/d/BrokenLinkPleaseAyacDHc_Ov8aoskoSVQsfmLHP_jYAkRMk/edit?usp=sharing mollit anim id est laborum.</span><br></p>'
|
||||
=>
|
||||
'<p><span style="color: rgb(37, 37, 37); font-family: sans-serif; line-height: 22.3999996185303px;">Lorem ipsum amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut <a href="http://google.com" class="_blanktarget">http://google.com</a> aliquip ex ea <a href="http://google.com">commodo consequat</a>. Duis aute irure in reprehenderit in excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia <a href="https://docs.google.com/document/d/BrokenLinkPleaseAyacDHc_Ov8aoskoSVQsfmLHP_jYAkRMk/edit?usp=sharing" class="_blanktarget">https://docs.google.com/document/d/BrokenLinkPleaseAyacDHc_Ov8aoskoSVQsfmLHP_jYAkRMk/edit?usp=sharing</a> <a href="https://docs.google.com/document/d/BrokenLinkPleaseAyacDHc_Ov8aoskoSVQsfmLHP_jYAkRMk/edit?usp=sharing" class="_blanktarget">https://docs.google.com/document/d/BrokenLinkPleaseAyacDHc_Ov8aoskoSVQsfmLHP_jYAkRMk/edit?usp=sharing</a> mollit anim id est laborum.</span><br></p>',
|
||||
// Test some broken html.
|
||||
'5 < 10 www.google.com <a href="hi.com">im a link</a>' => '5 < 10 <a href="http://www.google.com" class="_blanktarget">www.google.com</a> <a href="hi.com">im a link</a>',
|
||||
'h3 (www.styles.com/h3) < h1 (www.styles.com/h1)' => 'h3 (<a href="http://www.styles.com/h3" class="_blanktarget">www.styles.com/h3</a>) < h1 (<a href="http://www.styles.com/h1" class="_blanktarget">www.styles.com/h1</a>)',
|
||||
'<p>text www.moodle.org</p> text' => '<p>text <a href="http://www.moodle.org" class="_blanktarget">www.moodle.org</a></p> text',
|
||||
// Some more urls.
|
||||
'<link rel="search" type="application/opensearchdescription+xml" href="/osd.jsp" title="Peer review - Moodle Tracker"/>' => '<link rel="search" type="application/opensearchdescription+xml" href="/osd.jsp" title="Peer review - Moodle Tracker"/>',
|
||||
'<a href="https://docs.moodle.org/dev/Main_Page"></a><span>www.google.com</span><span class="placeholder"></span>' => '<a href="https://docs.moodle.org/dev/Main_Page"></a><span><a href="http://www.google.com" class="_blanktarget">www.google.com</a></span><span class="placeholder"></span>',
|
||||
'http://nolandforzombies.com <a href="zombiesFTW.com">Zombies FTW</a> http://aliens.org' => '<a href="http://nolandforzombies.com" class="_blanktarget">http://nolandforzombies.com</a> <a href="zombiesFTW.com">Zombies FTW</a> <a href="http://aliens.org" class="_blanktarget">http://aliens.org</a>',
|
||||
//URLs in Javascript. Commented out as part of MDL-21183
|
||||
//'var url="http://moodle.org";'=>'var url="http://moodle.org";',
|
||||
//'var url = "http://moodle.org";'=>'var url = "http://moodle.org";',
|
||||
|
||||
@@ -51,9 +51,11 @@ class gradingform_guide_editguide extends moodleform {
|
||||
$form->setType('returnurl', PARAM_LOCALURL);
|
||||
|
||||
// Name.
|
||||
$form->addElement('text', 'name', get_string('name', 'gradingform_guide'), array('size'=>52));
|
||||
$form->addElement('text', 'name', get_string('name', 'gradingform_guide'),
|
||||
array('size' => 52, 'maxlength' => 255));
|
||||
$form->addRule('name', get_string('required'), 'required');
|
||||
$form->setType('name', PARAM_TEXT);
|
||||
$form->addRule('name', null, 'maxlength', 255, 'client');
|
||||
|
||||
// Description.
|
||||
$options = gradingform_guide_controller::description_form_field_options($this->_customdata['context']);
|
||||
|
||||
@@ -197,6 +197,10 @@ class moodlequickform_guideeditor extends HTML_QuickForm_input {
|
||||
$errors['err_noshortname'] = 1;
|
||||
$criterion['error_description'] = true;
|
||||
}
|
||||
if (strlen(trim($criterion['shortname'])) > 255) {
|
||||
$errors['err_shortnametoolong'] = 1;
|
||||
$criterion['error_description'] = true;
|
||||
}
|
||||
if (!strlen(trim($criterion['maxscore']))) {
|
||||
$errors['err_nomaxscore'] = 1;
|
||||
$criterion['error_description'] = true;
|
||||
|
||||
@@ -54,6 +54,7 @@ $string['err_nodescription'] = 'Student description can not be empty';
|
||||
$string['err_nodescriptionmarkers'] = 'Marker description can not be empty';
|
||||
$string['err_nomaxscore'] = 'Criterion max score can not be empty';
|
||||
$string['err_noshortname'] = 'Criterion name can not be empty';
|
||||
$string['err_shortnametoolong'] = 'Criterion name must be less than 256 characters';
|
||||
$string['err_scoreinvalid'] = 'The score given to {$a->criterianame} is not valid, the max score is: {$a->maxscore}';
|
||||
$string['gradingof'] = '{$a} grading';
|
||||
$string['guidemappingexplained'] = 'WARNING: Your marking guide has a maximum grade of <b>{$a->maxscore} points</b> but the maximum grade set in your activity is {$a->modulegrade} The maximum score set in your marking guide will be scaled to the maximum grade in the module.<br />
|
||||
|
||||
@@ -287,11 +287,11 @@ if ($formdata = $mform2->get_data()) {
|
||||
$newgrade = new stdClass();
|
||||
$newgrade->newgradeitem = $newgradeitems[$key];
|
||||
|
||||
// if the user has a grade for this grade item
|
||||
if (trim($value) != '-') {
|
||||
// instead of omitting the grade we could insert one with finalgrade set to 0
|
||||
// we do not have access to grade item min grade
|
||||
$newgrade->finalgrade = $value;
|
||||
// If the user has a grade for this grade item.
|
||||
$trimmed = trim($value);
|
||||
if ($trimmed !== '' and $trimmed != '-') {
|
||||
// Only include a grade if it is not blank or a dash.
|
||||
$newgrade->finalgrade = $value;
|
||||
$newgrades[] = $newgrade;
|
||||
}
|
||||
break;
|
||||
|
||||
+3
-3
@@ -533,7 +533,7 @@ function grade_print_tabs($active_type, $active_plugin, $plugin_info, $return=fa
|
||||
$top_row = array();
|
||||
$bottom_row = array();
|
||||
$inactive = array($active_plugin);
|
||||
$activated = array();
|
||||
$activated = array($active_type);
|
||||
|
||||
$count = 0;
|
||||
$active = '';
|
||||
@@ -577,9 +577,9 @@ function grade_print_tabs($active_type, $active_plugin, $plugin_info, $return=fa
|
||||
$tabs[] = $bottom_row;
|
||||
|
||||
if ($return) {
|
||||
return print_tabs($tabs, $active_type, $inactive, $activated, true);
|
||||
return print_tabs($tabs, $active_plugin, $inactive, $activated, true);
|
||||
} else {
|
||||
print_tabs($tabs, $active_type, $inactive, $activated);
|
||||
print_tabs($tabs, $active_plugin, $inactive, $activated);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+29
-24
@@ -415,8 +415,14 @@ class grade_report_grader extends grade_report {
|
||||
// Limit to users with a gradeable role.
|
||||
list($gradebookrolessql, $gradebookrolesparams) = $DB->get_in_or_equal(explode(',', $this->gradebookroles), SQL_PARAMS_NAMED, 'grbr0');
|
||||
|
||||
// Check the status of showing only active enrolments.
|
||||
$coursecontext = $this->context->get_course_context(true);
|
||||
$defaultgradeshowactiveenrol = !empty($CFG->grade_report_showonlyactiveenrol);
|
||||
$showonlyactiveenrol = get_user_preferences('grade_report_showonlyactiveenrol', $defaultgradeshowactiveenrol);
|
||||
$showonlyactiveenrol = $showonlyactiveenrol || !has_capability('moodle/course:viewsuspendedusers', $coursecontext);
|
||||
|
||||
// Limit to users with an active enrollment.
|
||||
list($enrolledsql, $enrolledparams) = get_enrolled_sql($this->context);
|
||||
list($enrolledsql, $enrolledparams) = get_enrolled_sql($this->context, '', 0, $showonlyactiveenrol);
|
||||
|
||||
// Fields we need from the user table.
|
||||
$userfields = user_picture::fields('u', get_extra_user_fields($this->context));
|
||||
@@ -479,30 +485,29 @@ class grade_report_grader extends grade_report {
|
||||
$this->userselect = "AND g.userid $usql";
|
||||
$this->userselect_params = $uparams;
|
||||
|
||||
// Add a flag to each user indicating whether their enrolment is active.
|
||||
$sql = "SELECT ue.userid
|
||||
FROM {user_enrolments} ue
|
||||
JOIN {enrol} e ON e.id = ue.enrolid
|
||||
WHERE ue.userid $usql
|
||||
AND ue.status = :uestatus
|
||||
AND e.status = :estatus
|
||||
AND e.courseid = :courseid
|
||||
AND ue.timestart < :now1 AND (ue.timeend = 0 OR ue.timeend > :now2)
|
||||
GROUP BY ue.userid";
|
||||
$coursecontext = $this->context->get_course_context(true);
|
||||
$time = time();
|
||||
$params = array_merge($uparams, array('estatus' => ENROL_INSTANCE_ENABLED, 'uestatus' => ENROL_USER_ACTIVE,
|
||||
'courseid' => $coursecontext->instanceid, 'now1' => $time, 'now2' => $time));
|
||||
$useractiveenrolments = $DB->get_records_sql($sql, $params);
|
||||
|
||||
$defaultgradeshowactiveenrol = !empty($CFG->grade_report_showonlyactiveenrol);
|
||||
$showonlyactiveenrol = get_user_preferences('grade_report_showonlyactiveenrol', $defaultgradeshowactiveenrol);
|
||||
$showonlyactiveenrol = $showonlyactiveenrol || !has_capability('moodle/course:viewsuspendedusers', $coursecontext);
|
||||
// First flag everyone as not suspended.
|
||||
foreach ($this->users as $user) {
|
||||
// If we are showing only active enrolments, then remove suspended users from list.
|
||||
if ($showonlyactiveenrol && !array_key_exists($user->id, $useractiveenrolments)) {
|
||||
unset($this->users[$user->id]);
|
||||
} else {
|
||||
$this->users[$user->id]->suspendedenrolment = false;
|
||||
}
|
||||
|
||||
// If we want to mix both suspended and not suspended users, let's find out who is suspended.
|
||||
if (!$showonlyactiveenrol) {
|
||||
$sql = "SELECT ue.userid
|
||||
FROM {user_enrolments} ue
|
||||
JOIN {enrol} e ON e.id = ue.enrolid
|
||||
WHERE ue.userid $usql
|
||||
AND ue.status = :uestatus
|
||||
AND e.status = :estatus
|
||||
AND e.courseid = :courseid
|
||||
AND ue.timestart < :now1 AND (ue.timeend = 0 OR ue.timeend > :now2)
|
||||
GROUP BY ue.userid";
|
||||
|
||||
$time = time();
|
||||
$params = array_merge($uparams, array('estatus' => ENROL_INSTANCE_ENABLED, 'uestatus' => ENROL_USER_ACTIVE,
|
||||
'courseid' => $coursecontext->instanceid, 'now1' => $time, 'now2' => $time));
|
||||
$useractiveenrolments = $DB->get_records_sql($sql, $params);
|
||||
|
||||
foreach ($this->users as $user) {
|
||||
$this->users[$user->id]->suspendedenrolment = !array_key_exists($user->id, $useractiveenrolments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ foreach ($outcomes as $outcomeid => $outcome) {
|
||||
FROM {grade_grades}
|
||||
WHERE itemid = ?".
|
||||
$hidesuspendedsql.
|
||||
"GROUP BY itemid";
|
||||
" GROUP BY itemid";
|
||||
$info = $DB->get_records_sql($sql, $params);
|
||||
|
||||
if (!$info) {
|
||||
|
||||
+1
-1
@@ -113,7 +113,7 @@ foreach ($rs as $row) {
|
||||
if (!array_key_exists($row->groupid, $members[$row->groupingid])) {
|
||||
$members[$row->groupingid][$row->groupid] = array();
|
||||
}
|
||||
if(isset($user->id)){
|
||||
if (!empty($user->id)) {
|
||||
$members[$row->groupingid][$row->groupid][] = $user;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ define('AJAX_SCRIPT', false); // prevents some warnings later
|
||||
define('CACHE_DISABLE_ALL', true); // Disables caching.. just in case.
|
||||
define('PHPUNIT_TEST', false);
|
||||
define('IGNORE_COMPONENT_CACHE', true);
|
||||
define('MDL_PERF_TEST', false);
|
||||
|
||||
// Servers should define a default timezone in php.ini, but if they don't then make sure something is defined.
|
||||
// This is a quick hack. Ideally we should ask the admin for a value. See MDL-22625 for more on this.
|
||||
|
||||
@@ -38,4 +38,5 @@ $string['cannotfindcomponent'] = 'لم يتم العثور على المكون';
|
||||
$string['cannotsavemd5file'] = 'لم يتم حفظ ملف md5';
|
||||
$string['cannotsavezipfile'] = 'لم يتم حفظ الملف المضغوط';
|
||||
$string['cannotunzipfile'] = 'لم يتم فك الملف المضغوط';
|
||||
$string['componentisuptodate'] = 'العنصر محدث';
|
||||
$string['missingrequiredfield'] = 'بعض الحقول المطلوبة مفقودة';
|
||||
|
||||
@@ -39,6 +39,7 @@ $string['cannotsavemd5file'] = 'Ezin da Md5 fitxategia gorde';
|
||||
$string['cannotsavezipfile'] = 'Ezin da ZIP fitxategia gorde';
|
||||
$string['cannotunzipfile'] = 'Ezin da fitxategia deskonprimatu';
|
||||
$string['componentisuptodate'] = 'Osagaia eguneratu da';
|
||||
$string['dmlexceptiononinstall'] = '<p>Datu-basearen errorea gertatu da [{$a->errorcode}].<br />{$a->debuginfo}</p>';
|
||||
$string['downloadedfilecheckfailed'] = 'Jaitsitako fitxategiaren konprobazioak kale egin du.';
|
||||
$string['invalidmd5'] = 'md5 ez da baliagarria';
|
||||
$string['missingrequiredfield'] = 'Beharrezko eremuren bat falta da.';
|
||||
|
||||
@@ -71,9 +71,10 @@ $string['pathsunsecuredataroot'] = 'Dataroot-en kokapena ez da segurua';
|
||||
$string['pathswrongadmindir'] = 'Kudeaketa direktorioa ez da existitzen';
|
||||
$string['phpextension'] = '{$a} PHP luzapena';
|
||||
$string['phpversion'] = 'PHP bertsioa';
|
||||
$string['phpversionhelp'] = '<p>Moodle-k PHP 4.1.0 edo geroagoko bertsioa behar du.</p>
|
||||
$string['phpversionhelp'] = '<p>Moodle-k gutxienez PHP 4.3.0 edo 5.1.0 (5.0.x errore batzuk ditu). </p>
|
||||
<p>Zure bertsioa: {$a}</p>
|
||||
<p>PHP eguneratu edo PHP bertsio berriagoa duen zerbitzari batera jo</p>';
|
||||
<p>PHP eguneratu edo PHP bertsio berriagoa duen zerbitzari batera jo</p>
|
||||
<p>5.0.x baduzu, nahi izanez gero, 4.4.x. bertsiora jaitsi dezakezu</p>';
|
||||
$string['welcomep10'] = '{$a->installername} ({$a->installerversion})';
|
||||
$string['welcomep20'] = 'Orri hau ikusten baduzu <strong>{$a->packname} {$a->packversion}</strong> paketea
|
||||
zure ordenadorean instalatu ahal izan duzu. Zorionak!';
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Automatically generated strings for Moodle installer
|
||||
*
|
||||
* Do not edit this file manually! It contains just a subset of strings
|
||||
* needed during the very first steps of installation. This file was
|
||||
* generated automatically by export-installer.php (which is part of AMOS
|
||||
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
|
||||
* list of strings defined in /install/stringnames.txt.
|
||||
*
|
||||
* @package installer
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['parentlanguage'] = 'fi';
|
||||
$string['thislanguage'] = 'Suomi+';
|
||||
@@ -32,8 +32,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['clianswerno'] = 'n';
|
||||
$string['cliansweryes'] = 'y';
|
||||
$string['cliincorrectvalueerror'] = 'エラー、「 {$a->option} 」の値「 {$a->value} 」が正しくありません。';
|
||||
$string['cliincorrectvalueretry'] = '値が正しくありません、再度お試しください。';
|
||||
$string['cliincorrectvalueerror'] = 'エラー: 「 {$a->option} 」の値「 {$a->value} 」が正しくありません。';
|
||||
$string['cliincorrectvalueretry'] = '値が正しくありません、再度入力してください。';
|
||||
$string['clitypevalue'] = '値を入力してください。';
|
||||
$string['clitypevaluedefault'] = '値を入力してください。デフォルト値 ({$a}) を使用するにはEnterキーを押してください。';
|
||||
$string['cliunknowoption'] = '不明なオプション:
|
||||
|
||||
@@ -32,4 +32,4 @@ defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['parentlanguage'] = '';
|
||||
$string['thisdirection'] = 'ltr';
|
||||
$string['thislanguage'] = 'Lithuanian';
|
||||
$string['thislanguage'] = 'Lietuvių';
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Automatically generated strings for Moodle installer
|
||||
*
|
||||
* Do not edit this file manually! It contains just a subset of strings
|
||||
* needed during the very first steps of installation. This file was
|
||||
* generated automatically by export-installer.php (which is part of AMOS
|
||||
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
|
||||
* list of strings defined in /install/stringnames.txt.
|
||||
*
|
||||
* @package installer
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['parentlanguage'] = 'no';
|
||||
$string['thisdirection'] = 'ltr';
|
||||
$string['thislanguage'] = 'Davvisámegiella';
|
||||
@@ -36,7 +36,7 @@ $string['cliincorrectvalueerror'] = '错误,将“{$a->option}”的值设为
|
||||
$string['cliincorrectvalueretry'] = '不正确的值,请重试';
|
||||
$string['clitypevalue'] = '输入值';
|
||||
$string['clitypevaluedefault'] = '输入值,按回车使用缺省值({$a})';
|
||||
$string['cliunknowoption'] = '错误选项:
|
||||
$string['cliunknowoption'] = '未识别的选项:
|
||||
{$a}
|
||||
请使用 --help 选项。';
|
||||
$string['cliyesnoprompt'] = '输入y(表示是)或n(表示否)';
|
||||
|
||||
+1
-1
@@ -1124,7 +1124,7 @@ $string['users'] = 'Users';
|
||||
$string['userquota'] = 'User quota';
|
||||
$string['usesitenameforsitepages'] = 'Use site name for site pages';
|
||||
$string['usetags'] = 'Enable tags functionality';
|
||||
$string['validateerror'] = 'This value was not valid:';
|
||||
$string['validateerror'] = 'This value is not valid';
|
||||
$string['verifychangedemail'] = 'Restrict domains when changing email';
|
||||
$string['warningcurrentsetting'] = 'Invalid current value: {$a}';
|
||||
$string['warningiconvbuggy'] = 'Your version of the iconv library does not support the //IGNORE modifier. You should install the mbstring extension which can be used instead for cleaning strings containing invalid UTF-8 characters.';
|
||||
|
||||
@@ -145,6 +145,7 @@ $string['cannotsetupblock'] = 'Blocks tables could NOT be set up successfully!';
|
||||
$string['cannotsetupcapformod'] = 'Could not set up the capabilities for {$a}';
|
||||
$string['cannotsetupcapforplugin'] = 'Could not set up the capabilities for {$a}';
|
||||
$string['cannotshowhidecoursesincategory'] = 'Cannot show/hide the courses in category {$a}.';
|
||||
$string['cannotsignup'] = 'You cannot create a new account because you are already logged in as {$a}.';
|
||||
$string['cannotunassigncap'] = 'Could not unassign deprecated capability {$a->cap} from role {$a->role}';
|
||||
$string['cannotunassignrolefrom'] = 'Cannot unassign this user from role id: {$a}';
|
||||
$string['cannotunzipfile'] = 'Cannot unzip file';
|
||||
|
||||
@@ -35,9 +35,11 @@ $string['categoryrole'] = 'Category role';
|
||||
$string['contains'] = 'contains';
|
||||
$string['content'] = 'Content';
|
||||
$string['contentandheadings'] = 'Content and headings';
|
||||
$string['coursecategory'] = 'course category';
|
||||
$string['courserole'] = 'Course role';
|
||||
$string['courserolelabel'] = '{$a->label} is {$a->rolename} in {$a->coursename} from {$a->categoryname}';
|
||||
$string['courserolelabelerror'] = '{$a->label} error: course {$a->coursename} does not exist';
|
||||
$string['coursevalue'] = 'course value';
|
||||
$string['datelabelisafter'] = '{$a->label} is after {$a->after}';
|
||||
$string['datelabelisbefore'] = '{$a->label} is before {$a->before}';
|
||||
$string['datelabelisbetween'] = '{$a->label} is between {$a->after} and {$a->before}';
|
||||
@@ -63,6 +65,7 @@ $string['isempty'] = 'is empty';
|
||||
$string['isequalto'] = 'is equal to';
|
||||
$string['isnotdefined'] = 'isn\'t defined';
|
||||
$string['isnotequalto'] = 'isn\'t equal to';
|
||||
$string['limiterfor'] = '{$a} field limiter';
|
||||
$string['neveraccessed'] = 'Never accessed';
|
||||
$string['nevermodified'] = 'Never modified';
|
||||
$string['newfilter'] = 'New filter';
|
||||
@@ -70,6 +73,8 @@ $string['nofiltersenabled'] = 'No filter plugins have been enabled on this site.
|
||||
$string['off'] = 'Off';
|
||||
$string['offbutavailable'] = 'Off, but available';
|
||||
$string['on'] = 'On';
|
||||
$string['profilefilterfield'] = 'Profile field name';
|
||||
$string['profilefilterlimiter'] = 'Profile field operator';
|
||||
$string['profilelabel'] = '{$a->label}: {$a->profile} {$a->operator} {$a->value}';
|
||||
$string['profilelabelnovalue'] = '{$a->label}: {$a->profile} {$a->operator}';
|
||||
$string['removeall'] = 'Remove all filters';
|
||||
@@ -79,3 +84,4 @@ $string['startswith'] = 'starts with';
|
||||
$string['tablenosave'] = 'Changes in table above are saved automatically.';
|
||||
$string['textlabel'] = '{$a->label} {$a->operator} {$a->value}';
|
||||
$string['textlabelnovalue'] = '{$a->label} {$a->operator}';
|
||||
$string['valuefor'] = '{$a} value';
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ $string['err_alphanumeric'] = 'You must enter only letters or numbers here.';
|
||||
$string['err_email'] = 'You must enter a valid email address here.';
|
||||
$string['err_lettersonly'] = 'You must enter only letters here.';
|
||||
$string['err_maxfiles'] = 'You must not attach more than {$a} files here.';
|
||||
$string['err_maxlength'] = 'You must enter not more than {$a->format} characters here.';
|
||||
$string['err_maxlength'] = 'You must enter no more than {$a->format} characters here.';
|
||||
$string['err_minlength'] = 'You must enter at least {$a->format} characters here.';
|
||||
$string['err_nonzero'] = 'You must enter a number not starting with a 0 here.';
|
||||
$string['err_nopunctuation'] = 'You must enter no punctuation characters here.';
|
||||
|
||||
+2
-1
@@ -1566,7 +1566,7 @@ $string['rssarticles'] = 'Number of RSS recent articles';
|
||||
$string['rsserror'] = 'Error reading RSS data';
|
||||
$string['rsserrorauth'] = 'Your RSS link does not contain a valid authentication token.';
|
||||
$string['rsserrorguest'] = 'This feed uses guest access to access the data, but guest does not have permission to read the data. Visit the original location that this feed comes from (URL) as a valid user and get a new RSS link from there.';
|
||||
$string['rsskeyshelp'] = 'To ensure security and privacy, RSS feed URLs contain a special token that identifies the user they are for. This prevents other users from accessing areas of Moodle they shouldn\'t have access to via RSS feeds.</p><p>This token is automatically created the first time you access an area of Moodle that produces an RSS feed. If you feel that your RSS feed token has been compromised in some way you can request a new one by clicking the Reset link here. Please note that your current RSS feed URLs will then become invalid.';
|
||||
$string['rsskeyshelp'] = '<p>To ensure security and privacy, RSS feed URLs contain a special token that identifies the user they are for. This prevents other users from accessing areas of the site where they are not allowed.</p><p>The token is automatically created the first time you access an area that produces an RSS feed. If you think that your RSS feed token has been compromised, you can request a new one by clicking the reset link. Please note that your current RSS feed URLs will then become invalid.</p>';
|
||||
$string['rsstype'] = 'RSS feed for this activity';
|
||||
$string['saveandnext'] = 'Save and show next';
|
||||
$string['savedat'] = 'Saved at:';
|
||||
@@ -1904,6 +1904,7 @@ $string['usemessageform'] = 'or use the form below to send a message to the sele
|
||||
$string['user'] = 'User';
|
||||
$string['userconfirmed'] = 'Confirmed {$a}';
|
||||
$string['usercurrentsettings'] = 'My profile settings';
|
||||
$string['useractivity'] = 'Activity';
|
||||
$string['userdata'] = 'User data';
|
||||
$string['userdeleted'] = 'This user account has been deleted';
|
||||
$string['userdescription'] = 'Description';
|
||||
|
||||
@@ -62,16 +62,16 @@ $string['close'] = 'Close';
|
||||
$string['commonrepositorysettings'] = 'Common repository settings';
|
||||
$string['configallowexternallinks'] = 'This option enables all users to choose whether or not external media is copied into Moodle or not. If this is off then media is always copied into Moodle (this is usually best for overall data integrity and security). If this is on then users can choose each time they add media to a text.';
|
||||
$string['configcacheexpire'] = 'The amount of time that file listings are cached locally (in seconds) when browsing external repositories.';
|
||||
$string['configgetfiletimeout'] = 'Timeout in seconds for downloading the external file into moodle.';
|
||||
$string['configgetfiletimeout'] = 'Timeout in seconds for downloading an external file into Moodle.';
|
||||
$string['configsaved'] = 'Configuration saved!';
|
||||
$string['configsyncfiletimeout'] = 'Timeout in seconds for syncronising the external file size.';
|
||||
$string['configsyncimagetimeout'] = 'Timeout in seconds for downloading an image file from external repository during syncronisation.';
|
||||
$string['confirmdelete'] = 'Are you sure you want to delete this repository - {$a}? If you choose "Continue and download", file references to external contents will be downloaded to moodle, but it could take long time to process.';
|
||||
$string['confirmdelete'] = 'Are you sure you want to delete the repository {$a}? If you choose "Continue and download", file references to external contents will be downloaded to Moodle. This could take a long time to process.';
|
||||
$string['confirmdeletefile'] = 'Are you sure you want to delete this file?';
|
||||
$string['confirmrenamefile'] = 'Are you sure you want to rename/move this file? There are {$a} alias/shortcut files that use this file as their source. If you proceed then those aliases will be converted to true copies.';
|
||||
$string['confirmdeletefilewithhref'] = 'Are you sure you want to delete this file? There are {$a} alias/shortcut files that use this file as their source. If you proceed then those aliases will be converted to true copies.';
|
||||
$string['confirmdeletefolder'] = 'Are you sure you want to delete this folder? All files and subfolders will be deleted.';
|
||||
$string['confirmremove'] = 'Are you sure you want to remove this repository plugin, its options and <strong>all of its instances</strong> - {$a}? If you choose "Continue and download", file references to external contents will be downloaded to moodle, but it could take long time to process.';
|
||||
$string['confirmremove'] = 'Are you sure you want to remove this repository plugin, its options and <strong>all of its instances</strong> - {$a}? If you choose "Continue and download", file references to external contents will be downloaded to Moodle. This could take a long time to process.';
|
||||
$string['confirmrenamefolder'] = ' Are you sure you want to move/rename this folder? Any alias/shortcut files that reference files in this folder will be converted into true copies.';
|
||||
$string['continueuninstall'] = 'Continue';
|
||||
$string['continueuninstallanddownload'] = 'Continue and download';
|
||||
@@ -242,5 +242,5 @@ $string['usenonjsfilemanager'] = 'Open file manager in new window';
|
||||
$string['usenonjsfilepicker'] = 'Open file picker in new window';
|
||||
$string['unzipped'] = 'Unzipped successfully';
|
||||
$string['wrongcontext'] = 'You cannot access to this context';
|
||||
$string['xhtmlerror'] = 'You are probably using XHTML strict header, some YUI Component doesn\'t work in this mode, please turn it off in moodle';
|
||||
$string['xhtmlerror'] = 'You are probably using an XHTML strict header. Certain YUI components don\'t work in this mode; please turn it off.';
|
||||
$string['ziped'] = 'Compress folder successfully';
|
||||
|
||||
+2
-2
@@ -171,10 +171,10 @@ $string['defaultx'] = 'Default: {$a}';
|
||||
$string['defineroles'] = 'Define roles';
|
||||
$string['deletecourseoverrides'] = 'Delete all overrides in course';
|
||||
$string['deletelocalroles'] = 'Delete all local role assignments';
|
||||
$string['deleterolesure'] = 'Are you sure that you want to delete role "{$a->name} ({$a->shortname})"?</p><p>Currently this role is assigned to {$a->count} users.';
|
||||
$string['deleterolesure'] = '<p>Are you sure that you want to delete role "{$a->name} ({$a->shortname})"?</p><p>Currently this role is assigned to {$a->count} users.</p>';
|
||||
$string['deletexrole'] = 'Delete {$a} role';
|
||||
$string['duplicaterole'] = 'Duplicate role';
|
||||
$string['duplicaterolesure'] = 'Are you sure that you want to duplicate role "{$a->name} ({$a->shortname})"?</p>';
|
||||
$string['duplicaterolesure'] = '<p>Are you sure that you want to duplicate role "{$a->name} ({$a->shortname})"?</p>';
|
||||
$string['editingrolex'] = 'Editing role \'{$a}\'';
|
||||
$string['editrole'] = 'Edit role';
|
||||
$string['editxrole'] = 'Edit {$a} role';
|
||||
|
||||
@@ -127,6 +127,7 @@ $string['missingusername'] = 'Missing username';
|
||||
$string['missingversionfile'] = 'Coding error: version.php file is missing for the component {$a}';
|
||||
$string['mobilewsdisabled'] = 'Disabled';
|
||||
$string['mobilewsenabled'] = 'Enabled';
|
||||
$string['nameexists'] = 'This name is already in use by another service';
|
||||
$string['nocapabilitytouseparameter'] = 'The user does not have the required capability to use the parameter {$a}';
|
||||
$string['nofunctions'] = 'This service has no functions.';
|
||||
$string['norequiredcapability'] = 'No required capability';
|
||||
|
||||
+31
-16
@@ -2927,7 +2927,7 @@ function get_capability_info($capabilityname) {
|
||||
|
||||
if (empty($ACCESSLIB_PRIVATE->capabilities)) {
|
||||
$ACCESSLIB_PRIVATE->capabilities = array();
|
||||
$caps = $DB->get_records('capabilities', array(), 'id, name, captype, riskbitmask');
|
||||
$caps = $DB->get_records('capabilities', array(), '', 'id, name, captype, riskbitmask');
|
||||
foreach ($caps as $cap) {
|
||||
$capname = $cap->name;
|
||||
unset($cap->id);
|
||||
@@ -6418,14 +6418,17 @@ class context_user extends context {
|
||||
protected static function create_level_instances() {
|
||||
global $DB;
|
||||
|
||||
$sql = "INSERT INTO {context} (contextlevel, instanceid)
|
||||
SELECT ".CONTEXT_USER.", u.id
|
||||
$sql = "SELECT ".CONTEXT_USER.", u.id
|
||||
FROM {user} u
|
||||
WHERE u.deleted = 0
|
||||
AND NOT EXISTS (SELECT 'x'
|
||||
FROM {context} cx
|
||||
WHERE u.id = cx.instanceid AND cx.contextlevel=".CONTEXT_USER.")";
|
||||
$DB->execute($sql);
|
||||
$contextdata = $DB->get_recordset_sql($sql);
|
||||
foreach ($contextdata as $context) {
|
||||
context::insert_context_record(CONTEXT_USER, $context->id, null);
|
||||
}
|
||||
$contextdata->close();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6626,13 +6629,16 @@ class context_coursecat extends context {
|
||||
protected static function create_level_instances() {
|
||||
global $DB;
|
||||
|
||||
$sql = "INSERT INTO {context} (contextlevel, instanceid)
|
||||
SELECT ".CONTEXT_COURSECAT.", cc.id
|
||||
$sql = "SELECT ".CONTEXT_COURSECAT.", cc.id
|
||||
FROM {course_categories} cc
|
||||
WHERE NOT EXISTS (SELECT 'x'
|
||||
FROM {context} cx
|
||||
WHERE cc.id = cx.instanceid AND cx.contextlevel=".CONTEXT_COURSECAT.")";
|
||||
$DB->execute($sql);
|
||||
$contextdata = $DB->get_recordset_sql($sql);
|
||||
foreach ($contextdata as $context) {
|
||||
context::insert_context_record(CONTEXT_COURSECAT, $context->id, null);
|
||||
}
|
||||
$contextdata->close();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6849,13 +6855,16 @@ class context_course extends context {
|
||||
protected static function create_level_instances() {
|
||||
global $DB;
|
||||
|
||||
$sql = "INSERT INTO {context} (contextlevel, instanceid)
|
||||
SELECT ".CONTEXT_COURSE.", c.id
|
||||
$sql = "SELECT ".CONTEXT_COURSE.", c.id
|
||||
FROM {course} c
|
||||
WHERE NOT EXISTS (SELECT 'x'
|
||||
FROM {context} cx
|
||||
WHERE c.id = cx.instanceid AND cx.contextlevel=".CONTEXT_COURSE.")";
|
||||
$DB->execute($sql);
|
||||
$contextdata = $DB->get_recordset_sql($sql);
|
||||
foreach ($contextdata as $context) {
|
||||
context::insert_context_record(CONTEXT_COURSE, $context->id, null);
|
||||
}
|
||||
$contextdata->close();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7103,13 +7112,16 @@ class context_module extends context {
|
||||
protected static function create_level_instances() {
|
||||
global $DB;
|
||||
|
||||
$sql = "INSERT INTO {context} (contextlevel, instanceid)
|
||||
SELECT ".CONTEXT_MODULE.", cm.id
|
||||
$sql = "SELECT ".CONTEXT_MODULE.", cm.id
|
||||
FROM {course_modules} cm
|
||||
WHERE NOT EXISTS (SELECT 'x'
|
||||
FROM {context} cx
|
||||
WHERE cm.id = cx.instanceid AND cx.contextlevel=".CONTEXT_MODULE.")";
|
||||
$DB->execute($sql);
|
||||
$contextdata = $DB->get_recordset_sql($sql);
|
||||
foreach ($contextdata as $context) {
|
||||
context::insert_context_record(CONTEXT_MODULE, $context->id, null);
|
||||
}
|
||||
$contextdata->close();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7320,13 +7332,16 @@ class context_block extends context {
|
||||
protected static function create_level_instances() {
|
||||
global $DB;
|
||||
|
||||
$sql = "INSERT INTO {context} (contextlevel, instanceid)
|
||||
SELECT ".CONTEXT_BLOCK.", bi.id
|
||||
$sql = "SELECT ".CONTEXT_BLOCK.", bi.id
|
||||
FROM {block_instances} bi
|
||||
WHERE NOT EXISTS (SELECT 'x'
|
||||
FROM {context} cx
|
||||
WHERE bi.id = cx.instanceid AND cx.contextlevel=".CONTEXT_BLOCK.")";
|
||||
$DB->execute($sql);
|
||||
$contextdata = $DB->get_recordset_sql($sql);
|
||||
foreach ($contextdata as $context) {
|
||||
context::insert_context_record(CONTEXT_BLOCK, $context->id, null);
|
||||
}
|
||||
$contextdata->close();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+19
-14
@@ -3224,16 +3224,20 @@ class admin_setting_configtime extends admin_setting {
|
||||
$defaultinfo = NULL;
|
||||
}
|
||||
|
||||
$return = '<div class="form-time defaultsnext">'.
|
||||
'<select id="'.$this->get_id().'h" name="'.$this->get_full_name().'[h]">';
|
||||
$return = '<div class="form-time defaultsnext">';
|
||||
$return .= '<label class="accesshide" for="' . $this->get_id() . 'h">' . get_string('hours') . '</label>';
|
||||
$return .= '<select id="' . $this->get_id() . 'h" name="' . $this->get_full_name() . '[h]">';
|
||||
for ($i = 0; $i < 24; $i++) {
|
||||
$return .= '<option value="'.$i.'"'.($i == $data['h'] ? ' selected="selected"' : '').'>'.$i.'</option>';
|
||||
$return .= '<option value="' . $i . '"' . ($i == $data['h'] ? ' selected="selected"' : '') . '>' . $i . '</option>';
|
||||
}
|
||||
$return .= '</select>:<select id="'.$this->get_id().'m" name="'.$this->get_full_name().'[m]">';
|
||||
$return .= '</select>:';
|
||||
$return .= '<label class="accesshide" for="' . $this->get_id() . 'm">' . get_string('minutes') . '</label>';
|
||||
$return .= '<select id="' . $this->get_id() . 'm" name="' . $this->get_full_name() . '[m]">';
|
||||
for ($i = 0; $i < 60; $i += 5) {
|
||||
$return .= '<option value="'.$i.'"'.($i == $data['m'] ? ' selected="selected"' : '').'>'.$i.'</option>';
|
||||
$return .= '<option value="' . $i . '"' . ($i == $data['m'] ? ' selected="selected"' : '') . '>' . $i . '</option>';
|
||||
}
|
||||
$return .= '</select></div>';
|
||||
$return .= '</select>';
|
||||
$return .= '</div>';
|
||||
return format_admin_setting($this, $this->visiblename, $return, $this->description, false, '', $defaultinfo, $query);
|
||||
}
|
||||
|
||||
@@ -6952,21 +6956,22 @@ function format_admin_setting($setting, $title='', $form='', $description='', $l
|
||||
}
|
||||
|
||||
|
||||
$adminroot = admin_get_root();
|
||||
$error = '';
|
||||
if (array_key_exists($fullname, $adminroot->errors)) {
|
||||
$error = '<div><span class="error">' . $adminroot->errors[$fullname]->error . '</span></div>';
|
||||
}
|
||||
|
||||
$str = '
|
||||
<div class="form-item clearfix" id="admin-'.$setting->name.'">
|
||||
<div class="form-label">
|
||||
<label '.$labelfor.'>'.highlightfast($query, $title).$override.$warning.'</label>
|
||||
<span class="form-shortname">'.highlightfast($query, $name).'</span>
|
||||
</div>
|
||||
<div class="form-setting">'.$form.$defaultinfo.'</div>
|
||||
<div class="form-setting">'.$error.$form.$defaultinfo.'</div>
|
||||
<div class="form-description">'.highlight($query, markdown_to_html($description)).'</div>
|
||||
</div>';
|
||||
|
||||
$adminroot = admin_get_root();
|
||||
if (array_key_exists($fullname, $adminroot->errors)) {
|
||||
$str = '<fieldset class="error"><legend>'.$adminroot->errors[$fullname]->error.'</legend>'.$str.'</fieldset>';
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
@@ -7763,11 +7768,11 @@ class admin_setting_webservicesoverview extends admin_setting {
|
||||
get_string('enablemobilewebservice', 'admin'),
|
||||
get_string('configenablemobilewebservice',
|
||||
'admin', ''), 0); //we don't want to display it but to know the ws mobile status
|
||||
$manageserviceurl = new moodle_url("/admin/settings.php?section=externalservices");
|
||||
$manageserviceurl = new moodle_url("/admin/settings.php?section=mobile");
|
||||
$wsmobileparam = new stdClass();
|
||||
$wsmobileparam->enablemobileservice = get_string('enablemobilewebservice', 'admin');
|
||||
$wsmobileparam->manageservicelink = html_writer::link($manageserviceurl,
|
||||
get_string('externalservices', 'webservice'));
|
||||
get_string('mobile', 'admin'));
|
||||
$mobilestatus = $enablemobile->get_setting()?get_string('mobilewsenabled', 'webservice'):get_string('mobilewsdisabled', 'webservice');
|
||||
$wsmobileparam->wsmobilestatus = html_writer::tag('strong', $mobilestatus);
|
||||
$return .= $OUTPUT->heading(get_string('enablemobilewebservice', 'admin'), 3, 'main');
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ require_once(dirname(__FILE__) . '/../../config.php');
|
||||
// Initialise ALL common incoming parameters here, up front.
|
||||
$courseid = required_param('courseid', PARAM_INT);
|
||||
$pagelayout = required_param('pagelayout', PARAM_ALPHAEXT);
|
||||
$pagetype = required_param('pagetype', PARAM_ALPHAEXT);
|
||||
$pagetype = required_param('pagetype', PARAM_ALPHANUMEXT);
|
||||
$contextid = required_param('contextid', PARAM_INT);
|
||||
$subpage = optional_param('subpage', '', PARAM_ALPHANUMEXT);
|
||||
$cmid = optional_param('cmid', null, PARAM_INT);
|
||||
|
||||
+5
-1
@@ -114,7 +114,11 @@ class auth_plugin_base {
|
||||
'department',
|
||||
'phone1',
|
||||
'phone2',
|
||||
'address'
|
||||
'address',
|
||||
'firstnamephonetic',
|
||||
'lastnamephonetic',
|
||||
'middlename',
|
||||
'alternatename'
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
+10
-7
@@ -843,9 +843,10 @@ function badges_get_badges($type, $courseid = 0, $sort = '', $dir = '', $page =
|
||||
*/
|
||||
function badges_get_user_badges($userid, $courseid = 0, $page = 0, $perpage = 0, $search = '', $onlypublic = false) {
|
||||
global $DB;
|
||||
$badges = array();
|
||||
|
||||
$params[] = $userid;
|
||||
$params = array(
|
||||
'userid' => $userid
|
||||
);
|
||||
$sql = 'SELECT
|
||||
bi.uniquehash,
|
||||
bi.dateissued,
|
||||
@@ -860,18 +861,19 @@ function badges_get_user_badges($userid, $courseid = 0, $page = 0, $perpage = 0,
|
||||
{user} u
|
||||
WHERE b.id = bi.badgeid
|
||||
AND u.id = bi.userid
|
||||
AND bi.userid = ?';
|
||||
AND bi.userid = :userid';
|
||||
|
||||
if (!empty($search)) {
|
||||
$sql .= ' AND (' . $DB->sql_like('b.name', '?', false) . ') ';
|
||||
$params[] = "%$search%";
|
||||
$sql .= ' AND (' . $DB->sql_like('b.name', ':search', false) . ') ';
|
||||
$params['search'] = '%'.$DB->sql_like_escape($search).'%';
|
||||
}
|
||||
if ($onlypublic) {
|
||||
$sql .= ' AND (bi.visible = 1) ';
|
||||
}
|
||||
|
||||
if ($courseid != 0) {
|
||||
$sql .= ' AND (b.courseid = ' . $courseid . ') ';
|
||||
$sql .= ' AND (b.courseid = :courseid) ';
|
||||
$params['courseid'] = $courseid;
|
||||
}
|
||||
$sql .= ' ORDER BY bi.dateissued DESC';
|
||||
$badges = $DB->get_records_sql($sql, $params, $page * $perpage, $perpage);
|
||||
@@ -1124,7 +1126,8 @@ function badges_download($userid) {
|
||||
if ($zipper->archive_to_pathname($filelist, $tempzip)) {
|
||||
send_temp_file($tempzip, 'badges.zip');
|
||||
} else {
|
||||
debugging("Problems with archiving the files.");
|
||||
debugging("Problems with archiving the files.", DEBUG_DEVELOPER);
|
||||
die;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -302,6 +302,11 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext {
|
||||
$loops = $timeout;
|
||||
}
|
||||
|
||||
// DOM will never change on non-javascript case; do not wait or try again.
|
||||
if (!$this->running_javascript()) {
|
||||
$loops = 1;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $loops; $i++) {
|
||||
// We catch the exception thrown by the step definition to execute it again.
|
||||
try {
|
||||
@@ -320,10 +325,12 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($microsleep) {
|
||||
usleep(100000);
|
||||
} else {
|
||||
sleep(1);
|
||||
if ($this->running_javascript()) {
|
||||
if ($microsleep) {
|
||||
usleep(100000);
|
||||
} else {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -221,7 +221,8 @@ class behat_config_manager {
|
||||
),
|
||||
'Moodle\BehatExtension\Extension' => array(
|
||||
'formatters' => array(
|
||||
'moodle_progress' => 'Moodle\BehatExtension\Formatter\MoodleProgressFormatter'
|
||||
'moodle_progress' => 'Moodle\BehatExtension\Formatter\MoodleProgressFormatter',
|
||||
'moodle_list' => 'Moodle\BehatExtension\Formatter\MoodleListFormatter'
|
||||
),
|
||||
'features' => $features,
|
||||
'steps_definitions' => $stepsdefinitions
|
||||
|
||||
@@ -39,41 +39,47 @@ class behat_selectors {
|
||||
* @var Allowed types when using text selectors arguments.
|
||||
*/
|
||||
protected static $allowedtextselectors = array(
|
||||
'dialogue' => 'dialogue',
|
||||
'activity' => 'activity',
|
||||
'block' => 'block',
|
||||
'region' => 'region',
|
||||
'table_row' => 'table_row',
|
||||
'list_item' => 'list_item',
|
||||
'table' => 'table',
|
||||
'fieldset' => 'fieldset',
|
||||
'css_element' => 'css_element',
|
||||
'xpath_element' => 'xpath_element'
|
||||
'dialogue' => 'dialogue',
|
||||
'fieldset' => 'fieldset',
|
||||
'list_item' => 'list_item',
|
||||
'question' => 'question',
|
||||
'region' => 'region',
|
||||
'section' => 'section',
|
||||
'table' => 'table',
|
||||
'table_row' => 'table_row',
|
||||
'xpath_element' => 'xpath_element',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var Allowed types when using selector arguments.
|
||||
*/
|
||||
protected static $allowedselectors = array(
|
||||
'dialogue' => 'dialogue',
|
||||
'activity' => 'activity',
|
||||
'block' => 'block',
|
||||
'region' => 'region',
|
||||
'table_row' => 'table_row',
|
||||
'list_item' => 'list_item',
|
||||
'link' => 'link',
|
||||
'button' => 'button',
|
||||
'link_or_button' => 'link_or_button',
|
||||
'select' => 'select',
|
||||
'checkbox' => 'checkbox',
|
||||
'radio' => 'radio',
|
||||
'file' => 'file',
|
||||
'filemanager' => 'filemanager',
|
||||
'optgroup' => 'optgroup',
|
||||
'option' => 'option',
|
||||
'table' => 'table',
|
||||
'css_element' => 'css_element',
|
||||
'dialogue' => 'dialogue',
|
||||
'field' => 'field',
|
||||
'fieldset' => 'fieldset',
|
||||
'file' => 'file',
|
||||
'filemanager' => 'filemanager',
|
||||
'link' => 'link',
|
||||
'link_or_button' => 'link_or_button',
|
||||
'list_item' => 'list_item',
|
||||
'optgroup' => 'optgroup',
|
||||
'option' => 'option',
|
||||
'question' => 'question',
|
||||
'radio' => 'radio',
|
||||
'region' => 'region',
|
||||
'section' => 'section',
|
||||
'select' => 'select',
|
||||
'table' => 'table',
|
||||
'table_row' => 'table_row',
|
||||
'text' => 'text',
|
||||
'css_element' => 'css_element',
|
||||
'xpath_element' => 'xpath_element'
|
||||
);
|
||||
|
||||
@@ -86,8 +92,14 @@ class behat_selectors {
|
||||
* @var XPaths for moodle elements.
|
||||
*/
|
||||
protected static $moodleselectors = array(
|
||||
'text' => <<<XPATH
|
||||
//*[contains(., %locator%)][count(./descendant::*[contains(., %locator%)]) = 0]
|
||||
'activity' => <<<XPATH
|
||||
//li[contains(concat(' ', normalize-space(@class), ' '), ' activity ')][normalize-space(.) = %locator% ]
|
||||
XPATH
|
||||
, 'block' => <<<XPATH
|
||||
//div[contains(concat(' ', normalize-space(@class), ' '), ' block ') and
|
||||
(contains(concat(' ', normalize-space(@class), ' '), concat(' ', %locator%, ' ')) or
|
||||
descendant::h2[normalize-space(.) = %locator%] or
|
||||
@aria-label = %locator%)]
|
||||
XPATH
|
||||
, 'dialogue' => <<<XPATH
|
||||
//div[contains(concat(' ', normalize-space(@class), ' '), ' moodle-dialogue ') and
|
||||
@@ -96,28 +108,36 @@ XPATH
|
||||
]) = %locator%] |
|
||||
//div[contains(concat(' ', normalize-space(@class), ' '), ' yui-dialog ') and
|
||||
normalize-space(descendant::div[@class='hd']) = %locator%]
|
||||
XPATH
|
||||
, 'block' => <<<XPATH
|
||||
//div[contains(concat(' ', normalize-space(@class), ' '), ' block ') and
|
||||
(contains(concat(' ', normalize-space(@class), ' '), concat(' ', %locator%, ' ')) or
|
||||
descendant::h2[normalize-space(.) = %locator%] or
|
||||
@aria-label = %locator%)]
|
||||
XPATH
|
||||
, 'region' => <<<XPATH
|
||||
//*[self::div | self::section | self::aside | self::header | self::footer][./@id = %locator%]
|
||||
XPATH
|
||||
, 'table_row' => <<<XPATH
|
||||
.//tr[contains(normalize-space(.), %locator%)]
|
||||
XPATH
|
||||
, 'list_item' => <<<XPATH
|
||||
.//li[contains(normalize-space(.), %locator%)]
|
||||
XPATH
|
||||
, 'filemanager' => <<<XPATH
|
||||
//div[contains(concat(' ', normalize-space(@class), ' '), ' ffilemanager ')]
|
||||
/descendant::input[@id = //label[contains(normalize-space(string(.)), %locator%)]/@for]
|
||||
XPATH
|
||||
, 'list_item' => <<<XPATH
|
||||
.//li[contains(normalize-space(.), %locator%)]
|
||||
XPATH
|
||||
, 'question' => <<<XPATH
|
||||
//div[contains(concat(' ', normalize-space(@class), ' '), ' que ')]
|
||||
[contains(div[@class='content']/div[@class='formulation'], %locator%)]
|
||||
XPATH
|
||||
, 'region' => <<<XPATH
|
||||
//*[self::div | self::section | self::aside | self::header | self::footer][./@id = %locator%]
|
||||
XPATH
|
||||
, 'section' => <<<XPATH
|
||||
//li[contains(concat(' ', normalize-space(@class), ' '), ' section ')][./descendant::*[self::h3]
|
||||
[normalize-space(.) = %locator%][contains(concat(' ', normalize-space(@class), ' '), ' sectionname ') or
|
||||
contains(concat(' ', normalize-space(@class), ' '), ' section-title ')]] |
|
||||
//div[contains(concat(' ', normalize-space(@class), ' '), ' sitetopic ')]
|
||||
[./descendant::*[self::h2][normalize-space(.) = %locator%] or %locator% = 'frontpage']
|
||||
XPATH
|
||||
, 'table' => <<<XPATH
|
||||
.//table[(./@id = %locator% or contains(.//caption, %locator%) or contains(concat(' ', normalize-space(@class), ' '), %locator% ))]
|
||||
XPATH
|
||||
, 'table_row' => <<<XPATH
|
||||
.//tr[contains(normalize-space(.), %locator%)]
|
||||
XPATH
|
||||
, 'text' => <<<XPATH
|
||||
//*[contains(., %locator%)][count(./descendant::*[contains(., %locator%)]) = 0]
|
||||
XPATH
|
||||
);
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ class behat_form_select extends behat_form_field {
|
||||
*/
|
||||
protected function get_selected_options($returntexts = true) {
|
||||
|
||||
$method = 'getText';
|
||||
$method = 'getHtml';
|
||||
if ($returntexts === false) {
|
||||
$method = 'getValue';
|
||||
}
|
||||
|
||||
+23
-14
@@ -517,6 +517,11 @@ class block_manager {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Block regions should not be docked during editing when all the blocks are hidden.
|
||||
if ($this->page->user_is_editing() && $this->page->user_can_edit_blocks()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->check_is_loaded();
|
||||
$this->ensure_content_created($region, $output);
|
||||
if (!$this->region_has_content($region, $output)) {
|
||||
@@ -524,7 +529,7 @@ class block_manager {
|
||||
return false;
|
||||
}
|
||||
foreach ($this->visibleblockcontent[$region] as $instance) {
|
||||
if (!empty($instance->content) && !get_user_preferences('docked_block_instance_'.$instance->blockinstanceid, 0)) {
|
||||
if (!get_user_preferences('docked_block_instance_'.$instance->blockinstanceid, 0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -776,19 +781,23 @@ class block_manager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method, calls add_block repeatedly for all the blocks in $blocks.
|
||||
* Convenience method, calls add_block repeatedly for all the blocks in $blocks. Optionally, a starting weight
|
||||
* can be used to decide the starting point that blocks are added in the region, the weight is passed to {@link add_block}
|
||||
* and incremented by the position of the block in the $blocks array
|
||||
*
|
||||
* @param array $blocks array with array keys the region names, and values an array of block names.
|
||||
* @param string $pagetypepattern optional. Passed to @see add_block()
|
||||
* @param string $subpagepattern optional. Passed to @see add_block()
|
||||
* @param string $pagetypepattern optional. Passed to {@link add_block()}
|
||||
* @param string $subpagepattern optional. Passed to {@link add_block()}
|
||||
* @param boolean $showinsubcontexts optional. Passed to {@link add_block()}
|
||||
* @param integer $weight optional. Determines the starting point that the blocks are added in the region.
|
||||
*/
|
||||
public function add_blocks($blocks, $pagetypepattern = NULL, $subpagepattern = NULL, $showinsubcontexts=false, $weight=0) {
|
||||
$initialweight = $weight;
|
||||
$this->add_regions(array_keys($blocks), false);
|
||||
foreach ($blocks as $region => $regionblocks) {
|
||||
$weight = 0;
|
||||
foreach ($regionblocks as $blockname) {
|
||||
foreach ($regionblocks as $offset => $blockname) {
|
||||
$weight = $initialweight + $offset;
|
||||
$this->add_block($blockname, $region, $weight, $showinsubcontexts, $pagetypepattern, $subpagepattern);
|
||||
$weight += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2188,12 +2197,12 @@ function blocks_find_block($blockid, $blocksarray) {
|
||||
|
||||
// Functions for programatically adding default blocks to pages ================
|
||||
|
||||
/**
|
||||
* Parse a list of default blocks. See config-dist for a description of the format.
|
||||
*
|
||||
* @param string $blocksstr
|
||||
* @return array
|
||||
*/
|
||||
/**
|
||||
* Parse a list of default blocks. See config-dist for a description of the format.
|
||||
*
|
||||
* @param string $blocksstr Determines the starting point that the blocks are added in the region.
|
||||
* @return array the parsed list of default blocks
|
||||
*/
|
||||
function blocks_parse_default_blocks_list($blocksstr) {
|
||||
$blocks = array();
|
||||
$bits = explode(':', $blocksstr);
|
||||
@@ -2204,7 +2213,7 @@ function blocks_parse_default_blocks_list($blocksstr) {
|
||||
}
|
||||
}
|
||||
if (!empty($bits)) {
|
||||
$rightbits =trim(array_shift($bits));
|
||||
$rightbits = trim(array_shift($bits));
|
||||
if ($rightbits != '') {
|
||||
$blocks[BLOCK_POS_RIGHT] = explode(',', $rightbits);
|
||||
}
|
||||
|
||||
@@ -54,4 +54,41 @@ class portfolio extends base {
|
||||
public static function get_manage_url() {
|
||||
return new moodle_url('/admin/portfolio.php');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if there should be a way to uninstall the plugin via the administration UI.
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_uninstall_allowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-uninstall hook.
|
||||
* This is intended for disabling of plugin, some DB table purging, etc.
|
||||
*/
|
||||
public function uninstall_cleanup() {
|
||||
global $DB;
|
||||
|
||||
// Get all instances of this portfolio.
|
||||
$count = $DB->count_records('portfolio_instance', array('plugin' => $this->name));
|
||||
if ($count > 0) {
|
||||
// This portfolio is in use, get the it's ID.
|
||||
$rec = $DB->get_record('portfolio_instance', array('plugin' => $this->name));
|
||||
|
||||
// Remove all records from portfolio_instance_config.
|
||||
$DB->delete_records('portfolio_instance_config', array('instance' => $rec->id));
|
||||
// Remove all records from portfolio_instance_user.
|
||||
$DB->delete_records('portfolio_instance_user', array('instance' => $rec->id));
|
||||
// Remove all records from portfolio_log.
|
||||
$DB->delete_records('portfolio_log', array('portfolio' => $rec->id));
|
||||
// Remove all records from portfolio_tempdata.
|
||||
$DB->delete_records('portfolio_tempdata', array('instance' => $rec->id));
|
||||
|
||||
// Remove the record from the portfolio_instance table.
|
||||
$DB->delete_records('portfolio_instance', array('id' => $rec->id));
|
||||
}
|
||||
|
||||
parent::uninstall_cleanup();
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ class memcached extends handler {
|
||||
protected $acquiretimeout = 120;
|
||||
/**
|
||||
* @var int $lockexpire how long to wait before expiring the lock so that other requests
|
||||
* may continue execution, ignored if memcached <= 2.1.0.
|
||||
* may continue execution, ignored if PECL memcached is below version 2.2.0.
|
||||
*/
|
||||
protected $lockexpire = 7200;
|
||||
|
||||
@@ -86,7 +86,7 @@ class memcached extends handler {
|
||||
* @return bool success
|
||||
*/
|
||||
public function start() {
|
||||
// NOTE: memcached <= 2.1.0 expires session locks automatically after max_execution_time,
|
||||
// NOTE: memcached before 2.2.0 expires session locks automatically after max_execution_time,
|
||||
// this leads to major difference compared to other session drivers that timeout
|
||||
// and stop the second request execution instead.
|
||||
|
||||
@@ -119,7 +119,7 @@ class memcached extends handler {
|
||||
ini_set('memcached.sess_prefix', $this->prefix);
|
||||
ini_set('memcached.sess_locking', '1'); // Locking is required!
|
||||
|
||||
// Try to configure lock and expire timeouts - ignored if memcached <=2.1.0.
|
||||
// Try to configure lock and expire timeouts - ignored if memcached is before version 2.2.0.
|
||||
ini_set('memcached.sess_lock_max_wait', $this->acquiretimeout);
|
||||
ini_set('memcached.sess_lock_expire', $this->lockexpire);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user