Compare commits
85 Commits
v3.2.0-rc1
...
v3.2.0-rc2
| Author | SHA1 | Date | |
|---|---|---|---|
| 0fbe41f4cd | |||
| e122972d3f | |||
| 57bfb7c30a | |||
| 529e944a8c | |||
| 8d294e729f | |||
| 82f9746962 | |||
| cbca970ab7 | |||
| 282f0437f1 | |||
| 873a7e1e86 | |||
| 38a8590ed0 | |||
| 45e862c4bd | |||
| d51d8ca2af | |||
| f4565e7147 | |||
| 52a51514f6 | |||
| 42cf4a3470 | |||
| 5d03ab36b5 | |||
| 727145bf1c | |||
| d10ca75b8c | |||
| aacdf8e280 | |||
| aabebc7516 | |||
| 5009bcd9b4 | |||
| 4b2790c580 | |||
| 5e43ccd3b9 | |||
| 783ef76bfc | |||
| 4b631c2d87 | |||
| 7e81bd114e | |||
| 9446cb507c | |||
| 21a5c3c447 | |||
| 9557be1542 | |||
| 05551a935a | |||
| f7d76254fd | |||
| 28f2458448 | |||
| e283c6ca33 | |||
| 26fef01b6b | |||
| d9a9a87835 | |||
| e0ba33697f | |||
| f318b74b49 | |||
| 63531fff79 | |||
| 51e8968635 | |||
| e67c14053e | |||
| 30f023b1b3 | |||
| fce0f1c235 | |||
| 57c01bca0e | |||
| 7d432be4e9 | |||
| 2380daba7b | |||
| 2f5208ea1b | |||
| 1e9487092d | |||
| 3d3fb328b4 | |||
| 23bb1871b3 | |||
| 896718ef79 | |||
| dfe7cbe4cf | |||
| 25bfa25190 | |||
| e47d61e198 | |||
| 87799e9fba | |||
| 30cfed3731 | |||
| 406f1eb76d | |||
| 7f24e5e654 | |||
| 65eb39c0b4 | |||
| 1bce723292 | |||
| f48cc821db | |||
| 0a5cafcbe9 | |||
| 5084343b3f | |||
| a4abacc9a6 | |||
| ff687b9c15 | |||
| b0db945b11 | |||
| d0da94cdf4 | |||
| 02bb0c0637 | |||
| 8abfb7b1bb | |||
| 0840b3e687 | |||
| 6706c1cb12 | |||
| 835f1f9add | |||
| b3fd942b52 | |||
| af28ceb945 | |||
| 538ce414a5 | |||
| f2e599d51c | |||
| fe9864f488 | |||
| f4c39cb983 | |||
| 3d66b5a100 | |||
| b95a05a536 | |||
| 2da36b3750 | |||
| 5ceb68d169 | |||
| c6b4421524 | |||
| 26dca05d02 | |||
| a4e2d64571 | |||
| 1cca9a3479 |
@@ -94,7 +94,8 @@ $isios = core_useragent::is_ios();
|
||||
if ($confirmed or $isios) {
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_heading($COURSE->fullname);
|
||||
$PAGE->set_url('/local/mobile/launch.php', array('service' => $serviceshortname, 'passport' => $passport, 'urlscheme' => $urlscheme));
|
||||
$params = array('service' => $serviceshortname, 'passport' => $passport, 'urlscheme' => $urlscheme, 'confirmed' => $confirmed);
|
||||
$PAGE->set_url("/$CFG->admin/tool/mobile/launch.php", $params);
|
||||
|
||||
echo $OUTPUT->header();
|
||||
if ($confirmed) {
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -37,6 +37,20 @@ function Tour(config) {
|
||||
*/
|
||||
Tour.prototype.tourName;
|
||||
|
||||
/**
|
||||
* The name of the tour storage key.
|
||||
*
|
||||
* @property {String} storageKey
|
||||
*/
|
||||
Tour.prototype.storageKey;
|
||||
|
||||
/**
|
||||
* The session storage object
|
||||
*
|
||||
* @property {Storage} storage
|
||||
*/
|
||||
Tour.prototype.storage;
|
||||
|
||||
/**
|
||||
* The original configuration as passed into the constructor.
|
||||
*
|
||||
@@ -120,6 +134,14 @@ Tour.prototype.init = function (config) {
|
||||
// Apply configuration.
|
||||
this.configure.apply(this, arguments);
|
||||
|
||||
try {
|
||||
this.storage = window.sessionStorage;
|
||||
this.storageKey = 'tourstate_' + this.tourName;
|
||||
} catch (e) {
|
||||
this.storage = false;
|
||||
this.storageKey = '';
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -280,6 +302,15 @@ Tour.prototype.getCurrentStepNumber = function () {
|
||||
*/
|
||||
Tour.prototype.setCurrentStepNumber = function (stepNumber) {
|
||||
this.currentStepNumber = stepNumber;
|
||||
if (this.storage) {
|
||||
try {
|
||||
this.storage.setItem(this.storageKey, stepNumber);
|
||||
} catch (e) {
|
||||
if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {
|
||||
this.storage.removeItem(this.storageKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -957,6 +988,16 @@ Tour.prototype.handleKeyDown = function (e) {
|
||||
* @chainable
|
||||
*/
|
||||
Tour.prototype.startTour = function (startAt) {
|
||||
if (this.storage && typeof startAt === 'undefined') {
|
||||
var storageStartValue = this.storage.getItem(this.storageKey);
|
||||
if (storageStartValue) {
|
||||
var storageStartAt = parseInt(storageStartValue, 10);
|
||||
if (storageStartAt <= this.steps.length) {
|
||||
startAt = storageStartAt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof startAt === 'undefined') {
|
||||
startAt = this.getCurrentStepNumber();
|
||||
}
|
||||
|
||||
@@ -76,15 +76,22 @@ EOF;
|
||||
/**
|
||||
* Fetch all enabled tours matching the specified target.
|
||||
*
|
||||
* @param string $targetmatch The URL to match.
|
||||
* @param moodle_url $targetmatch The URL to match.
|
||||
*/
|
||||
public static function get_matching_tourdata($targetmatch) {
|
||||
public static function get_matching_tourdata(\moodle_url $targetmatch) {
|
||||
$tours = self::get_enabled_tourdata();
|
||||
|
||||
return array_filter($tours, function($tour) use ($targetmatch) {
|
||||
// Attempt to determine whether this is the front page.
|
||||
// This is a special case because the frontpage uses a shortened page path making it difficult to detect exactly.
|
||||
$isfrontpage = $targetmatch->compare(new \moodle_url('/'), URL_MATCH_BASE);
|
||||
$target = $targetmatch->out_as_local_url();
|
||||
return array_filter($tours, function($tour) use ($isfrontpage, $target) {
|
||||
if ($isfrontpage && $tour->pathmatch === 'FRONTPAGE') {
|
||||
return true;
|
||||
}
|
||||
$pattern = preg_quote($tour->pathmatch, '@');
|
||||
$pattern = str_replace('%', '.*', $pattern);
|
||||
return !!preg_match("@{$pattern}@", $targetmatch);
|
||||
return !!preg_match("@{$pattern}@", $target);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -559,7 +559,7 @@ class manager {
|
||||
public static function get_matching_tours(\moodle_url $pageurl) {
|
||||
global $PAGE;
|
||||
|
||||
$tours = cache::get_matching_tourdata($pageurl->out_as_local_url());
|
||||
$tours = cache::get_matching_tourdata($pageurl);
|
||||
|
||||
foreach ($tours as $record) {
|
||||
$tour = tour::load_from_record($record);
|
||||
|
||||
@@ -608,6 +608,8 @@ class tour {
|
||||
* This is used in the session cookie to determine whether the user has seen this tour before.
|
||||
*/
|
||||
public function get_tour_key() {
|
||||
global $USER;
|
||||
|
||||
$tourtime = $this->get_config('majorupdatetime', null);
|
||||
|
||||
if ($tourtime === null) {
|
||||
@@ -622,7 +624,7 @@ class tour {
|
||||
$tourtime = max($tourtime, $userresetdate);
|
||||
}
|
||||
|
||||
return sprintf('tool_usertours_%d_%s', $this->get_id(), $tourtime);
|
||||
return sprintf('tool_usertours_%d_%d_%s', $USER->id, $this->get_id(), $tourtime);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -79,7 +79,10 @@ Some example values include:
|
||||
* /my/% - to match the Dashboard
|
||||
* /course/view.php?id=2 - to match a specific course
|
||||
* /mod/forum/view.php% - to match the forum discussion list
|
||||
* /user/profile.php% - to match the user profile page';
|
||||
* /user/profile.php% - to match the user profile page
|
||||
|
||||
If you wish to display a tour on the Site Home page, you can use the value: "FRONTPAGE".
|
||||
';
|
||||
$string['placement'] = 'Placement';
|
||||
$string['pluginname'] = 'User tours';
|
||||
$string['resettouronpage'] = 'Reset user tour on this page';
|
||||
|
||||
@@ -150,6 +150,14 @@ class cache_testcase extends advanced_testcase {
|
||||
'name' => 'my_glob_2',
|
||||
'pathmatch' => '/my/%'
|
||||
],
|
||||
(object) [
|
||||
'name' => 'frontpage_only',
|
||||
'pathmatch' => 'FRONTPAGE'
|
||||
],
|
||||
(object) [
|
||||
'name' => 'frontpage_match',
|
||||
'pathmatch' => '/?%'
|
||||
],
|
||||
];
|
||||
|
||||
return [
|
||||
@@ -163,6 +171,16 @@ class cache_testcase extends advanced_testcase {
|
||||
'/my/view.php',
|
||||
['my_exact_1', 'my_glob_1', 'my_glob_2'],
|
||||
],
|
||||
'Special constant FRONTPAGE must match front page only' => [
|
||||
$tourconfigs,
|
||||
'/',
|
||||
['frontpage_only'],
|
||||
],
|
||||
'Standard frontpage URL matches both the special constant, and a correctly formed pathmatch' => [
|
||||
$tourconfigs,
|
||||
'/?redirect=0',
|
||||
['frontpage_only', 'frontpage_match'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -181,7 +199,7 @@ class cache_testcase extends advanced_testcase {
|
||||
$this->helper_create_step((object) ['tourid' => $tour->get_id()]);
|
||||
}
|
||||
|
||||
$matches = \tool_usertours\cache::get_matching_tourdata((new moodle_url($targetmatch))->out_as_local_url());
|
||||
$matches = \tool_usertours\cache::get_matching_tourdata(new moodle_url($targetmatch));
|
||||
$this->assertCount(count($expected), $matches);
|
||||
|
||||
for ($i = 0; $i < count($matches); $i++) {
|
||||
|
||||
@@ -729,7 +729,7 @@ class tour_testcase extends advanced_testcase {
|
||||
$this->greaterThanOrEqual($time),
|
||||
true,
|
||||
null,
|
||||
sprintf('tool_usertours_%d_%s', $id, $time),
|
||||
sprintf('tool_usertours_\d_%d_%s', $id, $time),
|
||||
],
|
||||
|
||||
'Initial tour time, no user pref' => [
|
||||
@@ -738,7 +738,7 @@ class tour_testcase extends advanced_testcase {
|
||||
null,
|
||||
false,
|
||||
null,
|
||||
sprintf('tool_usertours_%d_%s', $id, $time),
|
||||
sprintf('tool_usertours_\d_%d_%s', $id, $time),
|
||||
],
|
||||
'Initial tour time, with user reset lower' => [
|
||||
$id,
|
||||
@@ -746,7 +746,7 @@ class tour_testcase extends advanced_testcase {
|
||||
null,
|
||||
false,
|
||||
$time - DAYSECS,
|
||||
sprintf('tool_usertours_%d_%s', $id, $time),
|
||||
sprintf('tool_usertours_\d_%d_%s', $id, $time),
|
||||
],
|
||||
'Initial tour time, with user reset higher' => [
|
||||
$id,
|
||||
@@ -754,7 +754,7 @@ class tour_testcase extends advanced_testcase {
|
||||
null,
|
||||
false,
|
||||
$time + DAYSECS,
|
||||
sprintf('tool_usertours_%d_%s', $id, $time + DAYSECS),
|
||||
sprintf('tool_usertours_\d_%d_%s', $id, $time + DAYSECS),
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -823,8 +823,8 @@ class tour_testcase extends advanced_testcase {
|
||||
set_user_preference(\tool_usertours\tour::TOUR_REQUESTED_BY_USER . $id, $userpref);
|
||||
}
|
||||
|
||||
$this->assertEquals(
|
||||
$expectation,
|
||||
$this->assertRegExp(
|
||||
'/' . $expectation . '/',
|
||||
$tour->get_tour_key()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<location>amd/src/tour.js</location>
|
||||
<name>Flexitour</name>
|
||||
<license>GPLv3</license>
|
||||
<version>0.9.9</version>
|
||||
<version>0.9.10</version>
|
||||
<licenseversion>3</licenseversion>
|
||||
</library>
|
||||
<library>
|
||||
|
||||
@@ -203,7 +203,8 @@ class auth_email_external extends external_api {
|
||||
)
|
||||
), 'User custom fields (also known as user profile fields)', VALUE_DEFAULT, array()
|
||||
),
|
||||
'redirect' => new external_value(PARAM_URL, 'Redirect the user to this url after confirmation.', VALUE_DEFAULT, ''),
|
||||
'redirect' => new external_value(PARAM_LOCALURL, 'Redirect the user to this site url after confirmation.',
|
||||
VALUE_DEFAULT, ''),
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -221,7 +222,7 @@ class auth_email_external extends external_api {
|
||||
* @param string $recaptchachallengehash recaptcha challenge hash
|
||||
* @param string $recaptcharesponse recaptcha response
|
||||
* @param array $customprofilefields user custom fields (also known as user profile fields)
|
||||
* @param string $redirect Url to redirect the user after confirmation
|
||||
* @param string $redirect Site url to redirect the user after confirmation
|
||||
* @return array settings and possible warnings
|
||||
* @since Moodle 3.2
|
||||
* @throws moodle_exception
|
||||
|
||||
@@ -61,18 +61,7 @@ class behat_auth extends behat_base {
|
||||
* @Given /^I log out$/
|
||||
*/
|
||||
public function i_log_out() {
|
||||
// There is no longer any need to worry about whether the navigation
|
||||
// bar needs to be expanded; user_menu now lives outside the
|
||||
// hamburger.
|
||||
|
||||
// However, the user menu *always* needs to be expanded. if running JS.
|
||||
if ($this->running_javascript()) {
|
||||
$xpath = "//div[@class='usermenu']//a[contains(concat(' ', @class, ' '), ' toggle-display ')]";
|
||||
|
||||
$this->execute('behat_general::i_click_on', array($xpath, "xpath_element"));
|
||||
}
|
||||
|
||||
// No need to check for exceptions as it will checked after this step execution.
|
||||
$this->execute('behat_general::click_link', get_string('logout'));
|
||||
// Click on logout link in footer, as it's much faster.
|
||||
$this->execute('behat_general::i_click_on_in_the', array(get_string('logout'), 'link', '#page-footer', "css_element"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4331,6 +4331,14 @@ class restore_create_categories_and_questions extends restore_structure_step {
|
||||
}
|
||||
$data->contextid = $mapping->parentitemid;
|
||||
|
||||
// Before 3.1, the 'stamp' field could be erroneously duplicated.
|
||||
// From 3.1 onwards, there's a unique index of (contextid, stamp).
|
||||
// If we encounter a duplicate in an old restore file, just generate a new stamp.
|
||||
// This is the same as what happens during an upgrade to 3.1+ anyway.
|
||||
if ($DB->record_exists('question_categories', ['stamp' => $data->stamp, 'contextid' => $data->contextid])) {
|
||||
$data->stamp = make_unique_id_code();
|
||||
}
|
||||
|
||||
// Let's create the question_category and save mapping
|
||||
$newitemid = $DB->insert_record('question_categories', $data);
|
||||
$this->set_mapping('question_category', $oldid, $newitemid);
|
||||
|
||||
@@ -628,7 +628,9 @@ abstract class backup_controller_dbops extends backup_dbops {
|
||||
$locked = $uselocks && (get_config('backup', $config.'_locked') == true);
|
||||
if ($plan->setting_exists($settingname)) {
|
||||
$setting = $plan->get_setting($settingname);
|
||||
if ($setting->get_value() != $value || 1==1) {
|
||||
// We can only update the setting if it isn't already locked by config or permission.
|
||||
if ($setting->get_status() !== base_setting::LOCKED_BY_CONFIG
|
||||
&& $setting->get_status() !== base_setting::LOCKED_BY_PERMISSION) {
|
||||
$setting->set_value($value);
|
||||
if ($locked) {
|
||||
$setting->set_status(base_setting::LOCKED_BY_CONFIG);
|
||||
|
||||
@@ -65,14 +65,6 @@ class block_course_summary extends block_base {
|
||||
$context = context_course::instance($this->page->course->id);
|
||||
$this->page->course->summary = file_rewrite_pluginfile_urls($this->page->course->summary, 'pluginfile.php', $context->id, 'course', 'summary', NULL);
|
||||
$this->content->text = format_text($this->page->course->summary, $this->page->course->summaryformat, $options);
|
||||
if ($this->page->user_is_editing()) {
|
||||
if($this->page->course->id == SITEID) {
|
||||
$editpage = $CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=frontpagesettings';
|
||||
} else {
|
||||
$editpage = $CFG->wwwroot.'/course/edit.php?id='.$this->page->course->id;
|
||||
}
|
||||
$this->content->text .= "<div class=\"editbutton\"><a href=\"$editpage\"><img src=\"" . $OUTPUT->pix_url('t/edit') . "\" alt=\"".get_string('edit')."\" /></a></div>";
|
||||
}
|
||||
$this->content->footer = '';
|
||||
|
||||
return $this->content;
|
||||
|
||||
@@ -29,15 +29,6 @@ Feature: Course summary block used in a course
|
||||
And I should see "Course summary" in the "Course summary" "block"
|
||||
And I should see "Proved the course summary block works!" in the "Course summary" "block"
|
||||
|
||||
Scenario: Teacher can see an edit icon when edit mode is on and follow it to the course edit page
|
||||
When I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I turn editing mode on
|
||||
Then I should see "Proved the course summary block works!" in the "Course summary" "block"
|
||||
And I should see "Course summary" in the "Course summary" "block"
|
||||
And I click on ".editbutton a" "css_element" in the "Course summary" "block"
|
||||
Then I should see "Edit course settings" in the "h2" "css_element"
|
||||
|
||||
Scenario: Teacher can not see edit icon when edit mode is off
|
||||
When I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
|
||||
@@ -22,15 +22,6 @@ Feature: Course summary block used on the frontpage
|
||||
And I should not see "Course summary" in the "Course/site summary" "block"
|
||||
And I should see "Proved the summary block works!" in the "Course/site summary" "block"
|
||||
|
||||
Scenario: Admin can see an edit icon when edit mode is on and follow it to the front page settings
|
||||
When I log in as "admin"
|
||||
And I am on site homepage
|
||||
And I follow "Turn editing on"
|
||||
Then I should see "Proved the summary block works!" in the "Course/site summary" "block"
|
||||
And I should not see "Course summary" in the "Course/site summary" "block"
|
||||
And I click on ".editbutton a" "css_element" in the "Course/site summary" "block"
|
||||
Then I should see "Front page settings" in the "h2" "css_element"
|
||||
|
||||
Scenario: Admin can not see edit icon when edit mode is off
|
||||
When I log in as "admin"
|
||||
And I am on site homepage
|
||||
|
||||
@@ -124,11 +124,12 @@ class behat_completion extends behat_base {
|
||||
} else {
|
||||
$imgalttext = get_string("completion-alt-auto-y", 'core_completion', $activityname);
|
||||
}
|
||||
$csselementforactivitytype = "li.modtype_".strtolower($activitytype);
|
||||
$activityxpath = "//li[contains(concat(' ', @class, ' '), ' modtype_" . strtolower($activitytype) . " ')]";
|
||||
$activityxpath .= "[descendant::*[contains(text(), '" . $activityname . "')]]";
|
||||
|
||||
$xpathtocheck = "//img[contains(@alt, '$imgalttext')]";
|
||||
$this->execute("behat_general::should_exist_in_the",
|
||||
array($xpathtocheck, "xpath_element", $csselementforactivitytype, "css_element")
|
||||
array($xpathtocheck, "xpath_element", $activityxpath, "xpath_element")
|
||||
);
|
||||
|
||||
}
|
||||
@@ -144,12 +145,12 @@ class behat_completion extends behat_base {
|
||||
} else {
|
||||
$imgalttext = get_string("completion-alt-auto-n", 'core_completion', $activityname);
|
||||
}
|
||||
$csselementforactivitytype = "li.modtype_".strtolower($activitytype);
|
||||
$activityxpath = "//li[contains(concat(' ', @class, ' '), ' modtype_" . strtolower($activitytype) . " ')]";
|
||||
$activityxpath .= "[descendant::*[contains(text(), '" . $activityname . "')]]";
|
||||
|
||||
$xpathtocheck = "//img[contains(@alt, '$imgalttext')]";
|
||||
$this->execute("behat_general::should_exist_in_the",
|
||||
array($xpathtocheck, "xpath_element", $csselementforactivitytype, "css_element")
|
||||
array($xpathtocheck, "xpath_element", $activityxpath, "xpath_element")
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+15
-5
@@ -217,11 +217,6 @@ class course_edit_form extends moodleform {
|
||||
$mform->addElement('select', 'calendartype', get_string('forcecalendartype', 'calendar'), $calendars);
|
||||
}
|
||||
|
||||
$options = range(0, 10);
|
||||
$mform->addElement('select', 'newsitems', get_string('newsitemsnumber'), $options);
|
||||
$mform->addHelpButton('newsitems', 'newsitemsnumber');
|
||||
$mform->setDefault('newsitems', $courseconfig->newsitems);
|
||||
|
||||
$mform->addElement('selectyesno', 'showgrades', get_string('showgrades'));
|
||||
$mform->addHelpButton('showgrades', 'showgrades');
|
||||
$mform->setDefault('showgrades', $courseconfig->showgrades);
|
||||
@@ -372,6 +367,21 @@ class course_edit_form extends moodleform {
|
||||
$mform->insertElementBefore($mform->removeElement($elements[$i]->getName(), false),
|
||||
'addcourseformatoptionshere');
|
||||
}
|
||||
|
||||
if ($courseformat->supports_news()) {
|
||||
// Show the news items select field if the course format supports news.
|
||||
$options = range(0, 10);
|
||||
$newsitems = $mform->createElement('select', 'newsitems', get_string('newsitemsnumber'), $options);
|
||||
$mform->insertElementBefore($newsitems, 'showgrades');
|
||||
$courseconfig = get_config('moodlecourse');
|
||||
$mform->setDefault('newsitems', $courseconfig->newsitems);
|
||||
$mform->addHelpButton('newsitems', 'newsitemsnumber');
|
||||
} else {
|
||||
// Otherwise, create a hidden newsitems element and set its value to 0.
|
||||
$newsitems = $mform->addElement('hidden', 'newsitems', 0);
|
||||
$mform->setType('newsitems', PARAM_INT);
|
||||
$newsitems->setValue(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1139,6 +1139,26 @@ abstract class format_base {
|
||||
return $startdate + $courseduration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the course format supports the creation of the Announcements forum.
|
||||
*
|
||||
* For course format plugin developers, please override this to return true if you want the Announcements forum
|
||||
* to be created upon course creation.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supports_news() {
|
||||
// For backwards compatibility, check if default blocks include the news_items block.
|
||||
$defaultblocks = $this->get_default_blocks();
|
||||
foreach ($defaultblocks as $blocks) {
|
||||
if (in_array('news_items', $blocks)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Return false by default.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the start date value from the course settings page form.
|
||||
*
|
||||
|
||||
@@ -401,6 +401,15 @@ class format_topics extends format_base {
|
||||
}
|
||||
return parent::inplace_editable_render_section_name($section, $linkifneeded, $editable, $edithint, $editlabel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the course format supports the creation of a news forum.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supports_news() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,9 @@ Overview of this plugin type at http://docs.moodle.org/dev/Course_formats
|
||||
* Course formats can overwrite get_default_course_enddate function to set the default course end date for new courses.
|
||||
format_base::get_default_course_enddate uses the new "Course duration" site setting to calculate the default course end date
|
||||
from the default course start date.
|
||||
* New method format_base::supports_news() which is used to determine whether an Announcements forum will be automatically created on
|
||||
course creation. For course format plugin developers, please override format_base::supports_news() to return true if you want the
|
||||
Announcements forum to be created upon course creation and remove the block names defined in format_base::get_default_blocks().
|
||||
|
||||
=== 3.1 ===
|
||||
* Course format may use the inplace_editable template to allow quick editing of section names, see
|
||||
|
||||
@@ -488,6 +488,15 @@ class format_weeks extends format_base {
|
||||
$dates = $this->get_section_dates(intval($numsections), $startdate);
|
||||
return $dates->end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the course format supports the creation of a news forum.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supports_news() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-1
@@ -3935,7 +3935,7 @@ function course_check_module_updates_since($cm, $from, $fileareas = array(), $fi
|
||||
}
|
||||
if (!empty($fileareas) and (empty($filter) or in_array('fileareas', $filter))) {
|
||||
$fs = get_file_storage();
|
||||
$files = $fs->get_area_files($context->id, $component, $fileareas, false, "filearea, timemodified DESC", true, $from);
|
||||
$files = $fs->get_area_files($context->id, $component, $fileareas, false, "filearea, timemodified DESC", false, $from);
|
||||
foreach ($fileareas as $filearea) {
|
||||
$updates->{$filearea . 'files'} = (object) array('updated' => false);
|
||||
}
|
||||
@@ -3993,6 +3993,7 @@ function course_check_module_updates_since($cm, $from, $fileareas = array(), $fi
|
||||
// Check comments.
|
||||
if (plugin_supports('mod', $cm->modname, FEATURE_COMMENT) and (empty($filter) or in_array('comments', $filter))) {
|
||||
$updates->comments = (object) array('updated' => false);
|
||||
require_once($CFG->dirroot . '/comment/lib.php');
|
||||
require_once($CFG->dirroot . '/comment/locallib.php');
|
||||
$manager = new comment_manager();
|
||||
$comments = $manager->get_component_comments_since($course, $context, $component, $from, $cm);
|
||||
|
||||
+2
-5
@@ -1506,14 +1506,11 @@ class core_course_renderer extends plugin_renderer_base {
|
||||
if ($coursecat->get_children_count()) {
|
||||
$classes = array(
|
||||
'collapseexpand',
|
||||
'collapse-all',
|
||||
);
|
||||
if ($chelper->get_subcat_depth() == 1) {
|
||||
$classes[] = 'disabled';
|
||||
}
|
||||
|
||||
// Only show the collapse/expand if there are children to expand.
|
||||
$content .= html_writer::start_tag('div', array('class' => 'collapsible-actions'));
|
||||
$content .= html_writer::link('#', get_string('collapseall'),
|
||||
$content .= html_writer::link('#', get_string('expandall'),
|
||||
array('class' => implode(' ', $classes)));
|
||||
$content .= html_writer::end_tag('div');
|
||||
$this->page->requires->strings_for_js(array('collapseall', 'expandall'), 'moodle');
|
||||
|
||||
@@ -101,4 +101,66 @@ class core_course_courseformat_testcase extends advanced_testcase {
|
||||
$this->assertFalse($modinfoteacher->get_cm($assign1->cmid)->available);
|
||||
$this->assertTrue($modinfoteacher->get_cm($assign1->cmid)->uservisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for supports_news() with a course format plugin that doesn't define 'news_items' in default blocks.
|
||||
*/
|
||||
public function test_supports_news() {
|
||||
$this->resetAfterTest();
|
||||
$format = course_get_format((object)['format' => 'testformat']);
|
||||
$this->assertFalse($format->supports_news());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for supports_news() for old course format plugins that defines 'news_items' in default blocks.
|
||||
*/
|
||||
public function test_supports_news_legacy() {
|
||||
$this->resetAfterTest();
|
||||
$format = course_get_format((object)['format' => 'testlegacy']);
|
||||
$this->assertTrue($format->supports_news());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class format_testformat.
|
||||
*
|
||||
* A test class that simulates a course format that doesn't define 'news_items' in default blocks.
|
||||
*
|
||||
* @copyright 2016 Jun Pataleta <jun@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class format_testformat extends format_base {
|
||||
/**
|
||||
* Returns the list of blocks to be automatically added for the newly created course.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_default_blocks() {
|
||||
return [
|
||||
BLOCK_POS_RIGHT => [],
|
||||
BLOCK_POS_LEFT => []
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class format_testlegacy.
|
||||
*
|
||||
* A test class that simulates old course formats that define 'news_items' in default blocks.
|
||||
*
|
||||
* @copyright 2016 Jun Pataleta <jun@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class format_testlegacy extends format_base {
|
||||
/**
|
||||
* Returns the list of blocks to be automatically added for the newly created course.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_default_blocks() {
|
||||
return [
|
||||
BLOCK_POS_RIGHT => ['news_items'],
|
||||
BLOCK_POS_LEFT => []
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
+58
-4
@@ -25,10 +25,12 @@ var CSS = {
|
||||
HASCHILDREN: 'with_children'
|
||||
},
|
||||
SELECTORS = {
|
||||
WITHCHILDRENTREES: '.with_children',
|
||||
LOADEDTREES: '.with_children.loaded',
|
||||
CONTENTNODE: '.content',
|
||||
CATEGORYLISTENLINK: '.category .info .categoryname',
|
||||
CATEGORYSPINNERLOCATION: '.categoryname',
|
||||
CATEGORYWITHCOLLAPSEDCHILDREN: '.category.with_children.collapsed',
|
||||
CATEGORYWITHCOLLAPSEDLOADEDCHILDREN: '.category.with_children.loaded.collapsed',
|
||||
CATEGORYWITHMAXIMISEDLOADEDCHILDREN: '.category.with_children.loaded:not(.collapsed)',
|
||||
COLLAPSEEXPAND: '.collapseexpand',
|
||||
@@ -82,6 +84,58 @@ NS.setup_keyboard_listeners = function() {
|
||||
Y.one(Y.config.doc).delegate('key', this.collapse_expand_all, 'enter', SELECTORS.COLLAPSEEXPAND, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand all categories.
|
||||
*
|
||||
* @method expand_category
|
||||
* @private
|
||||
* @param {Node} categorynode The node to expand
|
||||
*/
|
||||
NS.expand_category = function(categorynode) {
|
||||
// Load the actual dependencies now that we've been called.
|
||||
Y.use('io-base', 'json-parse', 'moodle-core-notification', 'anim-node-plugin', function() {
|
||||
// Overload the expand_category with the _expand_category function to ensure that
|
||||
// this function isn't called in the future, and call it for the first time.
|
||||
NS.expand_category = NS._expand_category;
|
||||
NS.expand_category(categorynode);
|
||||
});
|
||||
};
|
||||
|
||||
NS._expand_category = function(categorynode) {
|
||||
var categoryid,
|
||||
depth;
|
||||
|
||||
if (!categorynode.hasClass(CSS.HASCHILDREN)) {
|
||||
// Nothing to do here - this category has no children.
|
||||
return;
|
||||
}
|
||||
|
||||
if (categorynode.hasClass(CSS.LOADED)) {
|
||||
// We've already loaded this content so we just need to toggle the view of it.
|
||||
this.run_expansion(categorynode);
|
||||
return;
|
||||
}
|
||||
|
||||
// We use Data attributes to store the category.
|
||||
categoryid = categorynode.getData('categoryid');
|
||||
depth = categorynode.getData('depth');
|
||||
if (typeof categoryid === "undefined" || typeof depth === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
this._toggle_generic_expansion({
|
||||
parentnode: categorynode,
|
||||
childnode: categorynode.one(SELECTORS.CONTENTNODE),
|
||||
spinnerhandle: SELECTORS.CATEGORYSPINNERLOCATION,
|
||||
data: {
|
||||
categoryid: categoryid,
|
||||
depth: depth,
|
||||
showcourses: categorynode.getData('showcourses'),
|
||||
type: TYPE_CATEGORY
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle the animation of the clicked category node.
|
||||
*
|
||||
@@ -310,12 +364,12 @@ NS._collapse_expand_all = function(e) {
|
||||
NS.expand_all = function(ancestor) {
|
||||
var finalexpansions = [];
|
||||
|
||||
ancestor.all(SELECTORS.CATEGORYWITHCOLLAPSEDLOADEDCHILDREN)
|
||||
ancestor.all(SELECTORS.CATEGORYWITHCOLLAPSEDCHILDREN)
|
||||
.each(function(c) {
|
||||
if (c.ancestor(SELECTORS.CATEGORYWITHCOLLAPSEDLOADEDCHILDREN)) {
|
||||
if (c.ancestor(SELECTORS.CATEGORYWITHCOLLAPSEDCHILDREN)) {
|
||||
// Expand the hidden children first without animation.
|
||||
c.removeClass(CSS.SECTIONCOLLAPSED);
|
||||
c.all(SELECTORS.LOADEDTREES).removeClass(CSS.SECTIONCOLLAPSED);
|
||||
c.all(SELECTORS.WITHCHILDRENTREES).removeClass(CSS.SECTIONCOLLAPSED);
|
||||
} else {
|
||||
finalexpansions.push(c);
|
||||
}
|
||||
@@ -323,7 +377,7 @@ NS.expand_all = function(ancestor) {
|
||||
|
||||
// Run the final expansion with animation on the visible items.
|
||||
Y.all(finalexpansions).each(function(c) {
|
||||
this.run_expansion(c);
|
||||
this.expand_category(c);
|
||||
}, this);
|
||||
|
||||
};
|
||||
|
||||
+2
-1
File diff suppressed because one or more lines are too long
+58
-4
@@ -25,10 +25,12 @@ var CSS = {
|
||||
HASCHILDREN: 'with_children'
|
||||
},
|
||||
SELECTORS = {
|
||||
WITHCHILDRENTREES: '.with_children',
|
||||
LOADEDTREES: '.with_children.loaded',
|
||||
CONTENTNODE: '.content',
|
||||
CATEGORYLISTENLINK: '.category .info .categoryname',
|
||||
CATEGORYSPINNERLOCATION: '.categoryname',
|
||||
CATEGORYWITHCOLLAPSEDCHILDREN: '.category.with_children.collapsed',
|
||||
CATEGORYWITHCOLLAPSEDLOADEDCHILDREN: '.category.with_children.loaded.collapsed',
|
||||
CATEGORYWITHMAXIMISEDLOADEDCHILDREN: '.category.with_children.loaded:not(.collapsed)',
|
||||
COLLAPSEEXPAND: '.collapseexpand',
|
||||
@@ -81,6 +83,58 @@ NS.setup_keyboard_listeners = function() {
|
||||
Y.one(Y.config.doc).delegate('key', this.collapse_expand_all, 'enter', SELECTORS.COLLAPSEEXPAND, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand all categories.
|
||||
*
|
||||
* @method expand_category
|
||||
* @private
|
||||
* @param {Node} categorynode The node to expand
|
||||
*/
|
||||
NS.expand_category = function(categorynode) {
|
||||
// Load the actual dependencies now that we've been called.
|
||||
Y.use('io-base', 'json-parse', 'moodle-core-notification', 'anim-node-plugin', function() {
|
||||
// Overload the expand_category with the _expand_category function to ensure that
|
||||
// this function isn't called in the future, and call it for the first time.
|
||||
NS.expand_category = NS._expand_category;
|
||||
NS.expand_category(categorynode);
|
||||
});
|
||||
};
|
||||
|
||||
NS._expand_category = function(categorynode) {
|
||||
var categoryid,
|
||||
depth;
|
||||
|
||||
if (!categorynode.hasClass(CSS.HASCHILDREN)) {
|
||||
// Nothing to do here - this category has no children.
|
||||
return;
|
||||
}
|
||||
|
||||
if (categorynode.hasClass(CSS.LOADED)) {
|
||||
// We've already loaded this content so we just need to toggle the view of it.
|
||||
this.run_expansion(categorynode);
|
||||
return;
|
||||
}
|
||||
|
||||
// We use Data attributes to store the category.
|
||||
categoryid = categorynode.getData('categoryid');
|
||||
depth = categorynode.getData('depth');
|
||||
if (typeof categoryid === "undefined" || typeof depth === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
this._toggle_generic_expansion({
|
||||
parentnode: categorynode,
|
||||
childnode: categorynode.one(SELECTORS.CONTENTNODE),
|
||||
spinnerhandle: SELECTORS.CATEGORYSPINNERLOCATION,
|
||||
data: {
|
||||
categoryid: categoryid,
|
||||
depth: depth,
|
||||
showcourses: categorynode.getData('showcourses'),
|
||||
type: TYPE_CATEGORY
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle the animation of the clicked category node.
|
||||
*
|
||||
@@ -309,12 +363,12 @@ NS._collapse_expand_all = function(e) {
|
||||
NS.expand_all = function(ancestor) {
|
||||
var finalexpansions = [];
|
||||
|
||||
ancestor.all(SELECTORS.CATEGORYWITHCOLLAPSEDLOADEDCHILDREN)
|
||||
ancestor.all(SELECTORS.CATEGORYWITHCOLLAPSEDCHILDREN)
|
||||
.each(function(c) {
|
||||
if (c.ancestor(SELECTORS.CATEGORYWITHCOLLAPSEDLOADEDCHILDREN)) {
|
||||
if (c.ancestor(SELECTORS.CATEGORYWITHCOLLAPSEDCHILDREN)) {
|
||||
// Expand the hidden children first without animation.
|
||||
c.removeClass(CSS.SECTIONCOLLAPSED);
|
||||
c.all(SELECTORS.LOADEDTREES).removeClass(CSS.SECTIONCOLLAPSED);
|
||||
c.all(SELECTORS.WITHCHILDRENTREES).removeClass(CSS.SECTIONCOLLAPSED);
|
||||
} else {
|
||||
finalexpansions.push(c);
|
||||
}
|
||||
@@ -322,7 +376,7 @@ NS.expand_all = function(ancestor) {
|
||||
|
||||
// Run the final expansion with animation on the visible items.
|
||||
Y.all(finalexpansions).each(function(c) {
|
||||
this.run_expansion(c);
|
||||
this.expand_category(c);
|
||||
}, this);
|
||||
|
||||
};
|
||||
|
||||
+58
-4
@@ -23,10 +23,12 @@ var CSS = {
|
||||
HASCHILDREN: 'with_children'
|
||||
},
|
||||
SELECTORS = {
|
||||
WITHCHILDRENTREES: '.with_children',
|
||||
LOADEDTREES: '.with_children.loaded',
|
||||
CONTENTNODE: '.content',
|
||||
CATEGORYLISTENLINK: '.category .info .categoryname',
|
||||
CATEGORYSPINNERLOCATION: '.categoryname',
|
||||
CATEGORYWITHCOLLAPSEDCHILDREN: '.category.with_children.collapsed',
|
||||
CATEGORYWITHCOLLAPSEDLOADEDCHILDREN: '.category.with_children.loaded.collapsed',
|
||||
CATEGORYWITHMAXIMISEDLOADEDCHILDREN: '.category.with_children.loaded:not(.collapsed)',
|
||||
COLLAPSEEXPAND: '.collapseexpand',
|
||||
@@ -80,6 +82,58 @@ NS.setup_keyboard_listeners = function() {
|
||||
Y.one(Y.config.doc).delegate('key', this.collapse_expand_all, 'enter', SELECTORS.COLLAPSEEXPAND, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand all categories.
|
||||
*
|
||||
* @method expand_category
|
||||
* @private
|
||||
* @param {Node} categorynode The node to expand
|
||||
*/
|
||||
NS.expand_category = function(categorynode) {
|
||||
// Load the actual dependencies now that we've been called.
|
||||
Y.use('io-base', 'json-parse', 'moodle-core-notification', 'anim-node-plugin', function() {
|
||||
// Overload the expand_category with the _expand_category function to ensure that
|
||||
// this function isn't called in the future, and call it for the first time.
|
||||
NS.expand_category = NS._expand_category;
|
||||
NS.expand_category(categorynode);
|
||||
});
|
||||
};
|
||||
|
||||
NS._expand_category = function(categorynode) {
|
||||
var categoryid,
|
||||
depth;
|
||||
|
||||
if (!categorynode.hasClass(CSS.HASCHILDREN)) {
|
||||
// Nothing to do here - this category has no children.
|
||||
return;
|
||||
}
|
||||
|
||||
if (categorynode.hasClass(CSS.LOADED)) {
|
||||
// We've already loaded this content so we just need to toggle the view of it.
|
||||
this.run_expansion(categorynode);
|
||||
return;
|
||||
}
|
||||
|
||||
// We use Data attributes to store the category.
|
||||
categoryid = categorynode.getData('categoryid');
|
||||
depth = categorynode.getData('depth');
|
||||
if (typeof categoryid === "undefined" || typeof depth === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
this._toggle_generic_expansion({
|
||||
parentnode: categorynode,
|
||||
childnode: categorynode.one(SELECTORS.CONTENTNODE),
|
||||
spinnerhandle: SELECTORS.CATEGORYSPINNERLOCATION,
|
||||
data: {
|
||||
categoryid: categoryid,
|
||||
depth: depth,
|
||||
showcourses: categorynode.getData('showcourses'),
|
||||
type: TYPE_CATEGORY
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle the animation of the clicked category node.
|
||||
*
|
||||
@@ -308,12 +362,12 @@ NS._collapse_expand_all = function(e) {
|
||||
NS.expand_all = function(ancestor) {
|
||||
var finalexpansions = [];
|
||||
|
||||
ancestor.all(SELECTORS.CATEGORYWITHCOLLAPSEDLOADEDCHILDREN)
|
||||
ancestor.all(SELECTORS.CATEGORYWITHCOLLAPSEDCHILDREN)
|
||||
.each(function(c) {
|
||||
if (c.ancestor(SELECTORS.CATEGORYWITHCOLLAPSEDLOADEDCHILDREN)) {
|
||||
if (c.ancestor(SELECTORS.CATEGORYWITHCOLLAPSEDCHILDREN)) {
|
||||
// Expand the hidden children first without animation.
|
||||
c.removeClass(CSS.SECTIONCOLLAPSED);
|
||||
c.all(SELECTORS.LOADEDTREES).removeClass(CSS.SECTIONCOLLAPSED);
|
||||
c.all(SELECTORS.WITHCHILDRENTREES).removeClass(CSS.SECTIONCOLLAPSED);
|
||||
} else {
|
||||
finalexpansions.push(c);
|
||||
}
|
||||
@@ -321,7 +375,7 @@ NS.expand_all = function(ancestor) {
|
||||
|
||||
// Run the final expansion with animation on the visible items.
|
||||
Y.all(finalexpansions).each(function(c) {
|
||||
this.run_expansion(c);
|
||||
this.expand_category(c);
|
||||
}, this);
|
||||
|
||||
};
|
||||
|
||||
@@ -8,6 +8,14 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mediaplugin,
|
||||
.mediaplugin video {
|
||||
/* Make videos as wide as possible without being wider than their containers */
|
||||
width: 100vw;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.mediaplugin > div {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ class autogroup_form extends moodleform {
|
||||
}
|
||||
|
||||
$coursecontext = context_course::instance($COURSE->id);
|
||||
if ($cohorts = cohort_get_available_cohorts($coursecontext, COHORT_WITH_ENROLLED_MEMBERS_ONLY)) {
|
||||
if ($cohorts = cohort_get_available_cohorts($coursecontext, COHORT_WITH_ENROLLED_MEMBERS_ONLY, 0, 0)) {
|
||||
$options = array(0 => get_string('anycohort', 'cohort'));
|
||||
foreach ($cohorts as $c) {
|
||||
$options[$c->id] = format_string($c->name, true, context::instance_by_id($c->contextid));
|
||||
|
||||
+3
-4
@@ -170,15 +170,14 @@ $string['configcronremotepassword'] = 'This means that the cron.php script canno
|
||||
http://site.example.com/admin/cron.php?password=opensesame
|
||||
</pre>If this is left empty, no password is required.';
|
||||
$string['configcurlcache'] = 'Time-to-live for cURL cache, in seconds.';
|
||||
$string['configcustommenuitems'] = 'You can configure a custom menu here to be shown by themes. Each line consists of some menu text, a link URL (optional), a tooltip title (optional) and a language code or comma-separated list of codes (optional, for displaying the line to users of the specified language only), separated by pipe characters. You can specify a structure using hyphens, and dividers can be used by adding a line of one or more # characters where desired. For example:
|
||||
$string['configcustommenuitems'] = 'You can configure a custom menu here to be shown by themes. Each line consists of some menu text, a link URL (optional), a tooltip title (optional) and a language code or comma-separated list of codes (optional, for displaying the line to users of the specified language only), separated by pipe characters. Lines starting with a hyphen will appear as menu items in the previous top level menu, and dividers can be used by adding a line of one or more # characters where desired. For example:
|
||||
<pre>
|
||||
Moodle community|https://moodle.org
|
||||
-Moodle free support|https://moodle.org/support
|
||||
-Moodle Docs|http://docs.moodle.org|Moodle Docs
|
||||
-German Moodle Docs|http://docs.moodle.org/de|Documentation in German|de
|
||||
-###
|
||||
-Moodle development|https://moodle.org/development
|
||||
--Moodle Docs|http://docs.moodle.org|Moodle Docs
|
||||
--German Moodle Docs|http://docs.moodle.org/de|Documentation in German|de
|
||||
#####
|
||||
Moodle.com|http://moodle.com/
|
||||
</pre>';
|
||||
$string['configcustomusermenuitems'] = 'You can configure the contents of the user menu (with the exception of the log out link, which is automatically added). Each line is separated by | characters and consists of 1) a string in "langstringname, componentname" form or as plain text, 2) a URL, and 3) an icon either as a pix icon or as a URL. Dividers can be used by adding a line of one or more # characters where desired.';
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
define(["jquery","core/yui"],function(a,b){return{Events:{FORM_FIELD_VALIDATION:"core_form-field-validation"},notifyFilterContentUpdated:function(c){c=a(c),b.use("event","moodle-core-event",function(b){a(document).trigger(M.core.event.FILTER_CONTENT_UPDATED,c);var d=new b.NodeList(c.get());b.fire(M.core.event.FILTER_CONTENT_UPDATED,{nodes:d})})},notifyEditorContentRestored:function(){b.use("event","moodle-core-event",function(b){a(document).trigger(M.core.event.EDITOR_CONTENT_RESTORED),b.fire(M.core.event.EDITOR_CONTENT_RESTORED)})}}});
|
||||
define(["jquery","core/yui"],function(a,b){return{Events:{FORM_FIELD_VALIDATION:"core_form-field-validation"},getLegacyEvents:function(){var c=a.Deferred();return b.use("event","moodle-core-event",function(){c.resolve(window.M.core.event)}),c.promise()},notifyFilterContentUpdated:function(c){c=a(c),b.use("event","moodle-core-event",function(b){a(document).trigger(M.core.event.FILTER_CONTENT_UPDATED,[c]);var d=new b.NodeList(c.get());b.fire(M.core.event.FILTER_CONTENT_UPDATED,{nodes:d})})},notifyEditorContentRestored:function(){b.use("event","moodle-core-event",function(b){a(document).trigger(M.core.event.EDITOR_CONTENT_RESTORED),b.fire(M.core.event.EDITOR_CONTENT_RESTORED)})}}});
|
||||
+15
-1
@@ -35,6 +35,20 @@ define(['jquery', 'core/yui'],
|
||||
FORM_FIELD_VALIDATION: "core_form-field-validation"
|
||||
},
|
||||
|
||||
/**
|
||||
* Load the legacy YUI module which defines events in M.core.event and return it.
|
||||
*
|
||||
* @method getLegacyEvents
|
||||
* @return {Promise}
|
||||
*/
|
||||
getLegacyEvents: function() {
|
||||
var result = $.Deferred();
|
||||
Y.use('event', 'moodle-core-event', function() {
|
||||
result.resolve(window.M.core.event);
|
||||
});
|
||||
return result.promise();
|
||||
},
|
||||
|
||||
/**
|
||||
* Trigger an event using both JQuery and YUI
|
||||
*
|
||||
@@ -45,7 +59,7 @@ define(['jquery', 'core/yui'],
|
||||
nodes = $(nodes);
|
||||
Y.use('event', 'moodle-core-event', function(Y) {
|
||||
// Trigger it the JQuery way.
|
||||
$(document).trigger(M.core.event.FILTER_CONTENT_UPDATED, nodes);
|
||||
$(document).trigger(M.core.event.FILTER_CONTENT_UPDATED, [nodes]);
|
||||
|
||||
// Create a YUI NodeList from our JQuery Object.
|
||||
var yuiNodes = new Y.NodeList(nodes.get());
|
||||
|
||||
@@ -117,6 +117,9 @@ class behat_util extends testing_util {
|
||||
// Enable web cron.
|
||||
set_config('cronclionly', 0);
|
||||
|
||||
// Set editor autosave to high value, so as to avoid unwanted ajax.
|
||||
set_config('autosavefrequency', '604800', 'editor_atto');
|
||||
|
||||
// Keeps the current version of database and dataroot.
|
||||
self::store_versions_hash();
|
||||
|
||||
|
||||
@@ -60,5 +60,10 @@ JS;
|
||||
}
|
||||
|
||||
$this->field->setValue($value);
|
||||
|
||||
// Ensure all pending JS is finished.
|
||||
if ($this->running_javascript()) {
|
||||
$this->session->wait(behat_base::TIMEOUT * 1000, behat_base::PAGE_READY_JS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +134,13 @@ function behat_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// No need to report the before_scenario warning generated to clear last error.
|
||||
// As error_clear_last is only available in php 7.0+, we trigger E_USER_WARNING
|
||||
// to clear any last error which was generated during reset in before_scenario.
|
||||
if (($errno === E_USER_WARNING) && $errstr == 'before_scenario') {
|
||||
return;
|
||||
}
|
||||
|
||||
// This error handler receives E_ALL | E_STRICT, running the behat test site the debug level is
|
||||
// set to DEVELOPER and will always include E_NOTICE,E_USER_NOTICE... as part of E_ALL, if the current
|
||||
// error_reporting() value does not include one of those levels is because it has been forced through
|
||||
@@ -175,6 +182,14 @@ function behat_shutdown_function() {
|
||||
if ($error = error_get_last()) {
|
||||
// Ignore E_WARNING, as they might come via ( @ )suppression and might lead to false failure.
|
||||
if (isset($error['type']) && !($error['type'] & E_WARNING)) {
|
||||
|
||||
// No need to report the before_scenario warning generated to clear last error.
|
||||
// As error_clear_last is only available in php 7.0+, we trigger E_USER_WARNING
|
||||
// to clear any last error which was generated during reset in before_scenario.
|
||||
if (($error['type'] & E_USER_WARNING) && $error['message'] == 'before_scenario') {
|
||||
return;
|
||||
}
|
||||
|
||||
$errors = behat_get_shutdown_process_errors();
|
||||
|
||||
$errors[] = $error;
|
||||
|
||||
@@ -5616,7 +5616,11 @@ function message_is_user_blocked($recipient, $sender = null) {
|
||||
debugging('message_is_user_blocked() is deprecated and is no longer used, please use
|
||||
\core_message\api::is_user_blocked() instead.', DEBUG_DEVELOPER);
|
||||
|
||||
return \core_message\api::is_user_blocked($recipient, $sender);
|
||||
$senderid = null;
|
||||
if ($sender !== null && isset($sender->id)) {
|
||||
$senderid = $sender->id;
|
||||
}
|
||||
return \core_message\api::is_user_blocked($recipient->id, $senderid);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1246,11 +1246,7 @@ class global_navigation extends navigation_node {
|
||||
} else {
|
||||
$this->rootnodes['courses']->isexpandable = true;
|
||||
}
|
||||
|
||||
// Load the users enrolled courses if they are viewing the My Moodle page AND the admin has not
|
||||
// set that they wish to keep the My Courses branch collapsed by default.
|
||||
$this->rootnodes['mycourses']->forceopen = true;
|
||||
$this->load_courses_enrolled();
|
||||
|
||||
$canviewcourseprofile = true;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ var require = {
|
||||
|
||||
paths: {
|
||||
jquery: '[JSURL]lib/jquery/jquery-3.1.0.min[JSEXT]',
|
||||
jqueryui: '[JSURL]lib/jquery/ui-1.11.4/jquery-ui.min[JSEXT]',
|
||||
jqueryui: '[JSURL]lib/jquery/ui-1.12.1/jquery-ui.min[JSEXT]',
|
||||
jqueryprivate: '[JSURL]lib/requirejs/jquery-private[JSEXT]'
|
||||
},
|
||||
|
||||
|
||||
@@ -103,6 +103,13 @@ class behat_hooks extends behat_base {
|
||||
*/
|
||||
protected static $runningsuite = '';
|
||||
|
||||
/**
|
||||
* Keeps track of php error generated during reset.
|
||||
*
|
||||
* @var int keep track of how many php errors were generated.
|
||||
*/
|
||||
public static $phperrorduringresetcounter = 0;
|
||||
|
||||
/**
|
||||
* Hook to capture BeforeSuite event so as to give access to moodle codebase.
|
||||
* This will try and catch any exception and exists if anything fails.
|
||||
@@ -339,7 +346,30 @@ class behat_hooks extends behat_base {
|
||||
// Reset $SESSION.
|
||||
\core\session\manager::init_empty_session();
|
||||
|
||||
// Set custom handler to try reset all data, if failed because of previous ajax.
|
||||
set_error_handler(
|
||||
function($errno, $errstr, $errfile, $errline) {
|
||||
behat_hooks::$phperrorduringresetcounter++;
|
||||
if (behat_hooks::$phperrorduringresetcounter < self::TIMEOUT) {
|
||||
sleep(1);
|
||||
behat_util::reset_all_data();
|
||||
}
|
||||
return true;
|
||||
}, -1 & ~E_NOTICE & ~E_WARNING);
|
||||
behat_util::reset_all_data();
|
||||
restore_error_handler();
|
||||
|
||||
// Trigger an error which will be ignored by behat_shutdown_function, this is hacky way to clear last error in php < 7.0.
|
||||
if (self::$phperrorduringresetcounter > 0) {
|
||||
if (function_exists('error_clear_last')) {
|
||||
error_clear_last();
|
||||
} else {
|
||||
trigger_error('before_scenario', E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the counter here, as this won't be required.
|
||||
self::$phperrorduringresetcounter = 0;
|
||||
|
||||
// Assign valid data to admin user (some generator-related code needs a valid user).
|
||||
$user = $DB->get_record('user', array('username' => 'admin'));
|
||||
@@ -381,6 +411,29 @@ class behat_hooks extends behat_base {
|
||||
$this->resize_window('medium');
|
||||
}
|
||||
|
||||
/**
|
||||
* Executed after scenario to go to a page where no JS is executed.
|
||||
* This will ensure there are no unwanted ajax calls from browser and
|
||||
* site can be reset safely.
|
||||
*
|
||||
* @param AfterScenarioScope $scope scope passed by event fired after scenario.
|
||||
* @AfterScenario
|
||||
*/
|
||||
public function after_scenario(AfterScenarioScope $scope) {
|
||||
try {
|
||||
$this->wait_for_pending_js();
|
||||
$this->getSession()->visit($this->locate_path('/README.txt'));
|
||||
$this->getSession()->reset();
|
||||
} catch (DriverException $e) {
|
||||
// Try restart session, if DriverException caught.
|
||||
try {
|
||||
$this->getSession()->restart();
|
||||
} catch (DriverException $e) {
|
||||
// Do nothing, as this will be caught while starting session in before_scenario.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for JS to complete before beginning interacting with the DOM.
|
||||
*
|
||||
|
||||
+56
-58
@@ -348,58 +348,54 @@ class api {
|
||||
* @return \stdClass
|
||||
*/
|
||||
public static function get_profile($userid, $otheruserid) {
|
||||
global $CFG, $DB;
|
||||
global $CFG, $DB, $PAGE;
|
||||
|
||||
require_once($CFG->dirroot . '/user/lib.php');
|
||||
|
||||
if ($user = \core_user::get_user($otheruserid)) {
|
||||
// Create the data we are going to pass to the renderable.
|
||||
$userfields = user_get_user_details($user, null, array('city', 'country', 'email',
|
||||
'profileimageurl', 'profileimageurlsmall', 'lastaccess'));
|
||||
if ($userfields) {
|
||||
$data = new \stdClass();
|
||||
$data->userid = $userfields['id'];
|
||||
$data->fullname = $userfields['fullname'];
|
||||
$data->city = isset($userfields['city']) ? $userfields['city'] : '';
|
||||
$data->country = isset($userfields['country']) ? $userfields['country'] : '';
|
||||
$data->email = isset($userfields['email']) ? $userfields['email'] : '';
|
||||
$data->profileimageurl = isset($userfields['profileimageurl']) ? $userfields['profileimageurl'] : '';
|
||||
if (isset($userfields['profileimageurlsmall'])) {
|
||||
$data->profileimageurlsmall = $userfields['profileimageurlsmall'];
|
||||
} else {
|
||||
$data->profileimageurlsmall = '';
|
||||
}
|
||||
if (isset($userfields['lastaccess'])) {
|
||||
$data->isonline = helper::is_online($userfields['lastaccess']);
|
||||
} else {
|
||||
$data->isonline = false;
|
||||
}
|
||||
} else {
|
||||
// Technically the access checks in user_get_user_details are correct,
|
||||
// but messaging has never obeyed them. In order to keep messaging working
|
||||
// we at least need to return a minimal user record.
|
||||
$data = new \stdClass();
|
||||
$data->userid = $otheruserid;
|
||||
$data->fullname = fullname($user);
|
||||
$data->city = '';
|
||||
$data->country = '';
|
||||
$data->email = '';
|
||||
$data->profileimageurl = '';
|
||||
$data->profileimageurlsmall = '';
|
||||
$data->isonline = false;
|
||||
}
|
||||
// Check if the contact has been blocked.
|
||||
$contact = $DB->get_record('message_contacts', array('userid' => $userid, 'contactid' => $otheruserid));
|
||||
if ($contact) {
|
||||
$data->isblocked = (bool) $contact->blocked;
|
||||
$data->iscontact = true;
|
||||
} else {
|
||||
$data->isblocked = false;
|
||||
$data->iscontact = false;
|
||||
}
|
||||
$user = \core_user::get_user($otheruserid, '*', MUST_EXIST);
|
||||
|
||||
return $data;
|
||||
// Create the data we are going to pass to the renderable.
|
||||
$data = new \stdClass();
|
||||
$data->userid = $otheruserid;
|
||||
$data->fullname = fullname($user);
|
||||
$data->city = '';
|
||||
$data->country = '';
|
||||
$data->email = '';
|
||||
$data->isonline = false;
|
||||
// Get the user picture data - messaging has always shown these to the user.
|
||||
$userpicture = new \user_picture($user);
|
||||
$userpicture->size = 1; // Size f1.
|
||||
$data->profileimageurl = $userpicture->get_url($PAGE)->out(false);
|
||||
$userpicture->size = 0; // Size f2.
|
||||
$data->profileimageurlsmall = $userpicture->get_url($PAGE)->out(false);
|
||||
|
||||
$userfields = user_get_user_details($user, null, array('city', 'country', 'email', 'lastaccess'));
|
||||
if ($userfields) {
|
||||
if (isset($userfields['city'])) {
|
||||
$data->city = $userfields['city'];
|
||||
}
|
||||
if (isset($userfields['country'])) {
|
||||
$data->country = $userfields['country'];
|
||||
}
|
||||
if (isset($userfields['email'])) {
|
||||
$data->email = $userfields['email'];
|
||||
}
|
||||
if (isset($userfields['lastaccess'])) {
|
||||
$data->isonline = helper::is_online($userfields['lastaccess']);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the contact has been blocked.
|
||||
$contact = $DB->get_record('message_contacts', array('userid' => $userid, 'contactid' => $otheruserid));
|
||||
if ($contact) {
|
||||
$data->isblocked = (bool) $contact->blocked;
|
||||
$data->iscontact = true;
|
||||
} else {
|
||||
$data->isblocked = false;
|
||||
$data->iscontact = false;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -620,8 +616,12 @@ class api {
|
||||
return false;
|
||||
}
|
||||
|
||||
$senderid = null;
|
||||
if ($sender !== null && isset($sender->id)) {
|
||||
$senderid = $sender->id;
|
||||
}
|
||||
// The recipient has specifically blocked this sender.
|
||||
if (self::is_user_blocked($recipient, $sender)) {
|
||||
if (self::is_user_blocked($recipient->id, $senderid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -667,27 +667,25 @@ class api {
|
||||
* Note: This function will always return false if the sender has the
|
||||
* readallmessages capability at the system context level.
|
||||
*
|
||||
* @param object $recipient User object.
|
||||
* @param object $sender User object.
|
||||
* @param int $recipientid User ID of the recipient.
|
||||
* @param int $senderid User ID of the sender.
|
||||
* @return bool true if $sender is blocked, false otherwise.
|
||||
*/
|
||||
public static function is_user_blocked($recipient, $sender = null) {
|
||||
public static function is_user_blocked($recipientid, $senderid = null) {
|
||||
global $USER, $DB;
|
||||
|
||||
if (is_null($sender)) {
|
||||
if (is_null($senderid)) {
|
||||
// The message is from the logged in user, unless otherwise specified.
|
||||
$sender = $USER;
|
||||
$senderid = $USER->id;
|
||||
}
|
||||
|
||||
$systemcontext = \context_system::instance();
|
||||
if (has_capability('moodle/site:readallmessages', $systemcontext, $sender)) {
|
||||
if (has_capability('moodle/site:readallmessages', $systemcontext, $senderid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($contact = $DB->get_record('message_contacts', array('userid' => $recipient->id, 'contactid' => $sender->id))) {
|
||||
if ($contact->blocked) {
|
||||
return true;
|
||||
}
|
||||
if ($DB->get_field('message_contacts', 'blocked', ['userid' => $recipientid, 'contactid' => $senderid])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace core_message\output\messagearea;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core_message\api;
|
||||
use renderable;
|
||||
use templatable;
|
||||
|
||||
@@ -95,6 +96,8 @@ class messages implements templatable, renderable {
|
||||
$data->messages[] = $message->export_for_template($output);
|
||||
}
|
||||
|
||||
$data->isblocked = api::is_user_blocked($this->currentuserid, $this->otheruserid);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -996,7 +996,8 @@ class core_message_external extends external_api {
|
||||
'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
|
||||
'messages' => new external_multiple_structure(
|
||||
self::get_messagearea_message_structure()
|
||||
)
|
||||
),
|
||||
'isblocked' => new external_value(PARAM_BOOL, 'Is this user blocked by the current user?', VALUE_DEFAULT, false),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,37 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template core_message/message_area_messages_area
|
||||
|
||||
Messages area template.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Context variables required for this template:
|
||||
* isonline - boolean
|
||||
* isblocked - boolean
|
||||
* otheruserid - int
|
||||
* otheruserfullname - string
|
||||
* messages - array of messages
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"isonline": true,
|
||||
"isblocked": true,
|
||||
"otheruserid": 1,
|
||||
"otheruserfullname": "Sam Student",
|
||||
"messages": [
|
||||
{
|
||||
"text": "Hello there!"
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
{{#otheruserid}}
|
||||
<div class="messages-header">
|
||||
<div class="view-toggle btn-container">
|
||||
@@ -25,6 +56,11 @@
|
||||
<div class="name-container">
|
||||
<div class="name">
|
||||
<button class="btn btn-link" data-action="view-contact-profile" data-userid="{{otheruserid}}">{{otheruserfullname}}</button>
|
||||
{{#isblocked}}
|
||||
<span data-region="contact-icon-blocked">
|
||||
{{#pix}} t/block, core, {{#str}} contactblocked, message {{/str}} {{/pix}}
|
||||
</span>
|
||||
{{/isblocked}}
|
||||
</div>
|
||||
<div class="status {{#isonline}}online{{/isonline}}">
|
||||
<span class="offline-text">{{#str}} offline, message {{/str}}</span>
|
||||
|
||||
@@ -839,13 +839,17 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$this->setUser($user1);
|
||||
|
||||
// User shouldn't be blocked.
|
||||
$this->assertFalse(\core_message\api::is_user_blocked($user1, $user2));
|
||||
$this->assertFalse(\core_message\api::is_user_blocked($user1->id, $user2->id));
|
||||
|
||||
// Block the user.
|
||||
message_block_contact($user2->id);
|
||||
|
||||
// User should be blocked.
|
||||
$this->assertTrue(\core_message\api::is_user_blocked($user1, $user2));
|
||||
$this->assertTrue(\core_message\api::is_user_blocked($user1->id, $user2->id));
|
||||
|
||||
// Unblock the user.
|
||||
message_unblock_contact($user2->id);
|
||||
$this->assertFalse(\core_message\api::is_user_blocked($user1->id, $user2->id));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -865,7 +869,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
|
||||
$this->setAdminUser();
|
||||
|
||||
// As the admin you should still be able to send messages to the user.
|
||||
$this->assertFalse(\core_message\api::is_user_blocked($user1));
|
||||
$this->assertFalse(\core_message\api::is_user_blocked($user1->id));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -4872,7 +4872,7 @@ class assign {
|
||||
|
||||
if ($this->can_view_submission($user->id)) {
|
||||
|
||||
if (has_capability('mod/assign:submit', $this->get_context(), $user)) {
|
||||
if (has_capability('mod/assign:submit', $this->get_context(), $user, false)) {
|
||||
$submissionstatus = $this->get_assign_submission_status_renderable($user, $showlinks);
|
||||
$o .= $this->get_renderer()->render($submissionstatus);
|
||||
}
|
||||
|
||||
@@ -927,14 +927,6 @@
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.path-mod-assign #page-content [data-region="grade-panel"] .mform:not(.unresponsive) #id_attemptsettings .fitem .fitemtitle,
|
||||
.path-mod-assign #page-content [data-region="grade-panel"] .mform:not(.unresponsive) #id_attemptsettings .fitem .felement {
|
||||
display: table-cell;
|
||||
float: none;
|
||||
border-top: 1px solid #ddd;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.path-mod-assign #page-content [data-region="grade-panel"] .mform:not(.unresponsive) #id_attemptsettings .fitem:last-of-type .fitemtitle,
|
||||
.path-mod-assign #page-content [data-region="grade-panel"] .mform:not(.unresponsive) #id_attemptsettings .fitem:last-of-type .felement {
|
||||
border-bottom: 1px solid #ddd;
|
||||
|
||||
@@ -146,13 +146,17 @@ class behat_mod_feedback extends behat_base {
|
||||
|
||||
// If chart data is not visible then expand.
|
||||
$node = $this->get_selected_node("xpath_element", $charttabledataxpath);
|
||||
if ($node && !$node->isVisible()) {
|
||||
$this->execute('behat_general::i_click_on_in_the', array(
|
||||
get_string('showchartdata'),
|
||||
'link',
|
||||
$feedbackxpath,
|
||||
'xpath_element'
|
||||
));
|
||||
if ($node) {
|
||||
if (!$node->isVisible()) {
|
||||
// Focus on node, before checking if it's visible.
|
||||
$node->focus();
|
||||
$this->execute('behat_general::i_click_on_in_the', array(
|
||||
get_string('showchartdata'),
|
||||
'link',
|
||||
$feedbackxpath,
|
||||
'xpath_element'
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -124,8 +124,8 @@ class mod_forum_observer {
|
||||
global $CFG;
|
||||
|
||||
$course = $event->get_record_snapshot('course', $event->objectid);
|
||||
|
||||
if (!empty($course->newsitems)) {
|
||||
$format = course_get_format($course);
|
||||
if ($format->supports_news() && !empty($course->newsitems)) {
|
||||
require_once($CFG->dirroot . '/mod/forum/lib.php');
|
||||
// Auto create the announcements forum.
|
||||
forum_get_course_forum($event->objectid, 'news');
|
||||
@@ -142,8 +142,8 @@ class mod_forum_observer {
|
||||
global $CFG;
|
||||
|
||||
$course = $event->get_record_snapshot('course', $event->objectid);
|
||||
|
||||
if (!empty($course->newsitems)) {
|
||||
$format = course_get_format($course);
|
||||
if ($format->supports_news() && !empty($course->newsitems)) {
|
||||
require_once($CFG->dirroot . '/mod/forum/lib.php');
|
||||
// Auto create the announcements forum.
|
||||
forum_get_course_forum($event->objectid, 'news');
|
||||
|
||||
@@ -134,6 +134,7 @@ Feature: Lesson user override
|
||||
And I set the following fields to these values:
|
||||
| Password protected lesson | Yes |
|
||||
| id_password | moodle_rules |
|
||||
And I wait until the page is ready
|
||||
And I press "Save and display"
|
||||
And I navigate to "User overrides" node in "Lesson administration"
|
||||
And I press "Add user override"
|
||||
|
||||
+1
-1
@@ -1961,7 +1961,7 @@ function quiz_check_updates_since(cm_info $cm, $from, $filter = array()) {
|
||||
$select = 'id ' . $questionsql . ' AND (timemodified > :time1 OR timecreated > :time2)';
|
||||
$params['time1'] = $from;
|
||||
$params['time2'] = $from;
|
||||
$questions = $DB->count_records_select('question', $select, $params) > 0;
|
||||
$questions = $DB->get_records_select('question', $select, $params, '', 'id');
|
||||
if (!empty($questions)) {
|
||||
$updates->questions->updated = true;
|
||||
$updates->questions->itemids = array_keys($questions);
|
||||
|
||||
@@ -45,6 +45,7 @@ Feature: Scorm multi-sco completion
|
||||
And I should see "Play of the game"
|
||||
And I switch to the main frame
|
||||
And I follow "Exit activity"
|
||||
And I wait until the page is ready
|
||||
Then I should see "Basic Multi-sco SCORM package"
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
@@ -80,6 +81,7 @@ Feature: Scorm multi-sco completion
|
||||
And I should see "Play of the game"
|
||||
And I switch to the main frame
|
||||
And I follow "Exit activity"
|
||||
And I wait until the page is ready
|
||||
Then I should see "ADV Multi-sco SCORM package"
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
|
||||
@@ -24,9 +24,10 @@ function wiki_print_editor_html($pageid, $content, $version = -1, $section = nul
|
||||
$action .= "§ion=".urlencode($section);
|
||||
}
|
||||
|
||||
echo $OUTPUT->container_start('mdl-align');
|
||||
echo $OUTPUT->container_start('container');
|
||||
echo '<form method="post" action="'.$action.'">';
|
||||
echo $OUTPUT->container(print_textarea(true, 20, 100, 0, 0, "newcontent", $content, 0, true, '', 'form-textarea-advanced'), 'wiki_editor');
|
||||
$textarea = print_textarea(true, 20, 100, 0, 0, "newcontent", $content, 0, true, '', 'form-textarea-advanced');
|
||||
echo $OUTPUT->container($textarea, 'wiki_editor');
|
||||
wiki_print_edit_form_default_fields('html', $pageid, $version, $upload, $deleteuploads);
|
||||
echo '</form>';
|
||||
echo $OUTPUT->container_end();
|
||||
|
||||
@@ -64,7 +64,7 @@ function wiki_print_editor_wiki($pageid, $content, $editor, $version = -1, $sect
|
||||
|
||||
$PAGE->requires->js('/mod/wiki/editors/wiki/buttons.js');
|
||||
|
||||
echo $OUTPUT->container_start('mdl-align');
|
||||
echo $OUTPUT->container_start();
|
||||
foreach ($wiki_editor as $button) {
|
||||
echo "<a href=\"javascript:insertTags";
|
||||
echo "('" . $button[2] . "','" . $button[3] . "','" . $button[4] . "');\">";
|
||||
@@ -73,7 +73,7 @@ function wiki_print_editor_wiki($pageid, $content, $editor, $version = -1, $sect
|
||||
}
|
||||
echo $OUTPUT->container_end();
|
||||
|
||||
echo $OUTPUT->container_start('mdl-align');
|
||||
echo $OUTPUT->container_start();
|
||||
echo '<form method="post" id="mform1" action="' . $action . '">';
|
||||
echo $OUTPUT->container(print_textarea(false, 20, 60, 0, 0, "newcontent", $content, 0, true), false, 'wiki_editor');
|
||||
echo $OUTPUT->container_start();
|
||||
|
||||
@@ -53,8 +53,6 @@ class MoodleQuickForm_wikieditor extends MoodleQuickForm_textarea {
|
||||
$this->files = $attributes['files'];
|
||||
unset($attributes['files']);
|
||||
}
|
||||
|
||||
|
||||
parent::__construct($elementName, $elementLabel, $attributes);
|
||||
$this->_type = 'wikieditor';
|
||||
}
|
||||
@@ -144,7 +142,8 @@ class MoodleQuickForm_wikieditor extends MoodleQuickForm_textarea {
|
||||
$html .= "</a>";
|
||||
}
|
||||
$html .= "<label class='accesshide' for='addtags'>" . get_string('insertimage', 'wiki') . "</label>";
|
||||
$html .= "<select id='addtags' onchange=\"insertTags('{$imagetag[0]}', '{$imagetag[1]}', this.value)\">";
|
||||
$html .= "<select id='addtags' class='custom-select m-x-1' " .
|
||||
"onchange=\"insertTags('{$imagetag[0]}', '{$imagetag[1]}', this.value)\">";
|
||||
$html .= "<option value='" . s(get_string('wikiimage', 'wiki')) . "'>" . get_string('insertimage', 'wiki') . '</option>';
|
||||
foreach ($this->files as $filename) {
|
||||
$html .= "<option value='".s($filename)."'>";
|
||||
@@ -178,7 +177,15 @@ class MoodleQuickForm_wikieditor extends MoodleQuickForm_textarea {
|
||||
|
||||
public function export_for_template(renderer_base $output) {
|
||||
$context = $this->export_for_template_base($output);
|
||||
|
||||
// We do want the form-control class on the output from toHTML - but we dont' want it when calling export_for_template.
|
||||
// This is because in this type of form element the export_for_template calls toHTML to get the html for the context.
|
||||
// If we did both we would be duplicating the form-control which messes up the styles.
|
||||
$saved = $this->getAttribute('class');
|
||||
$this->updateAttributes(['class' => $saved . ' form-control']);
|
||||
|
||||
$context['html'] = $this->toHtml();
|
||||
$this->updateAttributes(['class' => $saved]);
|
||||
|
||||
return $context;
|
||||
}
|
||||
|
||||
@@ -1438,14 +1438,14 @@ function wiki_print_edit_form_default_fields($format, $pageid, $version = -1, $u
|
||||
|
||||
echo "<fieldset class=\"wiki-upload-section clearfix\"><legend class=\"ftoggler\">" . get_string("uploadtitle", 'wiki') . "</legend>";
|
||||
|
||||
echo $OUTPUT->container_start('mdl-align wiki-form-center aaaaa');
|
||||
echo $OUTPUT->container_start('container');
|
||||
print $filemanager->toHtml();
|
||||
echo $OUTPUT->container_end();
|
||||
|
||||
$cm = $PAGE->cm;
|
||||
$context = context_module::instance($cm->id);
|
||||
|
||||
echo $OUTPUT->container_start('mdl-align wiki-form-center wiki-upload-table');
|
||||
echo $OUTPUT->container_start('container wiki-upload-table');
|
||||
wiki_print_upload_table($context, 'wiki_upload', $pageid, $deleteuploads);
|
||||
echo $OUTPUT->container_end();
|
||||
|
||||
|
||||
+24
-29
@@ -1282,7 +1282,6 @@ class page_wiki_history extends page_wiki {
|
||||
$table = new html_table();
|
||||
$table->head = array('', get_string('version'), get_string('user'), get_string('modified'), '');
|
||||
$table->data = $contents;
|
||||
$table->attributes['class'] = 'mdl-align';
|
||||
|
||||
echo html_writer::table($table);
|
||||
|
||||
@@ -1314,15 +1313,15 @@ class page_wiki_history extends page_wiki {
|
||||
|
||||
$table->head = array(get_string('diff', 'wiki') . $icon, get_string('version'), get_string('user'), get_string('modified'), '');
|
||||
$table->data = $contents;
|
||||
$table->attributes['class'] = 'generaltable mdl-align';
|
||||
$table->attributes['class'] = 'table generaltable';
|
||||
$table->rowclasses = $rowclass;
|
||||
|
||||
// Print the form.
|
||||
echo html_writer::start_tag('form', array('action'=>new moodle_url('/mod/wiki/diff.php'), 'method'=>'get', 'id'=>'diff'));
|
||||
echo html_writer::tag('div', html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'pageid', 'value'=>$pageid)));
|
||||
echo html_writer::table($table);
|
||||
echo html_writer::start_tag('div', array('class'=>'mdl-align'));
|
||||
echo html_writer::empty_tag('input', array('type'=>'submit', 'class'=>'wiki_form-button', 'value'=>get_string('comparesel', 'wiki')));
|
||||
echo html_writer::start_tag('div');
|
||||
echo html_writer::empty_tag('input', array('type'=>'submit', 'class'=>'wiki_form-button btn btn-secondary', 'value'=>get_string('comparesel', 'wiki')));
|
||||
echo html_writer::end_tag('div');
|
||||
echo html_writer::end_tag('form');
|
||||
}
|
||||
@@ -1336,11 +1335,11 @@ class page_wiki_history extends page_wiki {
|
||||
//print_paging_bar($vcount, $paging, $rowsperpage,$CFG->wwwroot.'/mod/wiki/history.php?pageid='.$pageid.'&','paging');
|
||||
} else {
|
||||
$link = new moodle_url('/mod/wiki/history.php', array('pageid' => $pageid));
|
||||
$OUTPUT->container(html_writer::link($link->out(false), get_string('viewperpage', 'wiki', $this->rowsperpage)), 'mdl-align');
|
||||
$OUTPUT->container(html_writer::link($link->out(false), get_string('viewperpage', 'wiki', $this->rowsperpage)));
|
||||
}
|
||||
if ($vcount > $this->rowsperpage && !$this->allversion) {
|
||||
$link = new moodle_url('/mod/wiki/history.php', array('pageid' => $pageid, 'allversion' => 1));
|
||||
$OUTPUT->container(html_writer::link($link->out(false), get_string('viewallhistory', 'wiki')), 'mdl-align');
|
||||
$OUTPUT->container(html_writer::link($link->out(false), get_string('viewallhistory', 'wiki')));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1484,7 +1483,7 @@ class page_wiki_map extends page_wiki {
|
||||
|
||||
$table = new html_table();
|
||||
$table->head = array(get_string('contributions', 'wiki') . $OUTPUT->help_icon('contributions', 'wiki'));
|
||||
$table->attributes['class'] = 'wiki_editor generalbox';
|
||||
$table->attributes['class'] = 'generalbox table';
|
||||
$table->data = array();
|
||||
$table->rowclasses = array();
|
||||
|
||||
@@ -1548,7 +1547,7 @@ class page_wiki_map extends page_wiki {
|
||||
$fromlinks = wiki_get_linked_from_pages($page->id);
|
||||
|
||||
$table = new html_table();
|
||||
$table->attributes['class'] = 'wiki_navigation_from';
|
||||
$table->attributes['class'] = 'wiki_navigation_from table';
|
||||
$table->head = array(get_string('navigationfrom', 'wiki') . $OUTPUT->help_icon('navigationfrom', 'wiki') . ':');
|
||||
$table->data = array();
|
||||
$table->rowclasses = array();
|
||||
@@ -1556,13 +1555,12 @@ class page_wiki_map extends page_wiki {
|
||||
$lpage = wiki_get_page($link->frompageid);
|
||||
$link = new moodle_url('/mod/wiki/view.php', array('pageid' => $lpage->id));
|
||||
$table->data[] = array(html_writer::link($link->out(false), format_string($lpage->title)));
|
||||
$table->rowclasses[] = 'mdl-align';
|
||||
}
|
||||
|
||||
$table_left = html_writer::table($table);
|
||||
$table_left = $OUTPUT->container(html_writer::table($table), 'col-md-6 span6');
|
||||
|
||||
$table = new html_table();
|
||||
$table->attributes['class'] = 'wiki_navigation_to';
|
||||
$table->attributes['class'] = 'wiki_navigation_to table';
|
||||
$table->head = array(get_string('navigationto', 'wiki') . $OUTPUT->help_icon('navigationto', 'wiki') . ':');
|
||||
$table->data = array();
|
||||
$table->rowclasses = array();
|
||||
@@ -1575,10 +1573,9 @@ class page_wiki_map extends page_wiki {
|
||||
$viewlink = new moodle_url('/mod/wiki/view.php', array('pageid' => $lpage->id));
|
||||
$table->data[] = array(html_writer::link($viewlink->out(false), format_string($lpage->title)));
|
||||
}
|
||||
$table->rowclasses[] = 'mdl-align';
|
||||
}
|
||||
$table_right = html_writer::table($table);
|
||||
echo $OUTPUT->container($table_left . $table_right, 'wiki_navigation_container');
|
||||
$table_right = $OUTPUT->container(html_writer::table($table), 'col-md-6 span6');
|
||||
echo $OUTPUT->container($table_left . $table_right, 'wiki_navigation_container row');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1604,7 +1601,7 @@ class page_wiki_map extends page_wiki {
|
||||
|
||||
$table = new html_table();
|
||||
$table->head = array(get_string('pageindex', 'wiki') . $OUTPUT->help_icon('pageindex', 'wiki'));
|
||||
$table->attributes['class'] = 'wiki_editor generalbox';
|
||||
$table->attributes['class'] = 'generalbox table';
|
||||
$table->data[] = array($this->render_navigation_node($tree));
|
||||
|
||||
echo html_writer::table($table);
|
||||
@@ -1643,8 +1640,7 @@ class page_wiki_map extends page_wiki {
|
||||
|
||||
$table = new html_table();
|
||||
$table->head = array(get_string('pagelist', 'wiki') . $OUTPUT->help_icon('pagelist', 'wiki'));
|
||||
$table->attributes['class'] = 'wiki_editor generalbox';
|
||||
$table->align = array('center');
|
||||
$table->attributes['class'] = 'generalbox table';
|
||||
foreach ($stdaux as $key => $elem) {
|
||||
$table->data[] = array($key);
|
||||
foreach ($elem as $e) {
|
||||
@@ -1673,7 +1669,7 @@ class page_wiki_map extends page_wiki {
|
||||
|
||||
$table = new html_table();
|
||||
$table->head = array(get_string('orphaned', 'wiki') . $OUTPUT->help_icon('orphaned', 'wiki'));
|
||||
$table->attributes['class'] = 'wiki_editor generalbox';
|
||||
$table->attributes['class'] = 'generalbox table';
|
||||
$table->data = array();
|
||||
$table->rowclasses = array();
|
||||
|
||||
@@ -1709,7 +1705,7 @@ class page_wiki_map extends page_wiki {
|
||||
|
||||
$table = new html_table();
|
||||
$table->head = array(get_string('updatedpages', 'wiki') . $OUTPUT->help_icon('updatedpages', 'wiki'));
|
||||
$table->attributes['class'] = 'wiki_editor generalbox';
|
||||
$table->attributes['class'] = 'generalbox table';
|
||||
$table->data = array();
|
||||
$table->rowclasses = array();
|
||||
|
||||
@@ -1894,7 +1890,7 @@ class page_wiki_restoreversion extends page_wiki {
|
||||
$restoreurl = new moodle_url('/mod/wiki/restoreversion.php', $optionsyes);
|
||||
$return = new moodle_url('/mod/wiki/viewversion.php', array('pageid'=>$this->page->id, 'versionid'=>$version->id));
|
||||
|
||||
echo $OUTPUT->container_start('wiki-form-center');
|
||||
echo $OUTPUT->container_start();
|
||||
echo html_writer::tag('div', get_string('restoreconfirm', 'wiki', $version->version));
|
||||
echo $OUTPUT->container_start(false, 'wiki_restoreform');
|
||||
echo '<form class="wiki_restore_yes" action="' . $restoreurl . '" method="post" id="restoreversion">';
|
||||
@@ -1964,7 +1960,7 @@ class page_wiki_deletecomment extends page_wiki {
|
||||
$deleteurl = new moodle_url('/mod/wiki/instancecomments.php', $optionsyes);
|
||||
$return = new moodle_url('/mod/wiki/comments.php', array('pageid'=>$this->page->id));
|
||||
|
||||
echo $OUTPUT->container_start('wiki-form-center');
|
||||
echo $OUTPUT->container_start();
|
||||
echo html_writer::tag('p', $strdeletecheckfull);
|
||||
echo $OUTPUT->container_start(false, 'wiki_deletecommentform');
|
||||
echo '<form class="wiki_deletecomment_yes" action="' . $deleteurl . '" method="post" id="deletecomment">';
|
||||
@@ -2137,7 +2133,7 @@ class page_wiki_viewversion extends page_wiki {
|
||||
$viewlink = new moodle_url('/user/view.php', array('id' => $userinfo->id));
|
||||
$heading .= ' <strong>' . get_string('user') . ':</strong> ' . html_writer::link($viewlink->out(false), fullname($userinfo));
|
||||
$heading .= ' → ' . $OUTPUT->user_picture(wiki_get_user_info($pageversion->userid), array('popup' => true)) . '</p>';
|
||||
echo $OUTPUT->container($heading, 'wiki_headingtime', 'mdl-align wiki_modifieduser');
|
||||
echo $OUTPUT->container($heading, 'wiki_headingtime', 'wiki_modifieduser');
|
||||
$options = array('swid' => $this->subwiki->id, 'pretty_print' => true, 'pageid' => $this->page->id);
|
||||
|
||||
$pageversion->content = file_rewrite_pluginfile_urls($pageversion->content, 'pluginfile.php', $this->modcontext->id, 'mod_wiki', 'attachments', $this->subwiki->id);
|
||||
@@ -2509,7 +2505,7 @@ class page_wiki_admin extends page_wiki {
|
||||
$contents = array();
|
||||
$table = new html_table();
|
||||
$table->head = array('', get_string('pagename','wiki'));
|
||||
$table->attributes['class'] = 'generaltable mdl-align';
|
||||
$table->attributes['class'] = 'table generaltable';
|
||||
$swid = $this->subwiki->id;
|
||||
if ($showorphan) {
|
||||
if ($orphanedpages = wiki_get_orphaned_pages($swid)) {
|
||||
@@ -2536,7 +2532,7 @@ class page_wiki_admin extends page_wiki {
|
||||
|
||||
echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'option', 'value' => $this->view));
|
||||
echo html_writer::table($table);
|
||||
echo html_writer::start_tag('div', array('class' => 'mdl-align'));
|
||||
echo html_writer::start_tag('div');
|
||||
if (!$showorphan) {
|
||||
echo html_writer::empty_tag('input', array(
|
||||
'type' => 'submit',
|
||||
@@ -2547,7 +2543,7 @@ class page_wiki_admin extends page_wiki {
|
||||
echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'listall', 'value'=>'1'));
|
||||
echo html_writer::empty_tag('input', array(
|
||||
'type' => 'submit',
|
||||
'class' => 'wiki_form-button',
|
||||
'class' => 'wiki_form-button btn btn-secondary',
|
||||
'value' => get_string('listall', 'wiki'),
|
||||
'sesskey' => sesskey()));
|
||||
}
|
||||
@@ -2629,7 +2625,6 @@ class page_wiki_admin extends page_wiki {
|
||||
$table = new html_table();
|
||||
$table->head = array('', get_string('version'), get_string('user'), get_string('modified'), '');
|
||||
$table->data = $contents;
|
||||
$table->attributes['class'] = 'mdl-align';
|
||||
|
||||
echo html_writer::table($table);
|
||||
} else {
|
||||
@@ -2668,7 +2663,7 @@ class page_wiki_admin extends page_wiki {
|
||||
$table = new html_table();
|
||||
$table->head = array(get_string('deleteversions', 'wiki'), get_string('version'), get_string('user'), get_string('modified'), '');
|
||||
$table->data = $contents;
|
||||
$table->attributes['class'] = 'generaltable mdl-align';
|
||||
$table->attributes['class'] = 'table generaltable';
|
||||
$table->rowclasses = $rowclass;
|
||||
|
||||
///Print the form
|
||||
@@ -2677,8 +2672,8 @@ class page_wiki_admin extends page_wiki {
|
||||
echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'option', 'value' => $this->view));
|
||||
echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
|
||||
echo html_writer::table($table);
|
||||
echo html_writer::start_tag('div', array('class' => 'mdl-align'));
|
||||
echo html_writer::empty_tag('input', array('type' => 'submit', 'class' => 'wiki_form-button', 'value' => get_string('deleteversions', 'wiki')));
|
||||
echo html_writer::start_tag('div');
|
||||
echo html_writer::empty_tag('input', array('type' => 'submit', 'class' => 'wiki_form-button btn btn-secondary', 'value' => get_string('deleteversions', 'wiki')));
|
||||
echo html_writer::end_tag('div');
|
||||
echo html_writer::end_tag('form');
|
||||
}
|
||||
|
||||
@@ -35,13 +35,6 @@
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.wiki_editor {
|
||||
width: 50%;
|
||||
margin: auto;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.wiki_previewbox {
|
||||
width: 50%;
|
||||
margin: auto;
|
||||
@@ -92,12 +85,6 @@
|
||||
margin-left: 0%;
|
||||
}
|
||||
|
||||
.wiki-form-center {
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
.wiki-upload-table {
|
||||
margin: 8px auto;
|
||||
clear: both;
|
||||
@@ -364,12 +351,6 @@ a.wiki_edit_section {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.wikieditor-toolbar img {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.path-mod-wiki .printicon {
|
||||
background: url([[pix:t/print]]) no-repeat scroll 2px center transparent;
|
||||
padding-left: 20px;
|
||||
|
||||
@@ -60,18 +60,6 @@ class microsoft_skydrive extends oauth2_client {
|
||||
$this->foldernamecache = cache::make('repository_skydrive', 'foldername');
|
||||
}
|
||||
|
||||
/**
|
||||
* Should HTTP GET be used instead of POST?
|
||||
*
|
||||
* The Microsoft API does not support POST, so we should use
|
||||
* GET instead (with the auth_token passed as a GET param).
|
||||
*
|
||||
* @return bool true if GET should be used
|
||||
*/
|
||||
protected function use_http_get() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the auth url for OAuth 2.0 request
|
||||
* @return string the auth url
|
||||
@@ -88,6 +76,20 @@ class microsoft_skydrive extends oauth2_client {
|
||||
return 'https://login.live.com/oauth20_token.srf';
|
||||
}
|
||||
|
||||
/**
|
||||
* Post request.
|
||||
*
|
||||
* Overridden to convert the data to a string, else curl will set the wrong headers.
|
||||
*
|
||||
* @param string $url The URL.
|
||||
* @param array|string $params The parameters.
|
||||
* @param array $options The options.
|
||||
* @return bool
|
||||
*/
|
||||
public function post($url, $params = '', $options = array()) {
|
||||
return parent::post($url, format_postdata_for_curlcall($params), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads a file to a file from skydrive using authenticated request
|
||||
*
|
||||
|
||||
@@ -72,7 +72,7 @@ class repository_webdav extends repository {
|
||||
}
|
||||
public function get_file($url, $title = '') {
|
||||
$url = urldecode($url);
|
||||
$path = $this->prepare_file($title);
|
||||
$path = $this->prepare_file();
|
||||
if (!$this->dav->open()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
define(["jquery","./tether"],function(a,b){return window.jQuery=a,window.Tether=b,require(["theme_boost/util","theme_boost/alert","theme_boost/button","theme_boost/carousel","theme_boost/collapse","theme_boost/dropdown","theme_boost/modal","theme_boost/scrollspy","theme_boost/tab","theme_boost/tooltip","theme_boost/popover"],function(){a("body").popover({selector:'[data-toggle="popover"]',trigger:"focus"})}),{}});
|
||||
define(["jquery","./tether","core/event"],function(a,b,c){return window.jQuery=a,window.Tether=b,require(["theme_boost/util","theme_boost/alert","theme_boost/button","theme_boost/carousel","theme_boost/collapse","theme_boost/dropdown","theme_boost/modal","theme_boost/scrollspy","theme_boost/tab","theme_boost/tooltip","theme_boost/popover"],function(){a("body").popover({selector:'[data-toggle="popover"]',trigger:"focus"}),c.getLegacyEvents().done(function(b){a(document).on(b.FILTER_CONTENT_UPDATED,function(){a("body").popover({selector:'[data-toggle="popover"]',trigger:"focus"})})})}),{}});
|
||||
@@ -23,7 +23,7 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @since 2.9
|
||||
*/
|
||||
define(['jquery', './tether'], function(jQuery, Tether) {
|
||||
define(['jquery', './tether', 'core/event'], function(jQuery, Tether, Event) {
|
||||
|
||||
window.jQuery = jQuery;
|
||||
window.Tether = Tether;
|
||||
@@ -40,11 +40,23 @@ define(['jquery', './tether'], function(jQuery, Tether) {
|
||||
'theme_boost/tooltip',
|
||||
'theme_boost/popover'],
|
||||
function() {
|
||||
|
||||
jQuery('body').popover({
|
||||
selector: '[data-toggle="popover"]',
|
||||
trigger: 'focus'
|
||||
});
|
||||
|
||||
// We need to call popover automatically if nodes are added to the page later.
|
||||
Event.getLegacyEvents().done(function(events) {
|
||||
jQuery(document).on(events.FILTER_CONTENT_UPDATED, function() {
|
||||
jQuery('body').popover({
|
||||
selector: '[data-toggle="popover"]',
|
||||
trigger: 'focus'
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
return {};
|
||||
});
|
||||
|
||||
@@ -694,4 +694,12 @@ class core_renderer extends \core_renderer {
|
||||
return $skipped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Secure login info.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function secure_login_info() {
|
||||
return $this->login_info(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,16 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$blockshtml = $OUTPUT->blocks('side-pre');
|
||||
$hasblocks = strpos($blockshtml, 'data-block=') !== false;
|
||||
$bodyattributes = $OUTPUT->body_attributes();
|
||||
|
||||
$templatecontext = [
|
||||
'sitename' => format_string($SITE->shortname, true, array('context' => context_course::instance(SITEID))),
|
||||
'output' => $OUTPUT,
|
||||
'sidepreblocks' => $OUTPUT->blocks('side-pre'),
|
||||
'bodyattributes' => $bodyattributes,
|
||||
'sidepreblocks' => $blockshtml,
|
||||
'hasblocks' => $hasblocks
|
||||
];
|
||||
|
||||
echo $OUTPUT->render_from_template('theme_boost/secure', $templatecontext);
|
||||
|
||||
@@ -792,6 +792,7 @@
|
||||
|
||||
#adminsettings .form-overridden {
|
||||
@extend .form-control-feedback;
|
||||
@extend .alert-info;
|
||||
}
|
||||
|
||||
.modal.modal-in-page {
|
||||
|
||||
@@ -64,6 +64,9 @@
|
||||
width: 98%;
|
||||
height: 98%;
|
||||
}
|
||||
.file-picker .fp-def-search {
|
||||
margin-top: 0;
|
||||
}
|
||||
// Repositories on fp-repo-area (File Picker only)
|
||||
.file-picker .fp-list {
|
||||
list-style-type: none;
|
||||
|
||||
@@ -50,6 +50,10 @@
|
||||
border: 1px solid #e3e3e3;
|
||||
clear: both;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.contacts-area {
|
||||
border-right: 1px solid #e3e3e3;
|
||||
height: 600px;
|
||||
|
||||
@@ -355,7 +355,7 @@ div#dock {
|
||||
float: left;
|
||||
width: 20rem;
|
||||
display: inline-block;
|
||||
height: 12rem;
|
||||
min-height: 12rem;
|
||||
}
|
||||
|
||||
#page-mod-quiz-mod #id_reviewoptionshdr .btn-link {
|
||||
@@ -366,7 +366,7 @@ div#dock {
|
||||
float: left;
|
||||
clear: left;
|
||||
}
|
||||
#page-mod-quiz-mod #id_reviewoptionshdr .form-check-inline {
|
||||
#page-mod-quiz-mod #id_reviewoptionshdr .form-check {
|
||||
width: 90%;
|
||||
height: 22px;
|
||||
}
|
||||
@@ -462,9 +462,8 @@ div#dock {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign.
|
||||
*/
|
||||
|
||||
// Assign.
|
||||
.path-mod-assign [data-region="grade-actions-panel"] [data-region="grade-actions"] .collapse-buttons {
|
||||
top: auto;
|
||||
}
|
||||
@@ -472,38 +471,69 @@ div#dock {
|
||||
overflow: initial;
|
||||
}
|
||||
|
||||
.path-mod-assign [data-region="grade-panel"] .has-popout {
|
||||
background-color: $card-bg;
|
||||
// This section removes the responsiveness from the form in the grading panel
|
||||
$popout-header-font-size: 1.5 * $font-size-base;
|
||||
// This can't be calculated from modal-title-padding because we are mixing px and rem units.
|
||||
$popout-header-height: 4rem;
|
||||
|
||||
@include border-radius($card-border-radius);
|
||||
border: $card-border-width solid $card-border-color;
|
||||
.path-mod-assign #page-content [data-region="grade-panel"] .mform:not(.unresponsive) .fcontainer .fitem.popout .felement {
|
||||
height: calc(100% - #{$popout-header-height});
|
||||
}
|
||||
|
||||
.path-mod-assign [data-region="grade-panel"] {
|
||||
padding-top: $spacer;
|
||||
}
|
||||
.path-mod-assign [data-region="grade-panel"] .fitem > .col-md-3,
|
||||
.path-mod-assign [data-region="grade-panel"] .fitem > .col-md-9 {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
.path-mod-assign [data-region="grade-panel"] fieldset,
|
||||
.path-mod-assign [data-region="grade-panel"] .fitem.row {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.path-mod-assign [data-region="grade-panel"] .fitem > .col-md-3 > .pull-xs-right {
|
||||
float: none !important; /* stylelint-disable-line declaration-no-important */
|
||||
}
|
||||
|
||||
.path-mod-assign [data-region="grade-panel"] .mform .fitem.has-popout .felement {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.path-mod-assign [data-region="grade-panel"] .mform .fitem .felement {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
// Now styles for the popout sections.
|
||||
|
||||
.path-mod-assign [data-region="grade-panel"] .popout {
|
||||
background-color: $modal-content-bg;
|
||||
}
|
||||
|
||||
.path-mod-assign [data-region="grade-panel"] .col-md-3 {
|
||||
width: 100%;
|
||||
.path-mod-assign [data-region="grade-panel"] .fitem.has-popout {
|
||||
background-color: $card-bg;
|
||||
@include border-radius($card-border-radius);
|
||||
border: $card-border-width solid $card-border-color;
|
||||
padding: $card-spacer-x;
|
||||
margin-bottom: $spacer;
|
||||
}
|
||||
.path-mod-assign [data-region="grade-panel"] .has-popout .col-md-3 {
|
||||
border-bottom: $hr-border-width solid $hr-border-color;
|
||||
margin-bottom: $spacer;
|
||||
}
|
||||
|
||||
|
||||
.path-mod-assign [data-region="grade-panel"] .popout > .col-md-3 {
|
||||
@extend .modal-header;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.path-mod-assign [data-region="grade-panel"] [data-region="popout-button"] {
|
||||
margin-top: 0.5rem;
|
||||
font-size: $popout-header-font-size;
|
||||
}
|
||||
|
||||
.path-mod-assign [data-region="grade-panel"] .popout [data-region="popout-button"] {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.path-mod-assign [data-region="grade-panel"] h3 {
|
||||
margin: 10px 0;
|
||||
line-height: 40px;
|
||||
}
|
||||
// Now style the fixed header elements.
|
||||
|
||||
.path-mod-assign [data-region="assignment-info"] {
|
||||
overflow-y: hidden;
|
||||
@@ -525,6 +555,15 @@ div#dock {
|
||||
height: 85px;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.path-mod-assign [data-region="grading-navigation-panel"] {
|
||||
height: auto;
|
||||
}
|
||||
.path-mod-assign [data-region="user-info"] {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.path-mod-assign [data-region="grading-navigation"] [data-region="input-field"] input {
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
|
||||
@@ -58,13 +58,15 @@
|
||||
]
|
||||
}
|
||||
}}
|
||||
<ol class="breadcrumb" role="navigation">
|
||||
{{#get_items}}
|
||||
{{#has_action}}
|
||||
<li class="breadcrumb-item"><a href="{{{action}}}" {{#get_title}}title="{{get_title}}"{{/get_title}}>{{{text}}}</a></li>
|
||||
{{/has_action}}
|
||||
{{^has_action}}
|
||||
<li class="breadcrumb-item">{{{text}}}</li>
|
||||
{{/has_action}}
|
||||
{{/get_items}}
|
||||
</ol>
|
||||
<nav role="navigation">
|
||||
<ol class="breadcrumb">
|
||||
{{#get_items}}
|
||||
{{#has_action}}
|
||||
<li class="breadcrumb-item"><a href="{{{action}}}" {{#get_title}}title="{{get_title}}"{{/get_title}}>{{{text}}}</a></li>
|
||||
{{/has_action}}
|
||||
{{^has_action}}
|
||||
<li class="breadcrumb-item">{{{text}}}</li>
|
||||
{{/has_action}}
|
||||
{{/get_items}}
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
@@ -1,3 +1,94 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template core_form/element-select
|
||||
|
||||
Simple select form element template.
|
||||
|
||||
Context variables required for this template:
|
||||
* id - Element id,
|
||||
* name - Element name,
|
||||
* label - Element label,
|
||||
* multiple - multi select?,
|
||||
* checked - checked?,
|
||||
* error - Is there an error associated with this element?,
|
||||
* size - Element size,
|
||||
* value - Element value,
|
||||
* helpbutton - Helpbutton,
|
||||
* hiddenlabel - Element hidden flag,
|
||||
* frozen - Element frozen flag,
|
||||
* hardfrozen - Element hard fronzen flag,
|
||||
* extraclasses - Extra classes assocaited,
|
||||
* type - Element type,
|
||||
* attributes - Element attributes,
|
||||
* options - [
|
||||
{
|
||||
text - Option text,
|
||||
value - Option value,
|
||||
selected - Selected?,
|
||||
disabled - Disabled?,
|
||||
optionattributes - Option attributes
|
||||
}
|
||||
]
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"element": {
|
||||
"id": "id_maildisplay",
|
||||
"name": "maildisplay",
|
||||
"label": null,
|
||||
"multiple": null,
|
||||
"checked": null,
|
||||
"error": null,
|
||||
"size": null,
|
||||
"value": null,
|
||||
"helpbutton": "",
|
||||
"hiddenlabel": false,
|
||||
"frozen": false,
|
||||
"hardfrozen": false,
|
||||
"extraclasses": null,
|
||||
"type": "select",
|
||||
"attributes": "",
|
||||
"options": [
|
||||
{
|
||||
"text": "Hide my email address from everyone",
|
||||
"value": 0,
|
||||
"selected": false,
|
||||
"disabled": false,
|
||||
"optionattributes": ""
|
||||
},
|
||||
{
|
||||
"text": "Allow everyone to see my email address",
|
||||
"value": 1,
|
||||
"selected": true,
|
||||
"disabled": false,
|
||||
"optionattributes": ""
|
||||
},
|
||||
{
|
||||
"text": "Allow only other course members to see my email address",
|
||||
"value": 2,
|
||||
"selected": false,
|
||||
"disabled": false,
|
||||
"optionattributes": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}}
|
||||
{{< core_form/element-template }}
|
||||
{{$element}}
|
||||
{{^element.frozen}}
|
||||
@@ -12,7 +103,8 @@
|
||||
{{/error}}
|
||||
{{{element.attributes}}} >
|
||||
{{#element.options}}
|
||||
<option value="{{value}}" {{#selected}}selected{{/selected}} {{#disabled}}disabled{{/disabled}} {{{optionattributes}}}>{{text}}</option>
|
||||
<option value="{{value}}" {{#selected}}selected{{/selected}} {{#disabled}}disabled{{/disabled}}
|
||||
{{{optionattributes}}}>{{{text}}}</option>
|
||||
{{/element.options}}
|
||||
</select>
|
||||
{{/element.frozen}}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
{{!
|
||||
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/>.
|
||||
}}
|
||||
{{!
|
||||
Page header.
|
||||
}}
|
||||
<header role="banner" class="pos-f-t navbar navbar-full navbar-light bg-faded navbar-static-top moodle-has-zindex">
|
||||
|
||||
<div class="container-fluid">
|
||||
|
||||
<span class="navbar-brand {{# output.should_display_navbar_logo }}has-logo{{/ output.should_display_navbar_logo }}
|
||||
{{^ output.should_display_navbar_logo }}
|
||||
hidden-sm-down
|
||||
{{/ output.should_display_navbar_logo }}
|
||||
">
|
||||
|
||||
{{# output.should_display_navbar_logo }}
|
||||
<span class="logo hidden-xs-down">
|
||||
<img src="{{output.get_compact_logo_url}}" alt="{{sitename}}">
|
||||
</span>
|
||||
{{/ output.should_display_navbar_logo }}
|
||||
<span class="site-name hidden-sm-down">{{{ sitename }}}</span>
|
||||
</span>
|
||||
<div class="pull-xs-right nav-link">
|
||||
{{{ output.secure_login_info }}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<button aria-expanded="{{#navdraweropen}}true{{/navdraweropen}}{{^navdraweropen}}false{{/navdraweropen}}" aria-controls="nav-drawer" type="button" class="btn pull-xs-left m-r-1 btn-secondary" data-action="toggle-drawer" data-side="left" data-preference="drawer-open-nav">☰<span class="sr-only">{{#str}}expand, core{{/str}}</span></button>
|
||||
</div>
|
||||
|
||||
<a role="banner" href="{{{ config.wwwroot }}}" class="navbar-brand {{# output.should_display_navbar_logo }}has-logo{{/ output.should_display_navbar_logo }}
|
||||
<a href="{{{ config.wwwroot }}}" class="navbar-brand {{# output.should_display_navbar_logo }}has-logo{{/ output.should_display_navbar_logo }}
|
||||
{{^ output.should_display_navbar_logo }}
|
||||
hidden-sm-down
|
||||
{{/ output.should_display_navbar_logo }}
|
||||
|
||||
@@ -43,56 +43,53 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
</head>
|
||||
|
||||
<body {{{ output.body_attributes }}}>
|
||||
<body {{{ bodyattributes }}}>
|
||||
|
||||
{{{ output.standard_top_of_body_html }}}
|
||||
<div id="page-wrapper">
|
||||
|
||||
<header class="navbar navbar-full navbar-light bg-faded navbar-static-top moodle-has-zindex">
|
||||
<div class="container">
|
||||
<div class="clearfix">
|
||||
<button class="navbar-toggler pull-xs-right hidden-sm-up" data-toggle="collapse" data-target="#bd-main-mav">☰<span class="sr-only">{{#str}}expand{{/str}}</span></button>
|
||||
</div>
|
||||
{{{ output.standard_top_of_body_html }}}
|
||||
|
||||
<a role="banner" href="{{{ config.wwwroot }}}" class="navbar-brand">
|
||||
{{# output.should_display_navbar_logo }}
|
||||
<div class="logo">
|
||||
<img src="{{output.get_compact_logo_url}}" alt={{#quote}}{{sitename}}{{/quote}}>
|
||||
{{>theme_boost/header-secure}}
|
||||
|
||||
<div id="page" class="container-fluid">
|
||||
{{! Secured full header }}
|
||||
|
||||
<div id="page-header" class="row">
|
||||
<div class="col-xs-12 p-y-1">
|
||||
<div class="page-context-header">
|
||||
<div class="page-header-headings">
|
||||
{{{ output.page_heading }}}
|
||||
</div>
|
||||
</div>
|
||||
{{/ output.should_display_navbar_logo }}
|
||||
<div class="site-name">{{{ sitename }}}</div>
|
||||
</a>
|
||||
|
||||
<div class="collapse navbar-toggleable-xs" id="bd-main-nav">
|
||||
<nav class="nav navbar-nav">
|
||||
<!-- search_box -->
|
||||
{{{ output.search_box }}}
|
||||
<!-- custom_menu -->
|
||||
{{{ output.custom_menu }}}
|
||||
<!-- page_heading_menu -->
|
||||
{{{ output.page_heading_menu }}}
|
||||
<!-- login info -->
|
||||
{{{ output.login_info }}}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div id="page" class="container">
|
||||
{{{ output.full_header }}}
|
||||
|
||||
<div id="page-content" class="row">
|
||||
<div id="region-main-box" class="col-xs-12">
|
||||
<div class="row">
|
||||
<section id="region-main" class="col-xs-12">
|
||||
<div id="page-content" class="row">
|
||||
<div id="region-main-box" class="col-xs-12">
|
||||
<section id="region-main" {{#hasblocks}}class="has-blocks"{{/hasblocks}}>
|
||||
<div class="card card-block">
|
||||
{{{ output.course_content_header }}}
|
||||
{{{ output.main_content }}}
|
||||
{{{ output.course_content_footer }}}
|
||||
</div>
|
||||
</section>
|
||||
{{#hasblocks}}
|
||||
<section data-region="blocks-column">
|
||||
{{{ sidepreblocks }}}
|
||||
</section>
|
||||
{{/hasblocks}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{{ output.standard_end_of_body_html }}}
|
||||
|
||||
</div>
|
||||
<footer id="page-footer" class="p-y-1 bg-inverse">
|
||||
<div class="container">
|
||||
<div id="course-footer">{{{ output.course_footer }}}</div>
|
||||
|
||||
{{{ output.standard_end_of_body_html }}}
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
{{#js}}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Basic authentication steps definitions.
|
||||
*
|
||||
* @package core_auth
|
||||
* @category test
|
||||
* @copyright 2012 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
|
||||
|
||||
require_once(__DIR__ . '/../../../../lib/behat/behat_base.php');
|
||||
require_once(__DIR__ . '/../../../../auth/tests/behat/behat_auth.php');
|
||||
|
||||
/**
|
||||
* Log in log out steps definitions.
|
||||
*
|
||||
* @package core_auth
|
||||
* @category test
|
||||
* @copyright 2012 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class behat_theme_boost_behat_auth extends behat_auth {
|
||||
|
||||
public function i_log_out() {
|
||||
// There is no longer any need to worry about whether the navigation
|
||||
// bar needs to be expanded; user_menu now lives outside the
|
||||
// hamburger.
|
||||
|
||||
// However, the user menu *always* needs to be expanded. if running JS.
|
||||
if ($this->running_javascript()) {
|
||||
$xpath = "//div[@class='usermenu']//a[contains(concat(' ', @class, ' '), ' dropdown-toggle ')]";
|
||||
|
||||
$this->execute('behat_general::i_click_on', array($xpath, "xpath_element"));
|
||||
}
|
||||
|
||||
// No need to check for exceptions as it will checked after this step execution.
|
||||
$this->execute('behat_general::click_link', get_string('logout'));
|
||||
}
|
||||
}
|
||||
@@ -192,7 +192,7 @@ a.autolink.glossary:hover {
|
||||
}
|
||||
/*rtl:raw:
|
||||
.collapsible-actions .collapseexpand {
|
||||
background: url([[pix:t/collapsed_rtl]]);
|
||||
background: url([[pix:t/collapsed_rtl]]) right center no-repeat;
|
||||
}
|
||||
*/
|
||||
.collapsible-actions .collapse-all {
|
||||
|
||||
@@ -35,7 +35,7 @@ form {
|
||||
.mform fieldset.collapsible legend a.fheader {
|
||||
padding: 0 5px 0 20px;
|
||||
margin-left: -20px;
|
||||
background: url([[pix:t/expanded]]) 2px center no-repeat;
|
||||
background: url([[pix:t/expanded]]) left center no-repeat;
|
||||
}
|
||||
.mform fieldset.collapsed legend a.fheader {
|
||||
/*rtl:raw:
|
||||
|
||||
@@ -47,6 +47,10 @@
|
||||
clear: both;
|
||||
border-radius: 4px;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.contacts-area {
|
||||
border-right: 1px solid #e3e3e3;
|
||||
height: 600px;
|
||||
|
||||
@@ -9,6 +9,17 @@ select {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
// Assign
|
||||
.path-mod-assign #page-content [data-region="grade-panel"] .mform:not(.unresponsive) #id_attemptsettings .fitem {
|
||||
.fitemtitle,
|
||||
.felement {
|
||||
display: table-cell;
|
||||
float: none;
|
||||
border-top: 1px solid #ddd;
|
||||
padding: 8px 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Feedback module
|
||||
.path-mod-feedback .mform.feedback_form .fitem .fitemtitle {
|
||||
display: block;
|
||||
|
||||
@@ -162,7 +162,7 @@ a.autolink.glossary:hover {
|
||||
}
|
||||
/*rtl:raw:
|
||||
.collapsible-actions .collapseexpand {
|
||||
background: url([[pix:t/collapsed_rtl]]);
|
||||
background: url([[pix:t/collapsed_rtl]]) right center no-repeat;
|
||||
}
|
||||
*/
|
||||
.collapsible-actions .collapse-all {
|
||||
@@ -5838,6 +5838,9 @@ a.ygtvspacer:hover {
|
||||
clear: both;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.messaging-area-container .messaging-area img {
|
||||
max-width: 100%;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area {
|
||||
border-right: 1px solid #e3e3e3;
|
||||
height: 600px;
|
||||
@@ -13821,7 +13824,7 @@ form {
|
||||
.mform fieldset.collapsible legend a.fheader {
|
||||
padding: 0 5px 0 20px;
|
||||
margin-left: -20px;
|
||||
background: url([[pix:t/expanded]]) 2px center no-repeat;
|
||||
background: url([[pix:t/expanded]]) left center no-repeat;
|
||||
}
|
||||
.mform fieldset.collapsed legend a.fheader {
|
||||
/*rtl:raw:
|
||||
@@ -14456,6 +14459,13 @@ body.modal-open {
|
||||
select {
|
||||
width: auto;
|
||||
}
|
||||
.path-mod-assign #page-content [data-region="grade-panel"] .mform:not(.unresponsive) #id_attemptsettings .fitem .fitemtitle,
|
||||
.path-mod-assign #page-content [data-region="grade-panel"] .mform:not(.unresponsive) #id_attemptsettings .fitem .felement {
|
||||
display: table-cell;
|
||||
float: none;
|
||||
border-top: 1px solid #ddd;
|
||||
padding: 8px 0;
|
||||
}
|
||||
.path-mod-feedback .mform.feedback_form .fitem .fitemtitle {
|
||||
display: block;
|
||||
margin-top: 4px;
|
||||
|
||||
+2
-2
@@ -29,11 +29,11 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2016111800.00; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2016112200.00; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
|
||||
$release = '3.2rc1 (Build: 20161118)'; // Human-friendly version name
|
||||
$release = '3.2rc2 (Build: 20161122)'; // Human-friendly version name
|
||||
|
||||
$branch = '32'; // This version's branch.
|
||||
$maturity = MATURITY_RC; // This version's maturity level.
|
||||
|
||||
Reference in New Issue
Block a user