Merge branch 'MDL-56532-master' of git://github.com/andrewnicols/moodle
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 24 Oct 2016 18:05:03 +0000 (20:05 +0200)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 24 Oct 2016 18:05:03 +0000 (20:05 +0200)
329 files changed:
admin/admin_settings_search_form.php [new file with mode: 0644]
admin/auth_config.php
admin/search.php
admin/settings/appearance.php
admin/settings/top.php
admin/templates/setting_configpasswordunmask.mustache
admin/templates/settings.mustache
admin/templates/settings_search_results.mustache
admin/tool/behat/tests/behat/data_generators.feature
admin/tool/behat/tests/behat/edit_permissions.feature
admin/tool/behat/tests/behat/get_and_set_fields.feature
admin/tool/behat/tests/behat/manipulate_forms.feature
admin/tool/behat/tests/behat/nasty_strings.feature
admin/tool/lp/lib.php
admin/tool/lp/tests/behat/user_evidence_comp_link.feature
admin/tool/monitor/tests/behat/subscription.feature
admin/tool/recyclebin/tests/behat/backup_user_data.feature
admin/tool/recyclebin/tests/behat/basic_functionality.feature
admin/tool/usertours/amd/build/tour.min.js
admin/tool/usertours/amd/src/tour.js
admin/tool/usertours/classes/cache.php [new file with mode: 0644]
admin/tool/usertours/classes/helper.php
admin/tool/usertours/classes/local/table/step_list.php
admin/tool/usertours/classes/manager.php
admin/tool/usertours/classes/output/step.php
admin/tool/usertours/classes/step.php
admin/tool/usertours/classes/tour.php
admin/tool/usertours/db/caches.php [new file with mode: 0644]
admin/tool/usertours/lang/en/tool_usertours.php
admin/tool/usertours/tests/cache_test.php [new file with mode: 0644]
admin/tool/usertours/tests/helper_trait.php [new file with mode: 0644]
admin/tool/usertours/tests/manager_test.php
admin/tool/usertours/tests/step_output_test.php [deleted file]
admin/tool/usertours/tests/step_test.php
admin/tool/usertours/thirdpartylibs.xml
admin/tool/usertours/version.php
admin/upgradesettings.php
availability/condition/group/tests/condition_test.php
availability/condition/grouping/tests/condition_test.php
backup/util/ui/tests/behat/restore_moodle2_courses.feature
backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-debug.js
backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-min.js
backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall.js
backup/util/ui/yui/src/backupselectall/js/backupselectall.js
badges/tests/behat/award_badge.feature
blocks/activity_results/tests/behat/addblockinactivity.feature
blocks/activity_results/tests/behat/highscoreswithoutgroups.feature
blocks/activity_results/tests/behat/highscoreswithscales.feature
blocks/activity_results/tests/behat/highscoreswithscalesandgroups.feature
blocks/activity_results/tests/behat/highscoreswithseperategroups.feature
blocks/activity_results/tests/behat/highscoreswithvisiblegroups.feature
blocks/activity_results/tests/behat/lowscoreswithoutgroups.feature
blocks/activity_results/tests/behat/lowscoreswithscales.feature
blocks/activity_results/tests/behat/lowscoreswithscalesandgroups.feature
blocks/activity_results/tests/behat/lowscoreswithseperategroups.feature
blocks/activity_results/tests/behat/lowscoreswithvisiblegroups.feature
blocks/blog_menu/tests/behat/block_blog_menu_activity.feature
blocks/blog_tags/tests/behat/blogtag.feature
blocks/calendar_month/tests/behat/block_calendar_month_frontpage.feature
blocks/course_list/tests/behat/block_course_list_category.feature
blocks/course_summary/tests/behat/block_course_summary_frontpage.feature
blocks/navigation/tests/behat/expand_my_courses_setting.feature [deleted file]
blocks/news_items/tests/behat/display_news.feature
blocks/recent_activity/tests/behat/structural_changes.feature
blocks/search_forums/tests/behat/block_search_forums_course.feature
blocks/site_main_menu/tests/behat/add_url.feature
blocks/site_main_menu/tests/behat/edit_activities.feature
blocks/social_activities/tests/behat/edit_activities.feature
blocks/tags/tests/behat/tagcloud.feature
blocks/tests/behat/configure_block_throughout_site.feature
blocks/tests/behat/hidden_block_region.feature
calendar/tests/behat/calendar_lookahead.feature
cohort/tests/behat/add_cohort.feature
completion/tests/externallib_test.php
course/admin.php [new file with mode: 0644]
course/externallib.php
course/format/lib.php
course/format/social/lib.php
course/format/topics/lib.php
course/format/topics/tests/behat/edit_delete_sections.feature
course/format/weeks/lib.php
course/format/weeks/tests/behat/edit_delete_sections.feature
course/lib.php
course/switchrole.php
course/switchrole_form.php [new file with mode: 0644]
course/tests/behat/behat_course.php
course/tests/behat/category_change_visibility.feature
course/tests/behat/category_resort.feature
course/tests/behat/course_change_visibility.feature
course/tests/behat/course_controls.feature
course/tests/behat/course_creation.feature
course/tests/behat/move_activities.feature
course/tests/behat/navigate_course_list.feature
course/tests/courselib_test.php
course/tests/externallib_test.php
course/user.php
enrol/lti/tests/tool_provider_test.php
enrol/tests/behat/manage_enrolments_from_participants.feature
files/renderer.php
files/tests/behat/course_files.feature
grade/export/txt/tests/behat/export.feature
grade/export/xml/tests/behat/export.feature
grade/report/grader/tests/behat/ajax_grader.feature
grade/report/grader/tests/behat/switch_views.feature
grade/report/history/tests/behat/basic_functionality.feature
grade/report/singleview/tests/behat/singleview.feature
grade/report/user/tests/behat/user_view.feature
grade/report/user/tests/behat/view_usereport.feature
grade/tests/behat/grade_UI_settings.feature
grade/tests/behat/grade_aggregation.feature
grade/tests/behat/grade_aggregation_changes.feature
grade/tests/behat/grade_average.feature
grade/tests/behat/grade_calculated_grade_items.feature
grade/tests/behat/grade_calculated_grade_items_20150627.feature
grade/tests/behat/grade_calculated_weights.feature
grade/tests/behat/grade_contribution_with_extra_credit.feature
grade/tests/behat/grade_grade_minmax_change.feature
grade/tests/behat/grade_hidden_items.feature
grade/tests/behat/grade_letter_boundary.feature
grade/tests/behat/grade_letter_boundary_20160518.feature
grade/tests/behat/grade_mingrade.feature
grade/tests/behat/grade_minmax.feature
grade/tests/behat/grade_natural_exclude_empty.feature
grade/tests/behat/grade_natural_exclude_empty_20150619.feature
grade/tests/behat/grade_natural_normalisation.feature
grade/tests/behat/grade_natural_normalisation_20150619.feature
grade/tests/behat/grade_override_letter.feature
grade/tests/behat/grade_scales.feature
grade/tests/behat/grade_scales_aggregation.feature
grade/tests/behat/grade_single_item_scales.feature
grade/tests/behat/grade_to_pass.feature
grade/tests/behat/grade_view.feature
group/tests/behat/update_groups.feature
lang/en/admin.php
lang/en/block.php
lang/en/deprecated.txt
lang/en/form.php
lib/adminlib.php
lib/amd/build/templates.min.js
lib/amd/src/templates.js
lib/behat/behat_field_manager.php
lib/behat/classes/partial_named_selector.php
lib/behat/classes/util.php
lib/behat/form_field/behat_form_passwordunmask.php [new file with mode: 0644]
lib/blocklib.php
lib/classes/session/manager.php
lib/db/access.php
lib/deprecatedlib.php
lib/editor/atto/plugins/accessibilitychecker/tests/behat/accessibilitychecker.feature
lib/editor/atto/plugins/accessibilityhelper/tests/behat/accessibilityhelper.feature
lib/editor/atto/plugins/align/tests/behat/align.feature
lib/editor/atto/plugins/bold/tests/behat/bold.feature
lib/editor/atto/plugins/charmap/tests/behat/charmap.feature
lib/editor/atto/plugins/clear/tests/behat/clear.feature
lib/editor/atto/plugins/collapse/tests/behat/collapse.feature
lib/editor/atto/plugins/equation/tests/behat/equation.feature
lib/editor/atto/plugins/html/tests/behat/html.feature
lib/editor/atto/plugins/image/tests/behat/image.feature
lib/editor/atto/plugins/indent/tests/behat/indent.feature
lib/editor/atto/plugins/italic/tests/behat/italic.feature
lib/editor/atto/plugins/link/tests/behat/link.feature
lib/editor/atto/plugins/media/tests/behat/media.feature
lib/editor/atto/plugins/orderedlist/tests/behat/orderedlist.feature
lib/editor/atto/plugins/strike/tests/behat/strike.feature
lib/editor/atto/plugins/subscript/tests/behat/subscript.feature
lib/editor/atto/plugins/superscript/tests/behat/superscript.feature
lib/editor/atto/plugins/title/tests/behat/title.feature
lib/editor/atto/plugins/underline/tests/behat/underline.feature
lib/editor/atto/plugins/unorderedlist/tests/behat/unorderedlist.feature
lib/editor/atto/tests/behat/autosave.feature
lib/form/advcheckbox.php
lib/form/amd/build/passwordunmask.min.js [new file with mode: 0644]
lib/form/amd/src/passwordunmask.js [new file with mode: 0644]
lib/form/checkbox.php
lib/form/passwordunmask.php
lib/form/templatable_form_element.php
lib/form/templates/element-passwordunmask-fill.mustache [new file with mode: 0644]
lib/form/templates/element-passwordunmask.mustache [new file with mode: 0644]
lib/form/templates/element-template.mustache [new file with mode: 0644]
lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask-debug.js
lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask-min.js
lib/form/yui/build/moodle-form-passwordunmask/moodle-form-passwordunmask.js
lib/form/yui/src/passwordunmask/js/passwordunmask.js
lib/form/yui/src/passwordunmask/meta/passwordunmask.json
lib/formslib.php
lib/moodlelib.php
lib/navigationlib.php
lib/outputcomponents.php
lib/outputlib.php
lib/outputrenderers.php
lib/pagelib.php
lib/templates/settings_link_page.mustache [new file with mode: 0644]
lib/templates/settings_link_page_single.mustache [moved from lib/templates/prevent_form_autofill_password.mustache with 57% similarity]
lib/templates/signup_form_layout.mustache [new file with mode: 0644]
lib/tests/accesslib_test.php
lib/tests/behat/behat_general.php
lib/tests/behat/behat_permissions.php
lib/upgrade.txt
lib/weblib.php
login/signup.php
login/signup_form.php
login/tests/behat/change_password.feature
message/amd/build/message_area_contacts.min.js
message/amd/build/message_area_profile.min.js
message/amd/src/message_area_contacts.js
message/amd/src/message_area_profile.js
message/classes/api.php
message/classes/helper.php
message/output/popup/amd/build/notification_area_control_area.min.js
message/output/popup/amd/src/notification_area_control_area.js
message/tests/api_test.php
message/tests/events_test.php
message/tests/messagelib_test.php
mod/assign/amd/build/grading_panel.min.js
mod/assign/amd/src/grading_panel.js
mod/assign/feedback/editpdf/tests/behat/annotate_pdf.feature
mod/assign/feedback/file/tests/behat/feedback_file.feature
mod/assign/gradingtable.php
mod/assign/styles.css
mod/assign/tests/behat/edit_student_submission.feature
mod/assign/tests/behat/outcome_grading.feature
mod/assign/tests/behat/quickgrading.feature
mod/assign/tests/behat/steps_blind_marking.feature
mod/assign/tests/locallib_test.php
mod/data/tests/behat/view_entries.feature
mod/feedback/tests/behat/anonymous.feature
mod/feedback/tests/behat/coursemapping.feature
mod/feedback/tests/behat/export_import.feature
mod/feedback/tests/behat/groups.feature
mod/feedback/tests/behat/multichoice.feature
mod/feedback/tests/behat/non_anonymous.feature
mod/feedback/tests/behat/question_types.feature
mod/feedback/tests/behat/question_types_non_anon.feature
mod/feedback/tests/behat/show_nonrespondents.feature
mod/feedback/tests/behat/templates.feature
mod/forum/tests/behat/advanced_search.feature
mod/forum/tests/behat/edit_post_student.feature
mod/lesson/tests/behat/duplicate_lesson_page.feature
mod/lesson/tests/behat/lesson_group_override.feature
mod/lesson/tests/behat/lesson_practice.feature
mod/lesson/tests/behat/lesson_user_override.feature
mod/lesson/tests/behat/questions_images.feature
mod/quiz/tests/behat/editing_repaginate.feature
mod/quiz/tests/behat/settings_form_fields_disableif.feature
mod/wiki/tests/behat/page_history.feature
mod/workshop/tests/behat/embedded_images.feature
notes/index.php
pix/t/passwordunmask-edit.png [new file with mode: 0644]
pix/t/passwordunmask-edit.svg [new file with mode: 0644]
pix/t/passwordunmask-reveal.png [new file with mode: 0644]
pix/t/passwordunmask-reveal.svg [new file with mode: 0644]
report/log/tests/behat/filter_log.feature
report/log/tests/behat/user_log.feature
report/outline/tests/behat/user.feature
repository/filepicker.php
tag/tests/behat/collections.feature
tag/tests/behat/standard_tags.feature
theme/boost/amd/build/drawer.min.js [new file with mode: 0644]
theme/boost/amd/src/drawer.js [new file with mode: 0644]
theme/boost/classes/output/core/files_renderer.php
theme/boost/classes/output/core_renderer.php
theme/boost/config.php
theme/boost/lang/en/theme_boost.php
theme/boost/layout/columns1.php
theme/boost/layout/columns2.php
theme/boost/layout/login.php [new file with mode: 0644]
theme/boost/layout/secure.php
theme/boost/pix/blocksdrawer.png [new file with mode: 0644]
theme/boost/pix/blocksdrawer.svg [new file with mode: 0644]
theme/boost/scss/moodle.scss
theme/boost/scss/moodle/backup-restore.scss
theme/boost/scss/moodle/blocks.scss
theme/boost/scss/moodle/bootswatch.scss [new file with mode: 0644]
theme/boost/scss/moodle/core.scss
theme/boost/scss/moodle/course.scss
theme/boost/scss/moodle/debug.scss
theme/boost/scss/moodle/drawer.scss [new file with mode: 0644]
theme/boost/scss/moodle/grade.scss
theme/boost/scss/moodle/icons.scss
theme/boost/scss/moodle/login.scss [new file with mode: 0644]
theme/boost/scss/moodle/message.scss
theme/boost/scss/moodle/modules.scss
theme/boost/scss/moodle/sticky-footer.scss
theme/boost/scss/moodle/user.scss
theme/boost/scss/preset-default.scss
theme/boost/templates/blocks-drawer.mustache [new file with mode: 0644]
theme/boost/templates/columns1.mustache
theme/boost/templates/columns2.mustache
theme/boost/templates/core/block.mustache
theme/boost/templates/core/filemanager_loginform.mustache
theme/boost/templates/core/login.mustache
theme/boost/templates/core/navbar.mustache
theme/boost/templates/core/signup_form_layout.mustache [new file with mode: 0644]
theme/boost/templates/core_admin/setting_configpasswordunmask.mustache
theme/boost/templates/core_admin/settings.mustache
theme/boost/templates/core_admin/settings_search_results.mustache
theme/boost/templates/core_form/element-advcheckbox-inline.mustache
theme/boost/templates/core_form/element-advcheckbox.mustache
theme/boost/templates/core_form/element-autocomplete-inline.mustache
theme/boost/templates/core_form/element-autocomplete.mustache
theme/boost/templates/core_form/element-checkbox-inline.mustache
theme/boost/templates/core_form/element-checkbox.mustache
theme/boost/templates/core_form/element-passwordunmask.mustache
theme/boost/templates/core_form/element-select-inline.mustache
theme/boost/templates/core_form/element-select.mustache
theme/boost/templates/core_form/element-text-inline.mustache
theme/boost/templates/core_form/element-text.mustache
theme/boost/templates/core_form/element-url.mustache
theme/boost/templates/custom_menu_footer.mustache [new file with mode: 0644]
theme/boost/templates/flat_navigation.mustache [new file with mode: 0644]
theme/boost/templates/header.mustache
theme/boost/templates/login.mustache [new file with mode: 0644]
theme/boost/templates/maintenance.mustache
theme/boost/templates/nav-drawer.mustache [new file with mode: 0644]
theme/boost/templates/secure.mustache
theme/boost/tests/behat/behat_theme_boost_behat_course.php
theme/boost/tests/behat/behat_theme_boost_behat_navigation.php
theme/boost/tests/behat/blacklist.json
theme/bootstrapbase/less/moodle/debug.less
theme/bootstrapbase/less/moodle/forms.less
theme/bootstrapbase/less/moodle/message.less
theme/bootstrapbase/style/moodle.css
theme/upgrade.txt
user/profile.php
user/tests/behat/name_fields.feature
user/tests/behat/user_grade_navigation.feature
user/tests/behat/view_full_profile.feature
user/tests/behat/view_preferences_page.feature
version.php

diff --git a/admin/admin_settings_search_form.php b/admin/admin_settings_search_form.php
new file mode 100644 (file)
index 0000000..ad42300
--- /dev/null
@@ -0,0 +1,48 @@
+<?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/>.
+
+/**
+ * Admin settings search form
+ *
+ * @package    admin
+ * @copyright  2016 Damyon Wiese
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once $CFG->libdir.'/formslib.php';
+
+/**
+ * Admin settings search form
+ *
+ * @package    admin
+ * @copyright  2016 Damyon Wiese
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class admin_settings_search_form extends moodleform {
+    function definition () {
+        $mform = $this->_form;
+
+        //$mform->addElement('header', 'settingsheader', get_string('search', 'admin'));
+        $elements = [];
+        $elements[] = $mform->createElement('text', 'query', get_string('query', 'admin'));
+        $elements[] = $mform->createElement('submit', 'search', get_string('search'));
+        $mform->addGroup($elements);
+        $mform->setType('query', PARAM_RAW);
+        $mform->setDefault('query', optional_param('query', '', PARAM_RAW));
+    }
+}
index 1fe945b..b307cd7 100644 (file)
@@ -64,8 +64,6 @@ echo "<form id=\"authmenu\" method=\"post\" action=\"auth_config.php\">\n";
 echo "<div>\n";
 echo "<input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />\n";
 echo "<input type=\"hidden\" name=\"auth\" value=\"".$auth."\" />\n";
-// HACK to prevent browsers from automatically inserting the user's password into the wrong fields.
-echo prevent_form_autofill_password();
 
 // auth plugin description
 echo $OUTPUT->box_start();
index 6c255c6..0e9a531 100644 (file)
@@ -36,6 +36,8 @@ if ($data = data_submitted() and confirm_sesskey()) {
 // to modify them
 echo $OUTPUT->header($focus);
 
+echo $OUTPUT->heading(get_string('administrationsite'));
+
 if ($errormsg !== '') {
     echo $OUTPUT->notification($errormsg);
 
@@ -43,6 +45,18 @@ if ($errormsg !== '') {
     echo $OUTPUT->notification($statusmsg, 'notifysuccess');
 }
 
-echo admin_search_settings_html($query);
+require_once("admin_settings_search_form.php");
+$form = new admin_settings_search_form();
+$form->display();
+echo '<hr>';
+
+if ($query) {
+    echo admin_search_settings_html($query);
+} else {
+    $node = $PAGE->settingsnav->find('root', navigation_node::TYPE_SITE_ADMIN);
+    if ($node) {
+        echo $OUTPUT->render_from_template('core/settings_link_page', ['node' => $node]);
+    }
+}
 
 echo $OUTPUT->footer();
index f2047d8..7ee3f70 100644 (file)
@@ -172,7 +172,6 @@ preferences,moodle|/user/preferences.php|preferences',
     $temp->add(new admin_setting_configcheckbox('navshowcategories', new lang_string('navshowcategories', 'admin'), new lang_string('confignavshowcategories', 'admin'), 1));
     $temp->add(new admin_setting_configcheckbox('navshowmycoursecategories', new lang_string('navshowmycoursecategories', 'admin'), new lang_string('navshowmycoursecategories_help', 'admin'), 0));
     $temp->add(new admin_setting_configcheckbox('navshowallcourses', new lang_string('navshowallcourses', 'admin'), new lang_string('confignavshowallcourses', 'admin'), 0));
-    $temp->add(new admin_setting_configcheckbox('navexpandmycourses', new lang_string('navexpandmycourses', 'admin'), new lang_string('navexpandmycourses_desc', 'admin'), 1));
     $sortoptions = array(
         'sortorder' => new lang_string('sort_sortorder', 'admin'),
         'fullname' => new lang_string('sort_fullname', 'admin'),
index 223af0c..59a6102 100644 (file)
@@ -47,4 +47,4 @@ $ADMIN->add('root', new admin_category('development', new lang_string('developme
 $ADMIN->add('root', new admin_category('unsupported', new lang_string('unsupported', 'admin'), true));
 
 // hidden search script
-$ADMIN->add('root', new admin_externalpage('search', new lang_string('searchresults'), "$CFG->wwwroot/$CFG->admin/search.php", 'moodle/site:config', true));
+$ADMIN->add('root', new admin_externalpage('search', new lang_string('search', 'admin'), "$CFG->wwwroot/$CFG->admin/search.php", 'moodle/site:config', true));
index b9da812..bf00ea7 100644 (file)
     }
 }}
 <div class="form-password">
-    <input type="password" name="{{name}}" size="{{size}}" id="{{id}}" value="{{value}}">
-    <div class="unmask" id="{{id}}unmaskdiv"></div>
+    <span data-passwordunmask="wrapper" data-passwordunmaskid="{{ id }}">
+        <noscript>
+            <!-- Backwards compatability for Behat -->
+            <input  type="password"
+                    name="{{ name }}"
+                    id="{{ id }}"
+                    value="{{ value }}"
+                    size="{{ size }}"
+                    >
+        </noscript>
+        <span class="visibleifjs">
+            <span data-passwordunmask="editor">
+                <!-- The input in the noscript will be moved here as part of the page load -->
+            </span>
+            <a href="#" data-passwordunmask="edit" title="{{ edithint }}">
+                <span data-passwordunmask="displayvalue">{{> core_form/element-passwordunmask-fill }}</span>
+                {{# pix }} t/passwordunmask-edit, core, {{# str }} passwordunmaskedithint, form {{/ str }}{{/ pix }}
+            </a>
+            <a href="#" data-passwordunmask="unmask" title="{{ unmaskhint }}">
+                {{# pix }} t/passwordunmask-reveal, core, {{# str }} passwordunmaskrevealhint, form {{/ str }}{{/ pix }}
+            </a>
+            <span data-passwordunmask="instructions" class="form-text text-muted" style="display: none;">
+                {{# str }} passwordunmaskinstructions, form {{/ str }}
+            </span>
+        </span>
+    </span>
 </div>
 {{#js}}
-(function() {
-    var id = '{{id}}';
-    var unmaskid = id + 'unmask';
-    var unmaskdivid = id + 'unmaskdiv';
-    var unmaskstr = {{#quote}}{{#str}}unmaskpassword, form{{/str}}{{/quote}};
-    var is_ie = (navigator.userAgent.toLowerCase().indexOf("msie") != -1);
-
-    document.getElementById(id).setAttribute("autocomplete", "off");
-
-    var unmaskdiv = document.getElementById(unmaskdivid);
-
-    var unmaskchb = document.createElement("input");
-    unmaskchb.setAttribute("type", "checkbox");
-    unmaskchb.setAttribute("id", unmaskid);
-    unmaskchb.onchange = function() {unmaskPassword(id);};
-    unmaskdiv.appendChild(unmaskchb);
-
-    var unmasklbl = document.createElement("label");
-    unmasklbl.innerHTML = unmaskstr;
-    if (is_ie) {
-      unmasklbl.setAttribute("htmlFor", unmaskid);
-    } else {
-      unmasklbl.setAttribute("for", unmaskid);
-    }
-    unmaskdiv.appendChild(unmasklbl);
-
-    if (is_ie) {
-      // Ugly hack to work around the famous onchange IE bug.
-      unmaskchb.onclick = function() {this.blur();};
-      unmaskdiv.onclick = function() {this.blur();};
-    }
-})()
+require(['core_form/passwordunmask'], function(PasswordUnmask) {
+    new PasswordUnmask("{{ id }}");
+});
 {{/js}}
index aba6601..4f351b8 100644 (file)
@@ -43,7 +43,6 @@
         {{/params}}
         <input type="hidden" name="sesskey" value="{{sesskey}}">
         <input type="hidden" name="return" value="{{return}}">
-        {{>core/prevent_form_autofill_password}}
         {{#title}}
             <h2>{{title}}</h2>
         {{/title}}
index dd392f7..c6f7bbb 100644 (file)
@@ -37,7 +37,6 @@
 <form action="{{actionurl}}" method="post" id="adminsettings">
     <div>
         <input type="hidden" name="sesskey" value="{{sesskey}}">
-        {{>core/prevent_form_autofill_password}}
     </div>
     <fieldset>
         <div class="clearer"></div>
index cac5f63..6b6d5ed 100644 (file)
@@ -325,7 +325,7 @@ Feature: Set up contextual data for tests
     And I am on site homepage
     And I follow "Courses"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     Then I should see "Grade category 1"
     And I should see "Grade sub category 2"
 
@@ -349,7 +349,7 @@ Feature: Set up contextual data for tests
     When I log in as "admin"
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I expand "Setup" node
     And I follow "Gradebook setup"
     Then I should see "Test Grade Item 1"
@@ -380,7 +380,7 @@ Feature: Set up contextual data for tests
     When I log in as "admin"
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I follow "Scales"
     Then I should see "Test Scale 1"
     And I should see "Disappointing,  Good,  Very good,  Excellent"
@@ -432,7 +432,7 @@ Feature: Set up contextual data for tests
     When I log in as "admin"
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I expand "Setup" node
     And I follow "Gradebook setup"
     Then I should see "Test Outcome Grade Item 1"
index 29f7981..b07c121 100644 (file)
@@ -52,13 +52,13 @@ Feature: Edit capabilities
       | Forum name | I'm the name |
       | Description | I'm the introduction |
     And I follow "I'm the name"
-    And I follow "Permissions"
+    And I navigate to "Permissions" node in "Forum administration"
     And I override the system permissions of "Student" role with:
       | mod/forum:deleteanypost | Prohibit |
       | mod/forum:editanypost | Prevent |
       | mod/forum:addquestion | Allow |
     When I set the field "Advanced role override" to "Student (3)"
-    And I press "Go"
+    And I click on "Go" "button" in the "region-main" "region"
     Then "mod/forum:deleteanypost" capability has "Prohibit" permission
     And "mod/forum:editanypost" capability has "Prevent" permission
     And "mod/forum:addquestion" capability has "Allow" permission
index ca4f2a1..9edf445 100644 (file)
@@ -37,7 +37,7 @@ Feature: Verify that all form fields values can be get and set
     And I expand "Appearance" node
     And I am on site homepage
     And I follow "Course 1"
-    And I follow "Reset"
+    And I navigate to "Reset" node in "Course administration"
     # Select (multi-select) - Checking "the select box should contain".
     And I expand all fieldsets
     And the "Unenrol users" select box should contain "No roles"
index 126a800..b2524fb 100644 (file)
@@ -8,7 +8,7 @@ Feature: Forms manipulation
   Scenario: Basic forms manipulation
     Given I log in as "admin"
     And I follow "Preferences" in the user menu
-    And I follow "Edit profile"
+    And I click on "Edit profile" "link" in the "region-main" "region"
     When I set the field "First name" to "Field value"
     And I set the field "Select a country" to "Japan"
     And I set the field "Unmask" to "1"
index f8d847d..1c54765 100644 (file)
@@ -11,14 +11,14 @@ Feature: Transform steps arguments
       | Course 1 | C1 | 0 |
     And I log in as "admin"
     And I follow "Preferences" in the user menu
-    And I follow "Edit profile"
+    And I click on "Edit profile" "link" in the "region-main" "region"
 
   Scenario: Use nasty strings on steps arguments
     When I set the field "Surname" to "$NASTYSTRING1"
     And I set the field "Description" to "$NASTYSTRING2"
     And I set the field "City/town" to "$NASTYSTRING3"
     And I press "Update profile"
-    And I follow "Edit profile"
+    And I click on "Edit profile" "link" in the "region-main" "region"
     Then I should not see "NASTYSTRING"
     And the field "Surname" matches value "$NASTYSTRING1"
     And the field "City/town" matches value "$NASTYSTRING3"
@@ -29,7 +29,7 @@ Feature: Transform steps arguments
       | Description | $NASTYSTRING2 |
       | City/town | $NASTYSTRING3 |
     And I press "Update profile"
-    And I follow "Edit profile"
+    And I click on "Edit profile" "link" in the "region-main" "region"
     Then I should not see "NASTYSTRING"
     # BEHAT Transformation regression - See MDL-56397
     #And the field "Surname" matches value "$NASTYSTRING1"
@@ -41,7 +41,7 @@ Feature: Transform steps arguments
       | Description | va\"lue2 |
     And I set the field "City/town" to "va\"lue3"
     And I press "Update profile"
-    And I follow "Edit profile"
+    And I click on "Edit profile" "link" in the "region-main" "region"
     Then I should not see "NASTYSTRING"
     And the field "First name" matches value "va\"lue1"
     And the field "Description" matches value "va\\"lue2"
@@ -52,7 +52,7 @@ Feature: Transform steps arguments
     And I set the following fields to these values:
       | Surname | My Surname $NASTYSTRING2 |
     And I press "Update profile"
-    And I follow "Edit profile"
+    And I click on "Edit profile" "link" in the "region-main" "region"
     Then I should not see "NASTYSTRING"
     And I should see "My Firstname"
     And I should see "My Surname"
index 62b6892..7f1ba9c 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
-/**
- * This function extends the course navigation
- *
- * @param navigation_node $navigation The navigation node to extend
- * @param stdClass $course The course to object for the tool
- * @param context $coursecontext The context of the course
- */
-function tool_lp_extend_navigation_course($navigation, $course, $coursecontext) {
-    if (!get_config('core_competency', 'enabled')) {
-        return;
-    }
-
-    // Check access to the course and competencies page.
-    $capabilities = array('moodle/competency:coursecompetencyview', 'moodle/competency:coursecompetencymanage');
-    $context = context_course::instance($course->id);
-    if (!has_any_capability($capabilities, $context) || !can_access_course($course)) {
-        return;
-    }
-
-    // Just a link to course competency.
-    $title = get_string('competencies', 'core_competency');
-    $path = new moodle_url("/admin/tool/lp/coursecompetencies.php", array('courseid' => $course->id));
-    $settingsnode = navigation_node::create($title,
-                                            $path,
-                                            navigation_node::TYPE_SETTING,
-                                            null,
-                                            null,
-                                            new pix_icon('i/competencies', ''));
-    if (isset($settingsnode)) {
-        $navigation->add_node($settingsnode);
-    }
-}
-
-
 /**
  * This function extends the user navigation.
  *
index 4ebd5c9..779ece3 100644 (file)
@@ -41,6 +41,7 @@ Feature: Manage competencies linked to evidence of prior learning
 
   Scenario: Link competency to evidence of prior learning from list
     Given I follow "Evidence of prior learning"
+    And I change window size to "large"
     And I should see "List of evidence"
     And I should see "Test-Evidence"
     And I click on "Link" of edit menu in the "Test-Evidence" row
index bcf2ff6..4b29277 100644 (file)
@@ -147,7 +147,7 @@ Feature: tool_monitor_subscriptions
     When I follow "Event monitoring"
     And I set the field "Select a course" to "Course 1"
     Then I should see "You can manage rules from the Event monitoring rules page."
-    And I follow "Event monitoring rules"
+    And I click on "Event monitoring rules" "link" in the "region-main" "region"
     And I should see "You can subscribe to rules from the Event monitoring page."
     And I log out
     And I log in as "teacher1"
@@ -155,7 +155,7 @@ Feature: tool_monitor_subscriptions
     And I follow "Event monitoring"
     And I set the field "Select a course" to "Course 1"
     And I should see "You can manage rules from the Event monitoring rules page."
-    And I follow "Event monitoring rules"
+    And I click on "Event monitoring rules" "link" in the "region-main" "region"
     And I should see "You can subscribe to rules from the Event monitoring page."
     And I click on "//a[text()='Event monitoring']" "xpath_element"
     And the field "courseid" matches value "Course 1"
index 7c20c3e..500a273 100644 (file)
@@ -58,12 +58,12 @@ Feature: Backup user data
     And I follow "Course 1"
     And I turn editing mode on
     And I delete "Quiz 1" activity
-    And I follow "Recycle bin"
+    And I navigate to "Recycle bin" node in "Course administration"
     And I should see "Quiz 1"
-    And I follow "Restore"
+    And I click on "Restore" "link" in the "region-main" "region"
     And I log out
     And I log in as "student1"
     And I follow "Course 1"
-    When I navigate to "Grades" node in "Course administration"
+    When I click on "Grades" "link" in the "Navigation" "block"
     Then "Quiz 1" row "Grade" column of "user-grade" table should contain "5"
     And "Quiz 1" row "Percentage" column of "user-grade" table should contain "50"
index 85e5d57..ded5e99 100644 (file)
@@ -31,10 +31,10 @@ Feature: Basic recycle bin functionality
       | Assignment name | Test assign |
       | Description | Test |
     And I delete "Test assign" activity
-    When I follow "Recycle bin"
+    When I navigate to "Recycle bin" node in "Course administration"
     Then I should see "Test assign"
     And I should see "Contents will be permanently deleted after 7 days"
-    And I follow "Restore"
+    And I click on "Restore" "link" in the "region-main" "region"
     And I should see "'Test assign' has been restored"
     And I wait to be redirected
     And I am on homepage
@@ -51,10 +51,10 @@ Feature: Basic recycle bin functionality
     And I press "Continue"
     And I go to the courses management page
     And I should not see "Course 2" in the "#course-listing" "css_element"
-    When I follow "Recycle bin"
+    When I navigate to "Recycle bin" node in "Category: Miscellaneous"
     Then I should see "Course 2"
     And I should see "Contents will be permanently deleted after 14 days"
-    And I follow "Restore"
+    And I click on "Restore" "link" in the "region-main" "region"
     And I should see "'Course 2' has been restored"
     And I wait to be redirected
     And I go to the courses management page
@@ -69,7 +69,7 @@ Feature: Basic recycle bin functionality
       | Assignment name | Test assign |
       | Description | Test |
     And I delete "Test assign" activity
-    And I follow "Recycle bin"
+    And I navigate to "Recycle bin" node in "Course administration"
     When I click on "Delete" "link"
     Then I should see "Are you sure you want to delete the selected item from the recycle bin?"
     And I press "Cancel"
@@ -92,7 +92,7 @@ Feature: Basic recycle bin functionality
       | Description | Test 2 |
     And I delete "Test assign 1" activity
     And I delete "Test assign 2" activity
-    And I follow "Recycle bin"
+    And I navigate to "Recycle bin" node in "Course administration"
     And I should see "Test assign 1"
     And I should see "Test assign 2"
     When I click on "Delete all" "link"
index 2a58fee..2f37014 100644 (file)
Binary files a/admin/tool/usertours/amd/build/tour.min.js and b/admin/tool/usertours/amd/build/tour.min.js differ
index 46a0e19..1f7d0c6 100644 (file)
@@ -722,7 +722,11 @@ Tour.prototype.addStepToPage = function (stepConfig) {
     var animationTarget = $('body, html').stop(true, true);
 
     if (this.isStepActuallyVisible(stepConfig)) {
-        var zIndex = this.calculateZIndex(this.getStepTarget(stepConfig));
+        var targetNode = this.getStepTarget(stepConfig);
+
+        targetNode.data('flexitour', 'target');
+
+        var zIndex = this.calculateZIndex(targetNode);
         if (zIndex) {
             stepConfig.zIndex = zIndex + 1;
         }
@@ -774,6 +778,7 @@ Tour.prototype.addStepToPage = function (stepConfig) {
         this.currentStepNode.offset(this.calculateStepPositionInPage());
 
         this.currentStepPopper = new Popper($('body'), this.currentStepNode[0], {
+            removeOnDestroy: true,
             placement: stepConfig.placement + '-start',
             arrowElement: '[data-role="arrow"]',
             // Empty the modifiers. We've already placed the step and don't want it moved.
@@ -847,6 +852,8 @@ Tour.prototype.announceStep = function (stepConfig) {
         target.data('original-describedby', target.attr('aria-describedby')).attr('aria-describedby', stepId + '-body');
     }
 
+    this.accessibilityShow(stepConfig);
+
     return this;
 };
 
@@ -1036,6 +1043,8 @@ Tour.prototype.hide = function (transition) {
     // Reset the listeners.
     this.resetStepListeners();
 
+    this.accessibilityHide();
+
     this.fireEventHandlers('afterHide');
 
     this.currentStepNode = null;
@@ -1372,6 +1381,50 @@ Tour.prototype.centerPopper = function (data) {
     return data;
 };
 
+Tour.prototype.accessibilityShow = function (stepConfig) {
+    var stateHolder = 'data-has-hidden';
+    var attrName = 'aria-hidden';
+    var hideFunction = function hideFunction(child) {
+        var flexitourRole = child.data('flexitour');
+        if (flexitourRole) {
+            switch (flexitourRole) {
+                case 'container':
+                case 'target':
+                    return;
+            }
+        }
+
+        var hidden = child.attr(attrName);
+        if (!hidden) {
+            child.attr(stateHolder, true);
+            child.attr(attrName, true);
+        }
+    };
+
+    this.currentStepNode.siblings().each(function (index, node) {
+        hideFunction($(node));
+    });
+    this.currentStepNode.parentsUntil('body').siblings().each(function (index, node) {
+        hideFunction($(node));
+    });
+};
+
+Tour.prototype.accessibilityHide = function () {
+    var stateHolder = 'data-has-hidden';
+    var attrName = 'aria-hidden';
+    var showFunction = function showFunction(child) {
+        var hidden = child.attr(stateHolder);
+        if (typeof hidden !== 'undefined') {
+            child.removeAttr(stateHolder);
+            child.removeAttr(attrName);
+        }
+    };
+
+    $('[' + stateHolder + ']').each(function (index, node) {
+        showFunction($(node));
+    });
+};
+
 if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') {
     module.exports = Tour;
 }
diff --git a/admin/tool/usertours/classes/cache.php b/admin/tool/usertours/classes/cache.php
new file mode 100644 (file)
index 0000000..6c81a0a
--- /dev/null
@@ -0,0 +1,135 @@
+<?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/>.
+
+/**
+ * Cache manager.
+ *
+ * @package    tool_usertours
+ * @copyright  2016 Andrew Nicols <andrew@nicols.co.uk>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace tool_usertours;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Cache manager.
+ *
+ * @copyright  2016 Andrew Nicols <andrew@nicols.co.uk>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class cache {
+    /**
+     * @var CACHENAME_TOUR      The name of the cache used for storing tours.
+     */
+    const CACHENAME_TOUR = 'tourdata';
+
+    /**
+     * @var CACHEKEY_TOUR       The name of the key used for storing tours.
+     */
+    const CACHEKEY_TOUR = 'tours';
+
+    /**
+     * @var CACHENAME_STEP      The name of the cache used for storing steps.
+     */
+    const CACHENAME_STEP = 'stepdata';
+
+    /**
+     * Fetch all enabled tours.
+     */
+    public static function get_enabled_tourdata() {
+        global $DB;
+
+        $cache = \cache::make('tool_usertours', self::CACHENAME_TOUR);
+
+        $data = $cache->get(self::CACHEKEY_TOUR);
+        if ($data === false) {
+            $sql = <<<EOF
+                SELECT t.*
+                  FROM {tool_usertours_tours} t
+            INNER JOIN {tool_usertours_steps} s ON s.tourid = t.id
+                 WHERE t.enabled = 1
+              GROUP BY t.id
+                HAVING COUNT(s.id) > 0
+              ORDER BY t.sortorder ASC
+EOF;
+
+            $data = $DB->get_records_sql($sql);
+            $cache->set('tours', $data);
+        }
+
+        return $data;
+    }
+
+    /**
+     * Fetch all enabled tours matching the specified target.
+     *
+     * @param   string      $targetmatch    The URL to match.
+     */
+    public static function get_matching_tourdata($targetmatch) {
+        $tours = self::get_enabled_tourdata();
+
+        return array_filter($tours, function($tour) use ($targetmatch) {
+            $pattern = preg_quote($tour->pathmatch, '@');
+            $pattern = str_replace('%', '.*', $pattern);
+            return !!preg_match("@{$pattern}@", $targetmatch);
+        });
+    }
+
+    /**
+     * Notify of changes to any tour to clear the tour cache.
+     */
+    public static function notify_tour_change() {
+        $cache = \cache::make('tool_usertours', self::CACHENAME_TOUR);
+        $cache->delete(self::CACHEKEY_TOUR);
+    }
+
+    /**
+     * Fetch the tour data for the specified tour.
+     *
+     * @param   int         $tourid         The ID of the tour to fetch steps for
+     */
+    public static function get_stepdata($tourid) {
+        global $DB;
+
+        $cache = \cache::make('tool_usertours', self::CACHENAME_STEP);
+
+        $data = $cache->get($tourid);
+        if ($data === false) {
+            $sql = <<<EOF
+                SELECT s.*
+                  FROM {tool_usertours_steps} s
+                 WHERE s.tourid = :tourid
+              ORDER BY s.sortorder ASC
+EOF;
+
+            $data = $DB->get_records_sql($sql, ['tourid' => $tourid]);
+            $cache->set($tourid, $data);
+        }
+
+        return $data;
+    }
+    /**
+     * Notify of changes to any step to clear the step cache for that tour.
+     *
+     * @param   int         $tourid         The ID of the tour to clear the step cache for
+     */
+    public static function notify_step_change($tourid) {
+        $cache = \cache::make('tool_usertours', self::CACHENAME_STEP);
+        $cache->delete($tourid);
+    }
+}
index d27db08..ee0eb52 100644 (file)
@@ -355,6 +355,8 @@ class helper {
      * @return  string
      */
     public static function render_stepname_inplace_editable(step $step) {
+        $title = format_text(step::get_string_from_input($step->get_title()), FORMAT_HTML);
+
         return new \core\output\inplace_editable(
                 'tool_usertours',
                 'stepname',
@@ -362,9 +364,9 @@ class helper {
                 true,
                 \html_writer::link(
                     $step->get_edit_link(),
-                    $step->get_title()
+                    $title
                 ),
-                $step->get_title(false)
+                $step->get_title()
             );
     }
 
@@ -432,6 +434,11 @@ class helper {
             }
             $index++;
         }
+
+        // Notify the cache that a tour has changed.
+        // Tours are only stored in the cache if there are steps.
+        // If there step count has changed for some reason, this will change the potential cache results.
+        cache::notify_tour_change();
     }
 
 
@@ -442,11 +449,8 @@ class helper {
      * @return  stdClass[]
      */
     public static function get_steps($tourid) {
-        global $DB;
-
-        $order = 'sortorder ASC';
+        $steps = cache::get_stepdata($tourid);
 
-        $steps = $DB->get_records('tool_usertours_steps', array('tourid' => $tourid), $order);
         $return = [];
         foreach ($steps as $step) {
             $return[$step->id] = step::load_from_record($step);
index 2afafb8..a37127f 100644 (file)
@@ -96,7 +96,7 @@ class step_list extends \flexible_table {
      * @return  string
      */
     protected function col_content(step $step) {
-        return $step->get_content(false);
+        return format_text(step::get_string_from_input($step->get_content()), FORMAT_HTML);
     }
 
     /**
index 2362ac2..d9589fc 100644 (file)
@@ -559,22 +559,14 @@ class manager {
      * @return  tour
      */
     public static function get_matching_tours(\moodle_url $pageurl) {
-        global $DB, $PAGE;
+        global $PAGE;
 
-        $sql = <<<EOF
-            SELECT * FROM {tool_usertours_tours}
-             WHERE enabled = 1
-               AND ? LIKE pathmatch
-          ORDER BY sortorder ASC
-EOF;
 
-        $tours = $DB->get_records_sql($sql, array(
-            $pageurl->out_as_local_url(),
-        ));
+        $tours = cache::get_matching_tourdata($pageurl->out_as_local_url());
 
         foreach ($tours as $record) {
             $tour = tour::load_from_record($record);
-            if ($tour->is_enabled() && $tour->matches_all_filters($PAGE->context) && $tour->count_steps() > 0) {
+            if ($tour->is_enabled() && $tour->matches_all_filters($PAGE->context)) {
                 return $tour;
             }
         }
index 3da0d09..772edd0 100644 (file)
@@ -63,26 +63,16 @@ class step implements \renderable {
         $result = (object) [
             'stepid'    => $step->get_id(),
             'title'     => external_format_text(
-                    static::get_string_from_input($step->get_title()),
+                    stepsource::get_string_from_input($step->get_title()),
                     FORMAT_HTML,
                     $PAGE->context->id,
-                    'tool_usertours',
-                    null,
-                    null,
-                    [
-                        'filter' => true,
-                    ]
+                    'tool_usertours'
                 )[0],
             'content'   => external_format_text(
-                    static::get_string_from_input($step->get_content()),
+                    stepsource::get_string_from_input($step->get_content()),
                     FORMAT_HTML,
                     $PAGE->context->id,
-                    'tool_usertours',
-                    null,
-                    null,
-                    [
-                        'filter' => true,
-                    ]
+                    'tool_usertours'
                 )[0],
             'element'   => $step->get_target()->convert_to_css(),
         ];
@@ -95,27 +85,4 @@ class step implements \renderable {
 
         return $result;
     }
-
-    /**
-     * Attempt to fetch any matching langstring if the string is in the
-     * format identifier,component.
-     *
-     * @param   string  $string
-     * @return  string
-     */
-    protected static function get_string_from_input($string) {
-        $string = trim($string);
-
-        if (preg_match('|^([a-zA-Z][a-zA-Z0-9\.:/_-]*),([a-zA-Z][a-zA-Z0-9\.:/_-]*)$|', $string, $matches)) {
-            if ($matches[2] === 'moodle') {
-                $matches[2] = 'core';
-            }
-
-            if (get_string_manager()->string_exists($matches[1], $matches[2])) {
-                $string = get_string($matches[1], $matches[2]);
-            }
-        }
-
-        return $string;
-    }
 }
index b30fccd..6049e8f 100644 (file)
@@ -216,7 +216,7 @@ class step {
      * @return  $this
      */
     public function set_title($value) {
-        $this->title = clean_param($value, PARAM_TEXT);
+        $this->title = clean_text($value);
         $this->dirty = true;
 
         return $this;
@@ -485,8 +485,19 @@ class step {
             $this->id = $DB->insert_record('tool_usertours_steps', $record);
         }
 
+        $this->get_tour()->reset_step_sortorder();
+
         $this->reload();
 
+        // Notify of a change to the step configuration.
+        // This must be done separately to tour change notifications.
+        cache::notify_step_change($this->get_tourid());
+
+        // Notify the cache that a tour has changed.
+        // Tours are only stored in the cache if there are steps.
+        // If there step count has changed for some reason, this will change the potential cache results.
+        cache::notify_tour_change();
+
         return $this;
     }
 
@@ -502,6 +513,15 @@ class step {
 
         $DB->delete_records('tool_usertours_steps', array('id' => $this->id));
         $this->get_tour()->reset_step_sortorder();
+
+        // Notify of a change to the step configuration.
+        // This must be done separately to tour change notifications.
+        cache::notify_step_change($this->get_id());
+
+        // Notify the cache that a tour has changed.
+        // Tours are only stored in the cache if there are steps.
+        // If there step count has changed for some reason, this will change the potential cache results.
+        cache::notify_tour_change();
     }
 
     /**
@@ -630,4 +650,27 @@ class step {
 
         return $this;
     }
+
+    /**
+     * Attempt to fetch any matching langstring if the string is in the
+     * format identifier,component.
+     *
+     * @param   string  $string
+     * @return  string
+     */
+    public static function get_string_from_input($string) {
+        $string = trim($string);
+
+        if (preg_match('|^([a-zA-Z][a-zA-Z0-9\.:/_-]*),([a-zA-Z][a-zA-Z0-9\.:/_-]*)$|', $string, $matches)) {
+            if ($matches[2] === 'moodle') {
+                $matches[2] = 'core';
+            }
+
+            if (get_string_manager()->string_exists($matches[1], $matches[2])) {
+                $string = get_string($matches[1], $matches[2]);
+            }
+        }
+
+        return $string;
+    }
 }
index b628744..473a077 100644 (file)
@@ -523,6 +523,9 @@ class tour {
 
         $this->reload();
 
+        // Notify the cache that a tour has changed.
+        cache::notify_tour_change();
+
         return $this;
     }
 
@@ -566,6 +569,10 @@ class tour {
             $index++;
         }
 
+        // Notify of a change to the step configuration.
+        // Note: Do not notify of a tour change here. This is only a step change for a tour.
+        cache::notify_step_change($this->get_id());
+
         return $this;
     }
 
diff --git a/admin/tool/usertours/db/caches.php b/admin/tool/usertours/db/caches.php
new file mode 100644 (file)
index 0000000..3ae3c8f
--- /dev/null
@@ -0,0 +1,42 @@
+<?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/>.
+
+/**
+ * Plugin cache definitions.
+ *
+ * @package   tool_usertours
+ * @copyright 2016 Andrew Nicols <andrew@nicols.co.uk>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$definitions = array(
+    'tourdata' => array(
+        'mode' => cache_store::MODE_APPLICATION,
+        'simplekeys' => true,
+        'simpledata' => true,
+        'staticacceleration' => true,
+        'staticaccelerationsize' => 1,
+    ),
+    'stepdata' => array(
+        'mode' => cache_store::MODE_APPLICATION,
+        'simplekeys' => true,
+        'simpledata' => true,
+        'staticacceleration' => true,
+        'staticaccelerationsize' => 1,
+    ),
+);
index b26f28f..90e72ee 100644 (file)
@@ -28,6 +28,8 @@ $string['appliesto'] = 'Applies to';
 $string['below'] = 'Below';
 $string['block'] = 'Block';
 $string['block_named'] = 'Block named \'{$a}\'';
+$string['cachedef_stepdata'] = 'List of User Tour steps';
+$string['cachedef_tourdata'] = 'List of enabled User Tours information which are fetched on every page';
 $string['description'] = 'Description';
 $string['confirmstepremovalquestion'] = 'Are you sure that you wish to remove this step?';
 $string['confirmstepremovaltitle'] = 'Confirm step removal';
diff --git a/admin/tool/usertours/tests/cache_test.php b/admin/tool/usertours/tests/cache_test.php
new file mode 100644 (file)
index 0000000..fdbdde0
--- /dev/null
@@ -0,0 +1,340 @@
+<?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/>.
+
+/**
+ * Tests for cache.
+ *
+ * @package    tool_usertours
+ * @copyright  2016 Andrew Nicols <andrew@nicols.co.uk>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once(__DIR__ . '/helper_trait.php');
+
+/**
+ * Tests for cache.
+ *
+ * @package    tool_usertours
+ * @copyright  2016 Andrew Nicols <andrew@nicols.co.uk>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class cache_testcase extends advanced_testcase {
+    // There are shared helpers for these tests in the helper trait.
+    use tool_usertours_helper_trait;
+
+    /**
+     * Test that get_enabled_tourdata does not return disabled tours.
+     */
+    public function test_get_enabled_tourdata_disabled() {
+        $this->resetAfterTest();
+
+        $tour = $this->helper_create_tour((object)['enabled' => false]);
+        $this->helper_create_step((object) ['tourid' => $tour->get_id()]);
+
+        $matches = \tool_usertours\cache::get_enabled_tourdata();
+        $this->assertEmpty($matches);
+    }
+
+    /**
+     * Test that get_enabled_tourdata does not return an enabled but empty tour.
+     */
+    public function test_get_enabled_tourdata_enabled_no_steps() {
+        $this->resetAfterTest();
+
+        $this->helper_create_tour();
+
+        $matches = \tool_usertours\cache::get_enabled_tourdata();
+        $this->assertEmpty($matches);
+    }
+
+    /**
+     * Test that get_enabled_tourdata returns a tour with steps.
+     */
+    public function test_get_enabled_tourdata_enabled() {
+        $this->resetAfterTest();
+
+        // Create two tours. Only the second has steps.
+        $this->helper_create_tour();
+        $tour2 = $this->helper_create_tour();
+        $this->helper_create_step((object) ['tourid' => $tour2->get_id()]);
+
+        $matches = \tool_usertours\cache::get_enabled_tourdata();
+        $this->assertNotEmpty($matches);
+        $this->assertCount(1, $matches);
+
+        $match = array_shift($matches);
+        $this->assertEquals($tour2->get_id(), $match->id);
+    }
+
+    /**
+     * Test that get_enabled_tourdata returns tours in the correct sortorder
+     */
+    public function test_get_enabled_tourdata_enabled_sortorder() {
+        $this->resetAfterTest();
+
+        $tour1 = $this->helper_create_tour();
+        $this->helper_create_step((object) ['tourid' => $tour1->get_id()]);
+        $tour2 = $this->helper_create_tour();
+        $this->helper_create_step((object) ['tourid' => $tour2->get_id()]);
+
+        $matches = \tool_usertours\cache::get_enabled_tourdata();
+        $this->assertNotEmpty($matches);
+        $this->assertCount(2, $matches);
+
+        $match = array_shift($matches);
+        $this->assertEquals($tour1->get_id(), $match->id);
+        $match = array_shift($matches);
+        $this->assertEquals($tour2->get_id(), $match->id);
+    }
+
+    /**
+     * Test that caching prevents additional DB reads.
+     */
+    public function test_get_enabled_tourdata_single_fetch() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        $tour1 = $this->helper_create_tour();
+        $this->helper_create_step((object) ['tourid' => $tour1->get_id()]);
+        $tour2 = $this->helper_create_tour();
+        $this->helper_create_step((object) ['tourid' => $tour2->get_id()]);
+
+        // Only one read for the first call.
+        $startreads = $DB->perf_get_reads();
+        $matches = \tool_usertours\cache::get_enabled_tourdata();
+        $this->assertEquals(1, $DB->perf_get_reads() - $startreads);
+
+        // No subsequent reads for any further calls.
+        $matches = \tool_usertours\cache::get_enabled_tourdata();
+        $this->assertEquals(1, $DB->perf_get_reads() - $startreads);
+
+    }
+
+    /**
+     * Data provider for get_matching_tourdata.
+     *
+     * @return  array
+     */
+    public function get_matching_tourdata_provider() {
+        $tourconfigs = [
+            (object) [
+                'name' => 'my_exact_1',
+                'pathmatch' => '/my/view.php'
+            ],
+            (object) [
+                'name' => 'my_failed_regex',
+                'pathmatch' => '/my/*.php'
+            ],
+            (object) [
+                'name' => 'my_glob_1',
+                'pathmatch' => '/my/%'
+            ],
+            (object) [
+                'name' => 'my_glob_2',
+                'pathmatch' => '/my/%'
+            ],
+        ];
+
+        return [
+            'Matches expected glob' => [
+                $tourconfigs,
+                '/my/index.php',
+                ['my_glob_1', 'my_glob_2'],
+            ],
+            'Matches expected glob and exact' => [
+                $tourconfigs,
+                '/my/view.php',
+                ['my_exact_1', 'my_glob_1', 'my_glob_2'],
+            ],
+        ];
+    }
+
+    /**
+     * Tests for the get_matching_tourdata function.
+     *
+     * @dataProvider    get_matching_tourdata_provider
+     * @param   array   $tourconfigs    The configuration for the tours to create
+     * @param   string  $targetmatch    The match to be tested
+     * @param   array   $expected       An array containing the ordered names of the expected tours
+     */
+    public function test_get_matching_tourdata($tourconfigs, $targetmatch, $expected) {
+        $this->resetAfterTest();
+        foreach ($tourconfigs as $tourconfig) {
+            $tour = $this->helper_create_tour($tourconfig);
+            $this->helper_create_step((object) ['tourid' => $tour->get_id()]);
+        }
+
+        $matches = \tool_usertours\cache::get_matching_tourdata((new moodle_url($targetmatch))->out_as_local_url());
+        $this->assertCount(count($expected), $matches);
+
+        for ($i = 0; $i < count($matches); $i++) {
+            $match = array_shift($matches);
+            $this->assertEquals($expected[$i], $match->name);
+        }
+    }
+
+    /**
+     * Test that notify_tour_change clears the cache.
+     */
+    public function test_notify_tour_change() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        $tour1 = $this->helper_create_tour();
+        $this->helper_create_step((object) ['tourid' => $tour1->get_id()]);
+        $tour2 = $this->helper_create_tour();
+        $this->helper_create_step((object) ['tourid' => $tour2->get_id()]);
+
+        // Only one read for the first call.
+        $startreads = $DB->perf_get_reads();
+        $matches = \tool_usertours\cache::get_enabled_tourdata();
+        $this->assertEquals(1, $DB->perf_get_reads() - $startreads);
+
+        // No subsequent reads for any further calls.
+        $matches = \tool_usertours\cache::get_enabled_tourdata();
+        $this->assertEquals(1, $DB->perf_get_reads() - $startreads);
+
+        // Reset.
+        \tool_usertours\cache::notify_tour_change();
+
+        // An additional DB read now.
+        $startreads = $DB->perf_get_reads();
+        $matches = \tool_usertours\cache::get_enabled_tourdata();
+        $this->assertEquals(1, $DB->perf_get_reads() - $startreads);
+    }
+
+    /**
+     * Test that get_stepdata returns an empty array when no steps were found.
+     */
+    public function test_get_stepdata_no_steps() {
+        $this->resetAfterTest();
+
+        $tour = $this->helper_create_tour((object)['enabled' => false]);
+
+        $data = \tool_usertours\cache::get_stepdata($tour->get_id());
+        $this->assertInternalType('array', $data);
+        $this->assertEmpty($data);
+    }
+
+    /**
+     * Test that get_stepdata returns an empty array when no steps were found.
+     */
+    public function test_get_stepdata_correct_tour() {
+        $this->resetAfterTest();
+
+        $tour1 = $this->helper_create_tour((object)['enabled' => false]);
+        $this->helper_create_step((object) ['tourid' => $tour1->get_id()]);
+        $this->helper_create_step((object) ['tourid' => $tour1->get_id()]);
+        $this->helper_create_step((object) ['tourid' => $tour1->get_id()]);
+        $tour2 = $this->helper_create_tour((object)['enabled' => false]);
+
+        $data = \tool_usertours\cache::get_stepdata($tour1->get_id());
+        $this->assertInternalType('array', $data);
+        $this->assertCount(3, $data);
+
+        $data = \tool_usertours\cache::get_stepdata($tour2->get_id());
+        $this->assertInternalType('array', $data);
+        $this->assertEmpty($data);
+    }
+
+    /**
+     * Test that get_stepdata returns an array containing multiple steps in
+     * the same order.
+     *
+     * This is very difficult to determine because the act of changing the
+     * order will likely change the DB natural sorting.
+     */
+    public function test_get_stepdata_ordered_steps() {
+        $this->resetAfterTest();
+
+        $tour = $this->helper_create_tour((object)['enabled' => false]);
+        $steps = [];
+        $steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]);
+        $steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]);
+        $steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]);
+        $steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]);
+        $steps[0]->set_sortorder(10)->persist();
+
+        $data = \tool_usertours\cache::get_stepdata($tour->get_id());
+        $this->assertInternalType('array', $data);
+        $this->assertCount(4, $data);
+
+        // Re-order the steps.
+        usort($steps, function($a, $b) {
+            return ($a->get_sortorder() < $b->get_sortorder()) ? -1 : 1;
+        });
+
+        for ($i = 0; $i < count($data); $i++) {
+            $step = array_shift($data);
+            $this->assertEquals($steps[$i]->get_id(), $step->id);
+        }
+    }
+
+    /**
+     * Test that caching prevents additional DB reads.
+     */
+    public function test_get_stepdata_single_fetch() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        $tour = $this->helper_create_tour();
+        $this->helper_create_step((object) ['tourid' => $tour->get_id()]);
+
+        // Only one read for the first call.
+        $startreads = $DB->perf_get_reads();
+        $matches = \tool_usertours\cache::get_stepdata($tour->get_id());
+        $this->assertEquals(1, $DB->perf_get_reads() - $startreads);
+
+        // No subsequent reads for any further calls.
+        $matches = \tool_usertours\cache::get_stepdata($tour->get_id());
+        $this->assertEquals(1, $DB->perf_get_reads() - $startreads);
+    }
+
+    /**
+     * Test that notify_step_change clears the cache.
+     */
+    public function test_notify_step_change() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        $tour = $this->helper_create_tour();
+        $this->helper_create_step((object) ['tourid' => $tour->get_id()]);
+
+        // Only one read for the first call.
+        $startreads = $DB->perf_get_reads();
+        $matches = \tool_usertours\cache::get_stepdata($tour->get_id());
+        $this->assertEquals(1, $DB->perf_get_reads() - $startreads);
+
+        // No subsequent reads for any further calls.
+        $matches = \tool_usertours\cache::get_stepdata($tour->get_id());
+        $this->assertEquals(1, $DB->perf_get_reads() - $startreads);
+
+        // Reset.
+        \tool_usertours\cache::notify_step_change($tour->get_id());
+
+        // An additional DB read now.
+        $startreads = $DB->perf_get_reads();
+        $matches = \tool_usertours\cache::get_stepdata($tour->get_id());
+        $this->assertEquals(1, $DB->perf_get_reads() - $startreads);
+    }
+}
diff --git a/admin/tool/usertours/tests/helper_trait.php b/admin/tool/usertours/tests/helper_trait.php
new file mode 100644 (file)
index 0000000..aab15de
--- /dev/null
@@ -0,0 +1,105 @@
+<?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/>.
+
+/**
+ * Helpers for unit tests.
+ *
+ * @package    tool_usertours
+ * @copyright  2016 Andrew Nicols <andrew@nicols.co.uk>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Helpers for unit tests.
+ *
+ * @package    tool_usertours
+ * @copyright  2016 Andrew Nicols <andrew@nicols.co.uk>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+trait tool_usertours_helper_trait {
+    /**
+     * A helper to create an empty tour.
+     *
+     * @param   stdClass    $tourconfig     The configuration for the new tour
+     * @param   bool        $persist        Whether to persist the data
+     * @return  \tool_usertours\tour
+     */
+    public function helper_create_tour(\stdClass $tourconfig = null, $persist = true) {
+        $minvalues = [
+            'id' => null,
+            'pathmatch' => '/my/%',
+            'enabled' => true,
+            'name' => '',
+            'description' => '',
+            'configdata' => '',
+        ];
+
+        if ($tourconfig === null) {
+            $tourconfig = new \stdClass();
+        }
+
+        foreach ($minvalues as $key => $value) {
+            if (!isset($tourconfig->$key)) {
+                $tourconfig->$key = $value;
+            }
+        }
+
+        $tour = \tool_usertours\tour::load_from_record($tourconfig, true);
+        if ($persist) {
+            $tour->persist(true);
+        }
+
+        return $tour;
+    }
+
+    /**
+     * A helper to create an empty step for the specified tour.
+     *
+     * @param   stdClass    $stepconfig     The configuration for the new step
+     * @param   bool        $persist        Whether to persist the data
+     * @return  \tool_usertours\step
+     */
+    public function helper_create_step(\stdClass $stepconfig = null, $persist = true) {
+        $minvalues = [
+            'id' => null,
+            'title' => '',
+            'content' => '',
+            'targettype' => \tool_usertours\target::TARGET_UNATTACHED,
+            'targetvalue' => '',
+            'sortorder' => 0,
+            'configdata' => '',
+        ];
+
+        if ($stepconfig === null) {
+            $stepconfig = new \stdClass();
+        }
+
+        foreach ($minvalues as $key => $value) {
+            if (!isset($stepconfig->$key)) {
+                $stepconfig->$key = $value;
+            }
+        }
+
+        $step = \tool_usertours\step::load_from_record($stepconfig, true);
+        if ($persist) {
+            $step->persist(true);
+        }
+
+        return $step;
+    }
+}
index aa7a6bf..f32727a 100644 (file)
@@ -26,6 +26,7 @@ defined('MOODLE_INTERNAL') || die();
 
 global $CFG;
 require_once($CFG->libdir . '/formslib.php');
+require_once(__DIR__ . '/helper_trait.php');
 
 /**
  * Tests for step.
@@ -34,7 +35,9 @@ require_once($CFG->libdir . '/formslib.php');
  * @copyright  2016 Andrew Nicols <andrew@nicols.co.uk>
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class manager_testcase extends advanced_testcase {
+class tool_usertours_manager_testcase extends advanced_testcase {
+    // There are shared helpers for these tests in the helper trait.
+    use tool_usertours_helper_trait;
 
     /**
      * @var moodle_database
@@ -243,25 +246,14 @@ class manager_testcase extends advanced_testcase {
             $tourconfig->id = null;
             $tour = \tool_usertours\tour::load_from_record($tourconfig, true);
             $tour->persist(true);
-
-            $stepconfig = (object) [
-                'id' => null,
-                'tourid' => $tour->get_id(),
-                'title' => '',
-                'content' => '',
-                'targettype' => \tool_usertours\target::TARGET_UNATTACHED,
-                'targetvalue' => '',
-                'sortorder' => 0,
-                'configdata' => '',
-            ];
-            $step = \tool_usertours\step::load_from_record($stepconfig, true);
-            $step->persist(true);
+            $this->helper_create_step((object) ['tourid' => $tour->get_id()]);
         }
 
         $match = \tool_usertours\manager::get_matching_tours(new moodle_url($url));
         if ($expected === null) {
             $this->assertNull($match);
         } else {
+            $this->assertNotNull($match);
             $this->assertEquals($expected, $match->get_name());
         }
     }
@@ -289,5 +281,4 @@ class manager_testcase extends advanced_testcase {
 
         $this->assertNull(\tool_usertours\manager::get_matching_tours(new moodle_url($url)));
     }
-
 }
diff --git a/admin/tool/usertours/tests/step_output_test.php b/admin/tool/usertours/tests/step_output_test.php
deleted file mode 100644 (file)
index b14af63..0000000
+++ /dev/null
@@ -1,84 +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/>.
-
-/**
- * Tests for step.
- *
- * @package    tool_usertours
- * @copyright  2016 Andrew Nicols <andrew@nicols.co.uk>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-defined('MOODLE_INTERNAL') || die();
-
-/**
- * Tests for step.
- *
- * @package    tool_usertours
- * @copyright  2016 Andrew Nicols <andrew@nicols.co.uk>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class step_output_testcase extends advanced_testcase {
-
-    /**
-     * Data Provider for get_string_from_inpu.
-     *
-     * @return array
-     */
-    public function get_string_from_input_provider() {
-        return [
-            'Text'  => [
-                'example',
-                'example',
-            ],
-            'Text which looks like a langstring' => [
-                'example,fakecomponent',
-                'example,fakecomponent',
-            ],
-            'Text which is a langstring' => [
-                'administration,core',
-                'Administration',
-            ],
-            'Text which is a langstring but uses "moodle" instead of "core"' => [
-                'administration,moodle',
-                'Administration',
-            ],
-            'Text which is a langstring, but with extra whitespace' => [
-                '  administration,moodle  ',
-                'Administration',
-            ],
-            'Looks like a langstring, but has incorrect space around comma' => [
-                'administration , moodle',
-                'administration , moodle',
-            ],
-        ];
-    }
-
-    /**
-     * Ensure that the get_string_from_input function returns translated
-     * strings correctly.
-     *
-     * @dataProvider get_string_from_input_provider
-     * @param   string  $string     The string to test
-     * @param   string  $expected   The expected result
-     */
-    public function test_get_string_from_input($string, $expected) {
-        $rc = new ReflectionClass('\\tool_usertours\\output\\step');
-        $rcm = $rc->getMethod('get_string_from_input');
-        $rcm->setAccessible(true);
-        $this->assertEquals($expected, $rcm->invoke(null, $string));
-    }
-}
index 444d2da..005272e 100644 (file)
@@ -551,6 +551,11 @@ class step_testcase extends advanced_testcase {
         $rcp->setAccessible(true);
         $rcp->setValue($step, true);
 
+        $tour = $this->createMock(\tool_usertours\tour::class);
+        $rcp = $rc->getProperty('tour');
+        $rcp->setAccessible(true);
+        $rcp->setValue($step, $tour);
+
         $this->assertSame($step, $step->persist());
     }
 
@@ -590,6 +595,12 @@ class step_testcase extends advanced_testcase {
             ->method('reload')
             ;
 
+        $tour = $this->createMock(\tool_usertours\tour::class);
+        $rc = new \ReflectionClass(\tool_usertours\step::class);
+        $rcp = $rc->getProperty('tour');
+        $rcp->setAccessible(true);
+        $rcp->setValue($step, $tour);
+
         $this->assertSame($step, $step->persist(true));
     }
 
@@ -635,6 +646,11 @@ class step_testcase extends advanced_testcase {
         $rcp->setAccessible(true);
         $rcp->setValue($step, true);
 
+        $tour = $this->createMock(\tool_usertours\tour::class);
+        $rcp = $rc->getProperty('tour');
+        $rcp->setAccessible(true);
+        $rcp->setValue($step, $tour);
+
         $this->assertSame($step, $step->persist());
     }
 
@@ -678,6 +694,11 @@ class step_testcase extends advanced_testcase {
         $rcp->setAccessible(true);
         $rcp->setValue($step, 42);
 
+        $tour = $this->createMock(\tool_usertours\tour::class);
+        $rcp = $rc->getProperty('tour');
+        $rcp->setAccessible(true);
+        $rcp->setValue($step, $tour);
+
         $this->assertSame($step, $step->persist(true));
     }
 
@@ -803,4 +824,48 @@ class step_testcase extends advanced_testcase {
         $this->assertEquals($value, $step->$getter());
     }
 
+    /**
+     * Data Provider for get_string_from_input.
+     *
+     * @return array
+     */
+    public function get_string_from_input_provider() {
+        return [
+            'Text'  => [
+                'example',
+                'example',
+            ],
+            'Text which looks like a langstring' => [
+                'example,fakecomponent',
+                'example,fakecomponent',
+            ],
+            'Text which is a langstring' => [
+                'administration,core',
+                'Administration',
+            ],
+            'Text which is a langstring but uses "moodle" instead of "core"' => [
+                'administration,moodle',
+                'Administration',
+            ],
+            'Text which is a langstring, but with extra whitespace' => [
+                '  administration,moodle  ',
+                'Administration',
+            ],
+            'Looks like a langstring, but has incorrect space around comma' => [
+                'administration , moodle',
+                'administration , moodle',
+            ],
+        ];
+    }
+
+    /**
+     * Ensure that the get_string_from_input function returns langstring strings correctly.
+     *
+     * @dataProvider get_string_from_input_provider
+     * @param   string  $string     The string to test
+     * @param   string  $expected   The expected result
+     */
+    public function test_get_string_from_input($string, $expected) {
+        $this->assertEquals($expected, \tool_usertours\step::get_string_from_input($string));
+    }
 }
index 99e6120..45bad95 100644 (file)
@@ -4,7 +4,7 @@
     <location>amd/src/tour.js</location>
     <name>Flexitour</name>
     <license>GPLv3</license>
-    <version>0.9.6</version>
+    <version>0.9.7</version>
     <licenseversion>3</licenseversion>
   </library>
   <library>
index 827b68e..6711935 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2016101800;            // The current module version (Date: YYYYMMDDXX).
+$plugin->version   = 2016102001;            // The current module version (Date: YYYYMMDDXX).
 $plugin->requires  = 2016052300;            // Requires this Moodle version.
 $plugin->component = 'tool_usertours';      // Full name of the plugin (used for diagnostics).
index f4aa617..38a8f06 100644 (file)
@@ -63,8 +63,6 @@ echo '<form action="upgradesettings.php" method="post" id="adminsettings">';
 echo '<div>';
 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
 echo '<input type="hidden" name="return" value="'.$return.'" />';
-// HACK to prevent browsers from automatically inserting the user's password into the wrong fields.
-echo prevent_form_autofill_password();
 echo '<fieldset>';
 echo '<div class="clearer"><!-- --></div>';
 echo $newsettingshtml;
index da24294..1c94323 100644 (file)
@@ -179,7 +179,7 @@ class availability_group_condition_testcase extends advanced_testcase {
         $course = $generator->create_course();
         $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
         $teacher = $generator->create_user();
-        $generator->enrol_user($teacher->id, $course->id, $roleids['teacher']);
+        $generator->enrol_user($teacher->id, $course->id, $roleids['editingteacher']);
         $allusers = array($teacher->id => $teacher);
         $students = array();
         for ($i = 0; $i < 3; $i++) {
index 4ffd76f..94cd4ec 100644 (file)
@@ -222,7 +222,7 @@ class availability_grouping_condition_testcase extends advanced_testcase {
         $course = $generator->create_course();
         $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
         $teacher = $generator->create_user();
-        $generator->enrol_user($teacher->id, $course->id, $roleids['teacher']);
+        $generator->enrol_user($teacher->id, $course->id, $roleids['editingteacher']);
         $allusers = array($teacher->id => $teacher);
         $students = array();
         for ($i = 0; $i < 3; $i++) {
index 5aad4a3..1fa38f1 100644 (file)
@@ -67,7 +67,7 @@ Feature: Restore Moodle 2 course backups
     And I add a "Forum" to section "1" and I fill the form with:
       | Forum name | Test forum post backup name |
       | Description | Test forum post backup description |
-    And I follow "Restore"
+    And I navigate to "Restore" node in "Course administration"
     And I merge "test_backup.mbz" backup into the current course after deleting it's contents using this options:
       | Schema | Section 3 | 0 |
     Then I should see "Course 1"
@@ -91,6 +91,7 @@ Feature: Restore Moodle 2 course backups
       | id_startdate_month | January |
       | id_startdate_year | 2020 |
       | id_format | Weekly format |
+      | id_enddate_enabled | 0 |
     And I press "Save and display"
     And I should see "1 January - 7 January"
     And I should see "Test forum name"
index e005a81..c3d3787 100644 (file)
Binary files a/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-debug.js and b/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-debug.js differ
index b001213..129195e 100644 (file)
Binary files a/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-min.js and b/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall-min.js differ
index e005a81..c3d3787 100644 (file)
Binary files a/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall.js and b/backup/util/ui/yui/build/moodle-backup-backupselectall/moodle-backup-backupselectall.js differ
index faf369b..4d152bc 100644 (file)
@@ -63,7 +63,7 @@ M.core_backup.backupselectall = function(modnames) {
         // This is not a relevant page.
         return;
     }
-    if (!firstsection.one('.felement.fcheckbox')) {
+    if (!firstsection.one('input[type="checkbox"]')) {
         // No checkboxes.
         return;
     }
@@ -166,7 +166,8 @@ M.core_backup.backupselectall = function(modnames) {
         }
 
     };
-    Y.one('#backup-bytype').on('click', function() {
+    Y.one('#backup-bytype').on('click', function(e) {
+        e.preventDefault();
         toggletypes();
     });
 
index bd0a070..92cc5ad 100644 (file)
@@ -32,7 +32,7 @@ Feature: Award badges
     And I press "Continue"
     And I click on "Admin User" "link"
     And I choose "Profile" in the open action menu
-    And I follow "Edit profile"
+    And I click on "Edit profile" "link" in the "region-main" "region"
     And I expand all fieldsets
     And I set the field "Phone" to "123456789"
     And I press "Update profile"
@@ -113,7 +113,7 @@ Feature: Award badges
     And I log out
     And I log in as "student1"
     And I follow "Profile" in the user menu
-    And I follow "Course 1"
+    And I click on "Course 1" "link" in the "region-main" "region"
     And I should see "Course Badge"
 
   @javascript
@@ -131,7 +131,7 @@ Feature: Award badges
       | student1 | C1 | student |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I follow "Edit settings"
+    And I navigate to "Edit settings" node in "Course administration"
     And I set the following fields to these values:
       | Enable completion tracking | Yes |
     And I press "Save and display"
@@ -156,13 +156,13 @@ Feature: Award badges
     And I log out
     And I log in as "student1"
     And I follow "Profile" in the user menu
-    And I follow "Course 1"
+    And I click on "Course 1" "link" in the "region-main" "region"
     Then I should not see "badges"
     And I am on homepage
     And I follow "Course 1"
     And I press "Mark as complete: Test assignment name"
     And I follow "Profile" in the user menu
-    And I follow "Course 1"
+    And I click on "Course 1" "link" in the "region-main" "region"
     Then I should see "Course Badge"
 
   @javascript
@@ -180,7 +180,7 @@ Feature: Award badges
       | student1 | C1 | student |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I follow "Edit settings"
+    And I navigate to "Edit settings" node in "Course administration"
     And I set the following fields to these values:
       | Enable completion tracking | Yes |
     And I press "Save and display"
@@ -189,7 +189,7 @@ Feature: Award badges
       | Assignment name | Test assignment name |
       | Description | Submit your online text |
       | assignsubmission_onlinetext_enabled | 1 |
-    And I follow "Course completion"
+    And I navigate to "Course completion" node in "Course administration"
     And I set the field "id_overall_aggregation" to "2"
     And I click on "Condition: Activity completion" "link"
     And I set the field "Assignment - Test assignment name" to "1"
@@ -211,7 +211,7 @@ Feature: Award badges
     And I log out
     And I log in as "student1"
     And I follow "Profile" in the user menu
-    And I follow "Course 1"
+    And I click on "Course 1" "link" in the "region-main" "region"
     Then I should not see "badges"
     And I am on homepage
     And I follow "Course 1"
@@ -300,14 +300,14 @@ Feature: Award badges
     # Student 1 should have just course badge 1.
     And I log in as "student1"
     And I follow "Profile" in the user menu
-    When I follow "Course 1"
+    When I click on "Course 1" "link" in the "region-main" "region"
     Then I should see "Course Badge 1"
     And I should not see "Course Badge 2"
     And I log out
     # Student 2 should have just course badge 2.
     And I log in as "student2"
     And I follow "Profile" in the user menu
-    When I follow "Course 1"
+    When I click on "Course 1" "link" in the "region-main" "region"
     Then I should see "Course Badge 2"
     Then I should not see "Course Badge 1"
 
index 1f444c8..2c62fb7 100644 (file)
@@ -50,7 +50,7 @@ Feature: The activity results block displays student scores
     And I press "Save and return to course"
     And I follow "Course 1"
     And I should see "Test page name"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "90.00" to the user "Student 1" for the grade item "Test assignment 1"
     And I give the grade "80.00" to the user "Student 2" for the grade item "Test assignment 1"
index b744851..6797129 100644 (file)
@@ -32,7 +32,7 @@ Feature: The activity results block displays student scores
       | Description | Offline text |
       | assignsubmission_file_enabled | 0 |
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "90.00" to the user "Student 1" for the grade item "Test assignment"
     And I give the grade "80.00" to the user "Student 2" for the grade item "Test assignment"
@@ -167,4 +167,4 @@ Feature: The activity results block displays student scores
     Then I should see "User" in the "Activity results" "block"
     And I should see "90.00%" in the "Activity results" "block"
     And I should see "80.00%" in the "Activity results" "block"
-    And I should see "70.00%" in the "Activity results" "block"
\ No newline at end of file
+    And I should see "70.00%" in the "Activity results" "block"
index b5e52f8..44ea70b 100644 (file)
@@ -26,7 +26,7 @@ Feature: The activity results block displays student scores as scales
       | student5 | C1 | student |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I navigate to "Scales" node in "Grade administration"
     And I press "Add a new scale"
     And I set the following fields to these values:
@@ -42,7 +42,7 @@ Feature: The activity results block displays student scores as scales
       | id_grade_modgrade_type | Scale |
       | id_grade_modgrade_scale | My Scale |
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "Excellent!" to the user "Student 1" for the grade item "Test assignment"
     And I give the grade "Very good" to the user "Student 2" for the grade item "Test assignment"
index d546fda..1f23958 100644 (file)
@@ -43,7 +43,7 @@ Feature: The activity results block displays student scores as scales
       | student6 | G3 |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I navigate to "Scales" node in "Grade administration"
     And I press "Add a new scale"
     And I set the following fields to these values:
@@ -60,7 +60,7 @@ Feature: The activity results block displays student scores as scales
       | id_grade_modgrade_scale | My Scale |
       | Group mode | Separate groups |
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "Excellent!" to the user "Student 1" for the grade item "Test assignment"
     And I give the grade "Very good" to the user "Student 2" for the grade item "Test assignment"
index 27807f8..5e76326 100644 (file)
@@ -50,7 +50,7 @@ Feature: The activity results block displays student scores
       | assignsubmission_file_enabled | 0 |
       | Group mode | Separate groups |
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
     And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
@@ -225,4 +225,4 @@ Feature: The activity results block displays student scores
     And I follow "Course 1"
     And I should see "User" in the "Activity results" "block"
     And I should see "100.00%" in the "Activity results" "block"
-    And I should see "90.00%" in the "Activity results" "block"
\ No newline at end of file
+    And I should see "90.00%" in the "Activity results" "block"
index f5fd1bd..1d4d8d4 100644 (file)
@@ -50,7 +50,7 @@ Feature: The activity results block displays student scores
       | assignsubmission_file_enabled | 0 |
       | Group mode | Visible groups |
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
     And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
@@ -202,4 +202,4 @@ Feature: The activity results block displays student scores
     And I should see "Group" in the "Activity results" "block"
     And I should see "95.00%" in the "Activity results" "block"
     And I should see "85.00%" in the "Activity results" "block"
-    And I should see "75.00%" in the "Activity results" "block"
\ No newline at end of file
+    And I should see "75.00%" in the "Activity results" "block"
index c20061f..9290095 100644 (file)
@@ -32,7 +32,7 @@ Feature: The activity results block displays student scores
       | Description | Offline text |
       | assignsubmission_file_enabled | 0 |
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "90.00" to the user "Student 1" for the grade item "Test assignment"
     And I give the grade "80.00" to the user "Student 2" for the grade item "Test assignment"
@@ -156,4 +156,4 @@ Feature: The activity results block displays student scores
     Then I should see "User" in the "Activity results" "block"
     And I should see "50.00%" in the "Activity results" "block"
     And I should see "60.00%" in the "Activity results" "block"
-    And I should see "70.00%" in the "Activity results" "block"
\ No newline at end of file
+    And I should see "70.00%" in the "Activity results" "block"
index 00f31f6..52c97bd 100644 (file)
@@ -26,7 +26,7 @@ Feature: The activity results block displays student scores as scales
       | student5 | C1 | student |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I navigate to "Scales" node in "Grade administration"
     And I press "Add a new scale"
     And I set the following fields to these values:
@@ -42,7 +42,7 @@ Feature: The activity results block displays student scores as scales
       | id_grade_modgrade_type | Scale |
       | id_grade_modgrade_scale | My Scale |
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "Excellent!" to the user "Student 1" for the grade item "Test assignment"
     And I give the grade "Very good" to the user "Student 2" for the grade item "Test assignment"
index be5ae33..b16a339 100644 (file)
@@ -43,7 +43,7 @@ Feature: The activity results block displays student scores as scales
       | student6 | G3 |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I navigate to "Scales" node in "Grade administration"
     And I press "Add a new scale"
     And I set the following fields to these values:
@@ -60,7 +60,7 @@ Feature: The activity results block displays student scores as scales
       | id_grade_modgrade_scale | My Scale |
       | Group mode | Separate groups |
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "Excellent!" to the user "Student 1" for the grade item "Test assignment"
     And I give the grade "Very good" to the user "Student 2" for the grade item "Test assignment"
index b5e0546..47c5f56 100644 (file)
@@ -50,7 +50,7 @@ Feature: The activity results block displays student scores
       | assignsubmission_file_enabled | 0 |
       | Group mode | Separate groups |
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
     And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
@@ -217,4 +217,4 @@ Feature: The activity results block displays student scores
     And I follow "Course 1"
     And I should see "User" in the "Activity results" "block"
     And I should see "100.00%" in the "Activity results" "block"
-    And I should see "90.00%" in the "Activity results" "block"
\ No newline at end of file
+    And I should see "90.00%" in the "Activity results" "block"
index 7049958..0d0f224 100644 (file)
@@ -50,7 +50,7 @@ Feature: The activity results block displays student scores
       | assignsubmission_file_enabled | 0 |
       | Group mode | Visible groups |
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
     And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
@@ -198,4 +198,4 @@ Feature: The activity results block displays student scores
     And I follow "Course 1"
     And I should see "Group" in the "Activity results" "block"
     And I should see "85.00%" in the "Activity results" "block"
-    And I should see "75.00%" in the "Activity results" "block"
\ No newline at end of file
+    And I should see "75.00%" in the "Activity results" "block"
index 7bfb063..6b8001f 100644 (file)
@@ -219,4 +219,4 @@ Feature: Enable Block blog menu in an activity
     And I press "Search"
     Then I should see "S1 First Blog"
     And I should see "S2 First Blog"
-    And I should not see "S2 Second Blog"
\ No newline at end of file
+    And I should not see "S2 Second Blog"
index d840c38..597cbe7 100644 (file)
@@ -25,7 +25,7 @@ Feature: Adding blog tag block
     And I turn editing mode on
     And I add the "Blog tags" block
 
-    And I navigate to "Course blogs" node in "Current course > c1 > Participants"
+    And I navigate to "Course blogs" node in "My courses > c1 > Participants"
     And I follow "Blog about this Course"
     And I set the following fields to these values:
       | Entry title                                 | Blog post from teacher    |
@@ -35,7 +35,7 @@ Feature: Adding blog tag block
     And I log out
     And I log in as "student1"
     And I follow "Course 1"
-    And I navigate to "Course blogs" node in "Current course > c1 > Participants"
+    And I navigate to "Course blogs" node in "My courses > c1 > Participants"
     And I follow "Blog about this Course"
     And I set the following fields to these values:
       | Entry title                                 | Blog post from student    |
index ae09aa8..b7ef68e 100644 (file)
@@ -11,6 +11,8 @@ Feature: Enable the calendar block on the site front page
       | student1 | Student | 1 | student1@example.com | S1 |
     And I log in as "admin"
     And I am on site homepage
+    And I turn editing mode on
+    And I add the "Calendar" block
     And I create a calendar event with form data:
       | id_eventtype | Site |
       | id_name | Site Event |
index 4f3fa50..c427300 100644 (file)
@@ -28,13 +28,13 @@ Feature: Enable the course_list block on a category page and view it's contents
   Scenario: Add the course list block on category page and navigate to the course listing
     Given I log in as "admin"
     And I am on site homepage
-    And I navigate to "Turn editing on" node in "Front page settings"
-    And I follow "Course 1"
+    And I turn editing mode on
+    And I am on course index
     And I follow "Miscellaneous"
     And I add the "Courses" block
     And I log out
     When I log in as "teacher1"
-    And I follow "Course 1"
+    And I am on course index
     And I follow "Miscellaneous"
     Then I should see "Course 1" in the "My courses" "block"
     And I should see "Course 2" in the "My courses" "block"
@@ -46,13 +46,13 @@ Feature: Enable the course_list block on a category page and view it's contents
   Scenario: Add the course list block on category page and navigate to another course
     Given I log in as "admin"
     And I am on site homepage
-    And I navigate to "Turn editing on" node in "Front page settings"
-    And I follow "Course 1"
+    And I turn editing mode on
+    And I am on course index
     And I follow "Miscellaneous"
     And I add the "Courses" block
     And I log out
     When I log in as "teacher1"
-    And I follow "Course 1"
+    And I am on course index
     And I follow "Miscellaneous"
     Then I should see "Course 1" in the "My courses" "block"
     And I should see "Course 2" in the "My courses" "block"
@@ -64,8 +64,8 @@ Feature: Enable the course_list block on a category page and view it's contents
   Scenario: Add the course list block on category page and view as an admin
     Given I log in as "admin"
     And I am on site homepage
-    And I navigate to "Turn editing on" node in "Front page settings"
-    And I follow "Course 1"
+    And I turn editing mode on
+    And I am on course index
     And I follow "Miscellaneous"
     When I add the "Courses" block
     Then I should see "Miscellaneous" in the "Course categories" "block"
index e8980b0..6299f59 100644 (file)
@@ -7,6 +7,8 @@ Feature: Course summary block used on the frontpage
   Background:
     Given I log in as "admin"
     And I am on site homepage
+    And I turn editing mode on
+    And I add the "Course/site summary" block
     And I navigate to "Edit settings" node in "Front page settings"
     And I set the following fields to these values:
       | summary | Proved the summary block works! |
diff --git a/blocks/navigation/tests/behat/expand_my_courses_setting.feature b/blocks/navigation/tests/behat/expand_my_courses_setting.feature
deleted file mode 100644 (file)
index bfba988..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-@block @block_navigation
-Feature: Test expand my courses navigation setting
-  As a student
-  I visit my My Moodle page and observe the the My Courses branch
-
-  Background:
-    Given the following "users" exist:
-      | username | firstname | lastname | email |
-      | student1 | Student | 1 | student1@example.com |
-    And the following "categories" exist:
-      | name  | category | idnumber |
-      | cat1  | 0        | cat1     |
-    And the following "courses" exist:
-      | fullname | shortname | category |
-      | Course1  | c1        | cat1     |
-      | Course2  | c2        | cat1     |
-      | Course3  | c3        | cat1     |
-    And the following "course enrolments" exist:
-      | user     | course | role    |
-      | student1 | c1     | student |
-      | student1 | c2    | student |
-
-  Scenario: The My Courses branch is expanded on the My Moodle page by default
-    When I log in as "student1"
-    And I click on "Dashboard" "link" in the "Navigation" "block"
-    Then I should see "c1" in the "Navigation" "block"
-    And I should see "c2" in the "Navigation" "block"
-    And I should not see "c3" in the "Navigation" "block"
-
-  @javascript
-  Scenario: The My Courses branch is collapsed when expand my courses is off
-    Given I log in as "admin"
-    And I set the following administration settings values:
-      | Show My courses expanded on Dashboard | 0 |
-    And I log out
-    When I log in as "student1"
-    And I click on "Dashboard" "link" in the "Navigation" "block"
-    Then I should not see "c1" in the "Navigation" "block"
-    And I should not see "c2" in the "Navigation" "block"
-    And I should not see "c3" in the "Navigation" "block"
-
-  @javascript
-  Scenario: My Courses can be expanded on the My Moodle page when expand my courses is off
-    Given I log in as "admin"
-    And I set the following administration settings values:
-      | Show My courses expanded on Dashboard | 0 |
-    And I log out
-    When I log in as "student1"
-    And I click on "Dashboard" "link" in the "Navigation" "block"
-    And I should not see "c1" in the "Navigation" "block"
-    And I should not see "c2" in the "Navigation" "block"
-    And I should not see "c3" in the "Navigation" "block"
-    And I expand "My courses" node
-    Then I should see "c1" in the "Navigation" "block"
-    And I should see "c2" in the "Navigation" "block"
-    And I should not see "c3" in the "Navigation" "block"
index ecac0bd..a899073 100644 (file)
@@ -18,6 +18,9 @@ Feature: Latest announcements block displays the course latest news
     And I log out
     And I log in as "teacher1"
     And I follow "Course 1"
+    And I turn editing mode on
+    And I add the "Latest announcements" block
+    And I turn editing mode off
     When I add a new topic to "Announcements" forum with:
       | Subject | Discussion One |
       | Message | Not important |
@@ -31,14 +34,14 @@ Feature: Latest announcements block displays the course latest news
     Then I should see "Discussion One" in the "Latest announcements" "block"
     And I should see "Discussion Two" in the "Latest announcements" "block"
     And I should see "Discussion Three" in the "Latest announcements" "block"
-    And I follow "Edit settings"
+    And I click on "Edit settings" "link" in the "Administration" "block"
     And I set the following fields to these values:
       | News items to show | 2 |
     And I press "Save and display"
     And I should not see "Discussion One" in the "Latest announcements" "block"
     And I should see "Discussion Two" in the "Latest announcements" "block"
     And I should see "Discussion Three" in the "Latest announcements" "block"
-    And I follow "Edit settings"
+    And I click on "Edit settings" "link" in the "Administration" "block"
     And I set the following fields to these values:
       | News items to show | 0 |
     And I press "Save and display"
index 380ea1e..d66978a 100644 (file)
@@ -49,6 +49,7 @@ Feature: View structural changes in recent activity block
     Given I log in as "teacher1"
     And I follow "Course 1"
     And I turn editing mode on
+    And I add the "Recent activity" block
     When I add a "Forum" to section "1" and I fill the form with:
       | name        | ForumVisibleGroups |
       | Description | No description     |
@@ -145,6 +146,7 @@ Feature: View structural changes in recent activity block
     When I log in as "teacher1"
     And I follow "Course 1"
     And I turn editing mode on
+    And I add the "Recent activity" block
     And I add a "Forum" to section "1" and I fill the form with:
       | name        | ForumNew       |
       | Description | No description |
index 48d164d..0f54b4b 100644 (file)
@@ -21,6 +21,9 @@ Feature: The search forums block allows users to search for forum posts
     And I navigate to "Edit settings" node in "Course administration"
     And I set the field "id_newsitems" to "1"
     And I press "Save and display"
+    And I turn editing mode on
+    And I add the "Latest announcements" block
+    And I add the "Search forums" block
     And I log out
 
   Scenario: Use the search forum block in a course without any forum posts
index f391d7b..62054a0 100644 (file)
@@ -9,6 +9,7 @@ Feature: Add URL to main menu block
     Given I log in as "admin"
     And I am on site homepage
     And I navigate to "Turn editing on" node in "Front page settings"
+    And I add the "Main menu" block
     When I add a "URL" to section "0" and I fill the form with:
       | Name | google |
       | Description | gooooooooogle |
index dc73b9d..4799495 100644 (file)
@@ -9,6 +9,7 @@ Feature: Edit activities in main menu block
     Given I log in as "admin"
     And I am on site homepage
     And I navigate to "Turn editing on" node in "Front page settings"
+    And I add the "Main menu" block
     When I add a "Forum" to section "0" and I fill the form with:
       | Forum name | My forum name |
     And I click on "Edit title" "link" in the "//*[contains(@class,'block_site_main_menu')]//li[contains(.,'My forum name')]" "xpath_element"
index 07b58e3..ca391d3 100644 (file)
@@ -18,6 +18,7 @@ Feature: Edit activities in social activities block
     Given I log in as "user1"
     And I follow "Course 1"
     And I turn editing mode on
+    And I add the "Social activities" block
     And I set the field "Add an activity to section 'section 0'" to "Forum"
     And I set the field "Forum name" to "My forum name"
     And I press "Save and return to course"
index 36e1bc0..9c7ee6b 100644 (file)
@@ -31,7 +31,7 @@ Feature: Block tags displaying tag cloud
     And I should see "Cats" in the "Tags" "block"
     And I should not see "Neverusedtag" in the "Tags" "block"
     And I click on "Dogs" "link" in the "Tags" "block"
-    And I should see "Log in to the site" in the ".breadcrumb" "css_element"
+    And I should see "You are not logged in"
 
   Scenario: Add Tags block in a course
     When I log in as "teacher1"
index 9498021..db03ce2 100644 (file)
@@ -58,6 +58,7 @@ Feature: Add and configure blocks throughout the site
     Given I log in as "teacher1"
     And I follow "Course 1"
     And I follow "Turn editing on"
+    And I add the "Search forums" block
     Then I should see "Assign roles in Search forums block"
 
   @javascript
index bd3a6c4..6abadca 100644 (file)
@@ -14,6 +14,10 @@ Feature: Show hidden blocks in a docked block region when editing
     And I log in as "admin"
     And I follow "Course 1"
     And I turn editing mode on
+    And I add the "Search forums" block
+    And I add the "Latest announcements" block
+    And I add the "Upcoming events" block
+    And I add the "Recent activity" block
     # Hide all the blocks in the non-default region
     And I configure the "Search forums" block
     And I set the following fields to these values:
index 449574f..9c6c046 100644 (file)
@@ -20,6 +20,7 @@ Feature: Limit displayed upcoming events
     Given I follow "C1"
     And I turn editing mode on
     And I add the "Calendar" block
+    And I add the "Upcoming events" block
     And I follow "This month"
     And I click on "a.next" "css_element"
     And I click on "a.next" "css_element"
index 7d8ccdb..3d89faf 100644 (file)
@@ -32,7 +32,7 @@ Feature: Add cohorts of users
     When I add "First User (first@example.com)" user to "333" cohort members
     And I add "Second User (second@example.com)" user to "333" cohort members
     Then I should see "2" in the "#cohorts" "css_element"
-    And I follow "Assign"
+    And I click on "Assign" "link" in the "Test cohort name" "table_row"
     And the "Current users" select box should contain "First User (first@example.com)"
     And the "Current users" select box should contain "Second User (second@example.com)"
     And the "Current users" select box should not contain "Forth User (forth@example.com)"
@@ -49,7 +49,7 @@ Feature: Add cohorts of users
     And I press "Add to cohort"
     And I follow "Cohorts"
     Then I should see "2" in the "#cohorts" "css_element"
-    And I follow "Assign"
+    And I click on "Assign" "link" in the "Test cohort name" "table_row"
     And the "Current users" select box should contain "Third User (third@example.com)"
     And the "Current users" select box should contain "Forth User (forth@example.com)"
     And the "Current users" select box should not contain "First User (first@example.com)"
index ebcedc0..61ef537 100644 (file)
@@ -116,7 +116,7 @@ class core_completion_externallib_testcase extends externallib_advanced_testcase
         $cmforum = get_coursemodule_from_id('forum', $forum->cmid);
 
         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
-        $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
+        $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
         $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id);
         $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
 
@@ -220,7 +220,7 @@ class core_completion_externallib_testcase extends externallib_advanced_testcase
         $cmforum = get_coursemodule_from_id('forum', $forum->cmid);
 
         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
-        $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
+        $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
         $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id);
         $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
 
diff --git a/course/admin.php b/course/admin.php
new file mode 100644 (file)
index 0000000..959101b
--- /dev/null
@@ -0,0 +1,55 @@
+<?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/>.
+
+/**
+ * Listing of the course administration pages for this course.
+ *
+ * @copyright 2016 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once("../config.php");
+
+$courseid = required_param('courseid', PARAM_INT);
+
+$PAGE->set_url('/course/admin.php', array('courseid'=>$courseid));
+
+$course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
+
+require_login($course);
+$context = context_course::instance($course->id);
+
+$PAGE->set_pagelayout('incourse');
+
+if ($courseid == $SITE->id) {
+    $title = get_string('frontpagesettings');
+    $node = $PAGE->settingsnav->find('frontpage', navigation_node::TYPE_SETTING);
+} else {
+    $title = get_string('courseadministration');
+    $node = $PAGE->settingsnav->find('courseadmin', navigation_node::TYPE_COURSE);
+}
+$PAGE->set_title($title);
+$PAGE->set_heading($course->fullname);
+$PAGE->navbar->add($title);
+echo $OUTPUT->header();
+echo $OUTPUT->heading($title);
+
+if ($node) {
+    echo $OUTPUT->render_from_template('core/settings_link_page', ['node' => $node]);
+}
+
+echo $OUTPUT->footer();
index 7d3a96f..57bd05f 100644 (file)
@@ -2492,10 +2492,12 @@ class core_course_external extends external_api {
                         $info->outcomes = array();
                     }
                     $id = str_replace('outcome_', '', $key);
-                    $outcome = $outcome = grade_outcome::fetch(array('id' => $id));
+                    $outcome = grade_outcome::fetch(array('id' => $id));
+                    $scaleitems = $outcome->load_scale();
                     $info->outcomes[] = array(
                         'id' => $id,
-                        'name' => external_format_string($outcome->get_name(), $context->id)
+                        'name' => external_format_string($outcome->get_name(), $context->id),
+                        'scale' => $scaleitems->scale
                     );
                 }
             }
@@ -2572,6 +2574,7 @@ class core_course_external extends external_api {
                                 array(
                                     'id' => new external_value(PARAM_ALPHANUMEXT, 'Outcome id'),
                                     'name'  => new external_value(PARAM_TEXT, 'Outcome full name'),
+                                    'scale' => new external_value(PARAM_TEXT, 'Scale items')
                                 )
                             ),
                             'Outcomes information', VALUE_OPTIONAL
index f667427..35d371d 100644 (file)
@@ -96,6 +96,9 @@ abstract class format_base {
      * @return string
      */
     protected static final function get_format_or_default($format) {
+        global $CFG;
+        require_once($CFG->dirroot . '/course/lib.php');
+
         if (array_key_exists($format, self::$classesforformat)) {
             return self::$classesforformat[$format];
         }
@@ -482,7 +485,7 @@ abstract class format_base {
         }
         $blocknames = array(
             BLOCK_POS_LEFT => array(),
-            BLOCK_POS_RIGHT => array('search_forums', 'news_items', 'calendar_upcoming', 'recent_activity')
+            BLOCK_POS_RIGHT => array()
         );
         return $blocknames;
     }
index e466585..6d43ce4 100644 (file)
@@ -71,8 +71,7 @@ class format_social extends format_base {
     public function get_default_blocks() {
         return array(
             BLOCK_POS_LEFT => array(),
-            BLOCK_POS_RIGHT => array('search_forums', 'calendar_upcoming', 'social_activities',
-                'recent_activity', 'course_list')
+            BLOCK_POS_RIGHT => array()
         );
     }
 
index da48e81..5acb246 100644 (file)
@@ -121,9 +121,6 @@ class format_topics extends format_base {
             if ($sectionno != 0 && $usercoursedisplay == COURSE_DISPLAY_MULTIPAGE) {
                 $url->param('section', $sectionno);
             } else {
-                if (empty($CFG->linkcoursesections) && !empty($options['navigation'])) {
-                    return null;
-                }
                 $url->set_anchor('section-'.$sectionno);
             }
         }
@@ -208,7 +205,7 @@ class format_topics extends format_base {
     public function get_default_blocks() {
         return array(
             BLOCK_POS_LEFT => array(),
-            BLOCK_POS_RIGHT => array('search_forums', 'news_items', 'calendar_upcoming', 'recent_activity')
+            BLOCK_POS_RIGHT => array()
         );
     }
 
index 03db896..49023a5 100644 (file)
@@ -57,11 +57,11 @@ Feature: Sections can be edited and deleted in topics format
     When I click on "Edit topic name" "link" in the "li#section-1" "css_element"
     And I set the field "New name for topic Topic 1" to "Midterm evaluation"
     And I press key "13" in the field "New name for topic Topic 1"
-    Then I should not see "Topic 1" in the "#region-main" "css_element"
+    Then I should not see "Topic 1" in the "region-main" "region"
     And "New name for topic" "field" should not exist
     And I should see "Midterm evaluation" in the "li#section-1" "css_element"
     And I follow "Course 1"
-    And I should not see "Topic 1" in the "#region-main" "css_element"
+    And I should not see "Topic 1" in the "region-main" "region"
     And I should see "Midterm evaluation" in the "li#section-1" "css_element"
 
   Scenario: Deleting the last section in topics format
index d32664c..e9237c6 100644 (file)
@@ -124,9 +124,6 @@ class format_weeks extends format_base {
             if ($sectionno != 0 && $usercoursedisplay == COURSE_DISPLAY_MULTIPAGE) {
                 $url->param('section', $sectionno);
             } else {
-                if (empty($CFG->linkcoursesections) && !empty($options['navigation'])) {
-                    return null;
-                }
                 $url->set_anchor('section-'.$sectionno);
             }
         }
@@ -213,7 +210,7 @@ class format_weeks extends format_base {
     public function get_default_blocks() {
         return array(
             BLOCK_POS_LEFT => array(),
-            BLOCK_POS_RIGHT => array('search_forums', 'news_items', 'calendar_upcoming', 'recent_activity')
+            BLOCK_POS_RIGHT => array()
         );
     }
 
index 355059a..5d2150c 100644 (file)
@@ -62,11 +62,11 @@ Feature: Sections can be edited and deleted in weeks format
     When I click on "Edit week name" "link" in the "li#section-1" "css_element"
     And I set the field "New name for week 1 May - 7 May" to "Midterm evaluation"
     And I press key "13" in the field "New name for week 1 May - 7 May"
-    Then I should not see "1 May - 7 May" in the "#region-main" "css_element"
+    Then I should not see "1 May - 7 May" in the "region-main" "region"
     And "New name for week" "field" should not exist
     And I should see "Midterm evaluation" in the "li#section-1" "css_element"
     And I follow "Course 1"
-    And I should not see "1 May - 7 May" in the "#region-main" "css_element"
+    And I should not see "1 May - 7 May" in the "region-main" "region"
     And I should see "Midterm evaluation" in the "li#section-1" "css_element"
 
   Scenario: Deleting the last section in weeks format
index e731709..d8a922b 100644 (file)
@@ -3469,7 +3469,7 @@ function course_get_tagged_course_modules($tag, $exclusivemode = false, $fromcon
  * This function also handles the frontpage course.
  *
  * @param  stdClass $context context object (it can be a course context or the system context for frontpage settings)
- * @param  stdClass $course  the course where the settings are being rendered (only used when $context is set to frontpage)
+ * @param  stdClass $course  the course where the settings are being rendered
  * @return stdClass          the navigation options in a course and their availability status
  * @since  Moodle 3.2
  */
@@ -3510,6 +3510,30 @@ function course_get_user_navigation_options($context, $course = null) {
         $options->participants = has_capability('moodle/course:viewparticipants', $context);
         $options->badges = !empty($CFG->enablebadges) && !empty($CFG->badges_allowcoursebadges) &&
                             has_capability('moodle/badges:viewbadges', $context);
+        // Add view grade report is permitted.
+        $grades = false;
+
+        if (has_capability('moodle/grade:viewall', $context)) {
+            $grades = true;
+        } else if (!empty($course->showgrades)) {
+            $reports = core_component::get_plugin_list('gradereport');
+            if (is_array($reports) && count($reports) > 0) {  // Get all installed reports.
+                arsort($reports);   // User is last, we want to test it first.
+                foreach ($reports as $plugin => $plugindir) {
+                    if (has_capability('gradereport/'.$plugin.':view', $context)) {
+                        // Stop when the first visible plugin is found.
+                        $grades = true;
+                        break;
+                    }
+                }
+            }
+        }
+        $options->grades = $grades;
+    }
+
+    if (\core_competency\api::is_enabled()) {
+        $capabilities = array('moodle/competency:coursecompetencyview', 'moodle/competency:coursecompetencymanage');
+        $options->competencies = has_any_capability($capabilities, $context);
     }
     return $options;
 }
@@ -3545,25 +3569,6 @@ function course_get_user_administration_options($course, $context) {
         $options->publish = has_capability('moodle/course:publish', $context);
         $options->reset = has_capability('moodle/course:reset', $context);
         $options->roles = has_capability('moodle/role:switchroles', $context);
-
-        // Add view grade report is permitted.
-        $grades = false;
-        if (has_capability('moodle/grade:viewall', $context)) {
-            $grades = true;
-        } else if (!empty($course->showgrades)) {
-            $reports = core_component::get_plugin_list('gradereport');
-            if (is_array($reports) && count($reports) > 0) {  // Get all installed reports.
-                arsort($reports);   // User is last, we want to test it first.
-                foreach ($reports as $plugin => $plugindir) {
-                    if (has_capability('gradereport/'.$plugin.':view', $context)) {
-                        // Stop when the first visible plugin is found.
-                        $grades = true;
-                        break;
-                    }
-                }
-            }
-        }
-        $options->grades = $grades;
     } else {
         // Set default options to false.
         $listofoptions = array('tags', 'gradebook', 'outcomes', 'badges', 'import', 'publish', 'reset', 'roles', 'grades');
index a682c37..4e7c237 100644 (file)
@@ -46,9 +46,11 @@ if (strpos($returnurl, '?') === false) {
     $returnurl  = clean_param($returnurl, PARAM_URL);
 }
 
-$PAGE->set_url('/course/switchrole.php', array('id'=>$id));
+$PAGE->set_url('/course/switchrole.php', array('id'=>$id, 'switchrole'=>$switchrole));
 
-require_sesskey();
+if ($switchrole >= 0) {
+    require_sesskey();
+}
 
 if (!$course = $DB->get_record('course', array('id'=>$id))) {
     redirect(new moodle_url('/'));
@@ -70,6 +72,21 @@ if ($switchrole > 0 && has_capability('moodle/role:switchroles', $context)) {
     if (is_array($aroles) && isset($aroles[$switchrole])) {
         role_switch($switchrole, $context);
     }
+} else if ($switchrole < 0) {
+
+    $PAGE->set_title(get_string('switchroleto'));
+    $PAGE->set_heading($course->fullname);
+    $PAGE->set_pagelayout('incourse');
+
+    echo $OUTPUT->header();
+    echo $OUTPUT->heading(get_string('switchroleto'));
+
+    require_once($CFG->dirroot.'/course/switchrole_form.php');
+    $form = new switchrole_form(null, ['course' => $course]);
+    $form->display();
+
+    echo $OUTPUT->footer();
+    exit;
 }
 
 redirect($returnurl);
diff --git a/course/switchrole_form.php b/course/switchrole_form.php
new file mode 100644 (file)
index 0000000..5788656
--- /dev/null
@@ -0,0 +1,96 @@
+<?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/>.
+
+/**
+ * Switch roles form.
+ *
+ * @package     core_course
+ * @copyright   2016 Damyon Wiese
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->libdir.'/formslib.php');
+
+/**
+ * Defines the course completion settings form.
+ */
+class switchrole_form extends moodleform {
+
+    /**
+     * Determine whether the user is assuming another role
+     *
+     * This function checks to see if the user is assuming another role by means of
+     * role switching. In doing this we compare each RSW key (context path) against
+     * the current context path. This ensures that we can provide the switching
+     * options against both the course and any page shown under the course.
+     *
+     * @param context $context
+     * @return bool|int The role(int) if the user is in another role, false otherwise
+     */
+    protected function in_alternative_role($context) {
+        global $USER, $PAGE;
+        if (!empty($USER->access['rsw']) && is_array($USER->access['rsw'])) {
+            if (!empty($PAGE->context) && !empty($USER->access['rsw'][$PAGE->context->path])) {
+                return $USER->access['rsw'][$PAGE->context->path];
+            }
+            foreach ($USER->access['rsw'] as $key=>$role) {
+                if (strpos($context->path, $key)===0) {
+                    return $role;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Defines the form fields.
+     */
+    public function definition() {
+        global $USER, $CFG, $DB;
+
+        $mform = $this->_form;
+        $course = $this->_customdata['course'];
+
+        // Overall criteria aggregation.
+        $context = context_course::instance($course->id);
+        $roles = array();
+        $assumedrole = -1;
+        if (is_role_switched($course->id)) {
+            $roles[0] = get_string('switchrolereturn');
+            $assumedrole = $USER->access['rsw'][$context->path];
+        }
+        $availableroles = get_switchable_roles($context);
+        if (is_array($availableroles)) {
+            foreach ($availableroles as $key=>$role) {
+                if ($assumedrole == (int)$key) {
+                    continue;
+                }
+                $roles[$key] = $role;
+            }
+        }
+        $mform->addElement('select', 'switchrole', get_string('role'), $roles);
+
+        // Add common action buttons.
+        $this->add_action_buttons();
+
+        // Add hidden fields.
+        $mform->addElement('hidden', 'id', $course->id);
+        $mform->setType('id', PARAM_INT);
+    }
+}
index cf006b9..166210a 100644 (file)
@@ -650,7 +650,7 @@ class behat_course extends behat_base {
             // It should not exist at all.
             try {
                 $this->find_link($activityname);
-                throw new ExpectationException('The "' . $activityname . '" should not appear');
+                throw new ExpectationException('The "' . $activityname . '" should not appear', $this->getSession());
             } catch (ElementNotFoundException $e) {
                 // This is good, the activity should not be there.
             }
index 4b41415..1bb7129 100644 (file)
@@ -315,4 +315,4 @@ Feature: We can change the visibility of categories in the management interface.
       And category in management listing should be visible "CAT1"
       And category in management listing should be visible "CAT2"
       And category in management listing should be visible "CAT3"
-      And course in management listing should be dimmed "C1"
\ No newline at end of file
+      And course in management listing should be dimmed "C1"
index 42dacac..615928e 100644 (file)
@@ -209,4 +209,4 @@ Feature: Test we can resort categories in the management interface.
     And I should see category listing "Cat 1" before "Cat 1b"
     And I should see category listing "Cat 1b" before "Cat 1c"
     And I should see category listing "Cat 1c" before "Cat 1a"
-    And I should see category listing "Cat 1a" before "Cat 2"
\ No newline at end of file
+    And I should see category listing "Cat 1a" before "Cat 2"
index 6311d8b..ea67b34 100644 (file)
@@ -95,7 +95,7 @@ Feature: We can change the visibility of courses in the management interface.
     And I toggle visibility of category "CAT1" in management listing
     And I toggle visibility of course "C1" in management listing
     And I click on "Course categories and courses" "link" in the ".view-mode-selector" "css_element"
-    And I click on "Courses" "link"
+    And I click on "Courses" "link" in the ".view-mode-selector" "css_element"
     And a new page should have loaded since I started watching
     And I start watching to see if a new page loads
     And I should see "Course 1" in the "#course-listing ul.ml" "css_element"
index 7dfb1c7..fda72f9 100644 (file)
@@ -29,16 +29,8 @@ Feature: Course activity controls works as expected
     And I log in as "teacher1"
     And I follow "Course 1"
     When I follow <targetpage>
-    And I press "Turn editing on"
-    Then I should see "Turn editing off"
-    And I press "Turn editing off"
-    And "Turn editing on" "button" should exist
-    And I follow "Turn editing on"
-    And "Turn editing off" "button" should exist
-    And I follow "Turn editing off"
-    And I should see "Turn editing on"
-    And "Turn editing on" "button" should exist
     And I turn editing mode on
+    And I add the "Recent activity" block
     And I open the action menu in "Recent activity" "block"
     And I click on "Delete Recent activity block" "link"
     And I press "Yes"
@@ -68,7 +60,7 @@ Feature: Course activity controls works as expected
     And I click on "Hide" "link" in the "Test forum name 1" activity
     And <belowpage> "section" <should_see_other_sections> exist
     And I delete "Test forum name 1" activity
-    And I should not see "Test forum name 1" in the "#region-main" "css_element"
+    And I should not see "Test forum name 1" in the "region-main" "region"
     And I duplicate "Test forum name 2" activity editing the new copy with:
       | Forum name | Edited test forum name 2 |
     And <belowpage> "section" <should_see_other_sections> exist
@@ -109,16 +101,8 @@ Feature: Course activity controls works as expected
     And I log in as "teacher1"
     And I follow "Course 1"
     When I follow <targetpage>
-    And I press "Turn editing on"
-    Then I should see "Turn editing off"
-    And I press "Turn editing off"
-    And "Turn editing on" "button" should exist
-    And I follow "Turn editing on"
-    And "Turn editing off" "button" should exist
-    And I follow "Turn editing off"
-    And I should see "Turn editing on"
-    And "Turn editing on" "button" should exist
     And I turn editing mode on
+    And I add the "Recent activity" block
     And I open the action menu in "Recent activity" "block"
     And I click on "Delete Recent activity block" "link"
     And I press "Yes"
@@ -143,7 +127,7 @@ Feature: Course activity controls works as expected
     And <belowpage> "section" <should_see_other_sections> exist
     And I delete "Test forum name 1" activity
     And <belowpage> "section" <should_see_other_sections> exist
-    And I should not see "Test forum name 1" in the "#region-main" "css_element"
+    And I should not see "Test forum name 1" in the "region-main" "region"
     And I duplicate "Test forum name 2" activity editing the new copy with:
       | Forum name | Edited test forum name 2 |
     And <belowpage> "section" <should_see_other_sections> exist
index 3b2b0ff..f8c945c 100644 (file)
@@ -19,6 +19,8 @@ Feature: Managers can create courses
     And I log out
     When I log in as "teacher1"
     And I follow "Course 1"
+    And I turn editing mode on
+    And I add the "Latest announcements" block
     Then "Latest announcements" "block" should exist
     And I follow "Announcements"
     And "Add a new topic" "button" should exist
@@ -52,8 +54,10 @@ Feature: Managers can create courses
       | id_enddate_year | 2016 |
     And I press "Save and return"
     Then I should see the "Course categories and courses" management page
+    And I click on "Sort courses" "link"
+    And I click on "Sort by Course time created ascending" "link" in the ".course-listing-actions" "css_element"
     And I should see course listing "Course 1" before "Course 2"
-    And I follow "Course 2"
+    And I click on "Course 2" "link" in the "region-main" "region"
     And I click on "Edit" "link" in the ".course-detail" "css_element"
     And the following fields match these values:
       | Course full name | Course 2 |
index 7366ecc..1c81efd 100644 (file)
@@ -17,6 +17,7 @@ Feature: Activities can be moved between sections
     And I log in as "teacher1"
     And I follow "Course 1"
     And I turn editing mode on
+    And I add the "Recent activity" block
     And I follow "Delete Recent activity block"
     And I press "Yes"
     And I follow "Configure Navigation block"
index cabeace..d2bb130 100644 (file)
@@ -34,7 +34,7 @@ Feature: Browse course list and return back from enrolment page
   Scenario: A user can return to the previous page from enrolment page by clicking navigation links
     When I log in as "user2"
     And I follow "Preferences" in the user menu
-    And I follow "Edit profile"
+    And I click on "Edit profile" "link" in the "region-main" "region"
     And I expand "Courses" node
     And I expand "Sample category" node
     And I follow "Course 1"
index e470289..262bbed 100644 (file)
@@ -575,10 +575,6 @@ class core_course_courselib_testcase extends advanced_testcase {
         $sectioncreated = $DB->record_exists('course_sections', array('course' => $created->id, 'section' => 0));
         $this->assertTrue($sectioncreated);
 
-        // Ensure blocks have been associated to the course.
-        $blockcount = $DB->count_records('block_instances', array('parentcontextid' => $context->id));
-        $this->assertGreaterThan(0, $blockcount);
-
         // Ensure that the shortname isn't duplicated.
         try {
             $created = create_course($course);
@@ -3085,7 +3081,6 @@ class core_course_courselib_testcase extends advanced_testcase {
         $this->assertTrue($adminoptions->publish);
         $this->assertTrue($adminoptions->reset);
         $this->assertTrue($adminoptions->roles);
-        $this->assertTrue($adminoptions->grades);
     }
 
     /**
@@ -3118,7 +3113,6 @@ class core_course_courselib_testcase extends advanced_testcase {
         $this->assertFalse($adminoptions->publish);
         $this->assertFalse($adminoptions->reset);
         $this->assertFalse($adminoptions->roles);
-        $this->assertTrue($adminoptions->grades);
 
         $CFG->enablebadges = false;
         $adminoptions = course_get_user_administration_options($course, $context);
index 9015dbe..d991ac7 100644 (file)
@@ -558,6 +558,7 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $coursedata['summary'] = 'Course 1 description';
         $coursedata['summaryformat'] = FORMAT_MOODLE;
         $course1  = self::getDataGenerator()->create_course($coursedata);
+
         $generatedcourses[$course1->id] = $course1;
         $course2  = self::getDataGenerator()->create_course();
         $generatedcourses[$course2->id] = $course2;
@@ -642,8 +643,17 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $generatedcourses = array();
         $coursedata1['fullname'] = 'FIRST COURSE';
         $course1  = self::getDataGenerator()->create_course($coursedata1);
+
+        $page = new moodle_page();
+        $page->set_course($course1);
+        $page->blocks->add_blocks([BLOCK_POS_LEFT => ['news_items'], BLOCK_POS_RIGHT => []], 'course-view-*');
+
         $coursedata2['fullname'] = 'SECOND COURSE';
         $course2  = self::getDataGenerator()->create_course($coursedata2);
+
+        $page = new moodle_page();
+        $page->set_course($course2);
+        $page->blocks->add_blocks([BLOCK_POS_LEFT => ['news_items'], BLOCK_POS_RIGHT => []], 'course-view-*');
         // Search by name.
         $results = core_course_external::search_courses('search', 'FIRST');
         $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
@@ -1607,20 +1617,66 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         // Hidden activity.
         $assign = self::getDataGenerator()->create_module('assign', $record, $options);
 
+        $outcomescale = 'Distinction, Very Good, Good, Pass, Fail';
+
+        // Insert a custom grade scale to be used by an outcome.
+        $gradescale = new grade_scale();
+        $gradescale->name        = 'gettcoursemodulescale';
+        $gradescale->courseid    = $course->id;
+        $gradescale->userid      = 0;
+        $gradescale->scale       = $outcomescale;
+        $gradescale->description = 'This scale is used to mark standard assignments.';
+        $gradescale->insert();
+
+        // Insert an outcome.
+        $data = new stdClass();
+        $data->courseid = $course->id;
+        $data->fullname = 'Team work';
+        $data->shortname = 'Team work';
+        $data->scaleid = $gradescale->id;
+        $outcome = new grade_outcome($data, false);
+        $outcome->insert();
+
+        $outcomegradeitem = new grade_item();
+        $outcomegradeitem->itemname = $outcome->shortname;
+        $outcomegradeitem->itemtype = 'mod';
+        $outcomegradeitem->itemmodule = 'assign';
+        $outcomegradeitem->iteminstance = $assign->id;
+        $outcomegradeitem->outcomeid = $outcome->id;
+        $outcomegradeitem->cmid = 0;
+        $outcomegradeitem->courseid = $course->id;
+        $outcomegradeitem->aggregationcoef = 0;
+        $outcomegradeitem->itemnumber = 1; // The activity's original grade item will be 0.
+        $outcomegradeitem->gradetype = GRADE_TYPE_SCALE;
+        $outcomegradeitem->scaleid = $outcome->scaleid;
+        $outcomegradeitem->insert();
+
+        $assignmentgradeitem = grade_item::fetch(
+            array(
+                'itemtype' => 'mod',
+                'itemmodule' => 'assign',
+                'iteminstance' => $assign->id,
+                'itemnumber' => 0,
+                'courseid' => $course->id
+            )
+        );
+        $outcomegradeitem->set_parent($assignmentgradeitem->categoryid);
+        $outcomegradeitem->move_after_sortorder($assignmentgradeitem->sortorder);
+
         // Test admin user can see the complete hidden activity.
         $result = core_course_external::get_course_module($assign->cmid);
         $result = external_api::clean_returnvalue(core_course_external::get_course_module_returns(), $result);
 
         $this->assertCount(0, $result['warnings']);
         // Test we retrieve all the fields.
-        $this->assertCount(26, $result['cm']);
+        $this->assertCount(27, $result['cm']);
         $this->assertEquals($record['name'], $result['cm']['name']);
         $this->assertEquals($options['idnumber'], $result['cm']['idnumber']);
         $this->assertEquals(100, $result['cm']['grade']);
         $this->assertEquals(0.0, $result['cm']['gradepass']);
         $this->assertEquals('submissions', $result['cm']['advancedgrading'][0]['area']);
         $this->assertEmpty($result['cm']['advancedgrading'][0]['method']);
-        $this->assertArrayNotHasKey('outcomes', $result['cm']);
+        $this->assertEquals($outcomescale, $result['cm']['outcomes'][0]['scale']);
 
         $student = $this->getDataGenerator()->create_user();
         $studentrole = $DB->get_record('role', array('shortname' => 'student'));
@@ -1796,7 +1852,7 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
                 $navoptions->{$option['name']} = $option['available'];
             }
             if ($course['id'] == SITEID) {
-                $this->assertCount(7, $course['options']);
+                $this->assertCount(8, $course['options']);
                 $this->assertTrue($navoptions->blogs);
                 $this->assertFalse($navoptions->notes);
                 $this->assertFalse($navoptions->participants);
@@ -1804,12 +1860,15 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
                 $this->assertTrue($navoptions->tags);
                 $this->assertFalse($navoptions->search);
                 $this->assertTrue($navoptions->calendar);
+                $this->assertTrue($navoptions->competencies);
             } else {
-                $this->assertCount(4, $course['options']);
+                $this->assertCount(6, $course['options']);
                 $this->assertTrue($navoptions->blogs);
                 $this->assertFalse($navoptions->notes);
                 $this->assertTrue($navoptions->participants);
                 $this->assertTrue($navoptions->badges);
+                $this->assertTrue($navoptions->grades);
+                $this->assertTrue($navoptions->competencies);
             }
         }
     }
@@ -1859,9 +1918,8 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
                 $this->assertFalse($adminoptions->publish);
                 $this->assertFalse($adminoptions->reset);
                 $this->assertFalse($adminoptions->roles);
-                $this->assertFalse($adminoptions->grades);
             } else {
-                $this->assertCount(15, $course['options']);
+                $this->assertCount(14, $course['options']);
                 $this->assertFalse($adminoptions->update);
                 $this->assertFalse($adminoptions->filters);
                 $this->assertFalse($adminoptions->reports);
@@ -1876,7 +1934,6 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
                 $this->assertFalse($adminoptions->publish);
                 $this->assertFalse($adminoptions->reset);
                 $this->assertFalse($adminoptions->roles);
-                $this->assertTrue($adminoptions->grades);
             }
         }
     }
index aadbd89..ccf39f7 100644 (file)
@@ -149,9 +149,10 @@ switch ($mode) {
             if ($course->id == SITEID) {
                 $activenode = $PAGE->navigation->find('user' . $user->id, null);
             } else {
-                $currentcoursenode = $PAGE->navigation->find('currentcourse', null);
+                $currentcoursenode = $PAGE->navigation->find($course->id, navigation_node::TYPE_COURSE);
                 $activenode = $currentcoursenode->find_active_node();
             }
+
             // Check to see if the active node is a user name.
             if (!preg_match('/^user\d{0,}$/', $activenode->key)) { // No user name found.
                 $userurl = new moodle_url('/user/view.php', array('id' => $user->id, 'course' => $course->id));
index 64f3354..5e673ec 100644 (file)
@@ -75,7 +75,7 @@ class tool_provider_testcase extends advanced_testcase {
      */
     public function test_constructor_with_non_existent_tool() {
         $this->expectException('dml_exception');
-        new tool_provider(1);
+        new tool_provider(-1);
     }
 
     /**
index 82e7f11..7a4bbd9 100644 (file)
@@ -20,16 +20,16 @@ Feature: Manage enrollments from participants page
       | teacher1 | C1 | editingteacher |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Participants" node in "Current course > C1"
+    And I navigate to "Participants" node in "My courses > C1"
 
   Scenario: Check the participants link when "All partipants" selected
     Given I select "All participants" from the "roleid" singleselect
-    When I follow "Edit"
+    When I click on "Edit" "link" in the "region-main" "region"
     Then I should see "Enrolled users" in the "h2" "css_element"
     And the field "Role" matches value "All"
 
   Scenario: Check the participants link when "Student" selected
     Given I select "Student" from the "roleid" singleselect
-    When I follow "Edit"
+    When I click on "Edit" "link" in the "region-main" "region"
     Then I should see "Enrolled users" in the "h2" "css_element"
     And the field "Role" matches value "Student"
index 7fce284..46324fc 100644 (file)
@@ -1016,8 +1016,6 @@ class core_files_renderer extends plugin_renderer_base {
 
                     <div class="controls"><select></select></div>
                 </div>';
-        // HACK to prevent browsers from automatically inserting the user's password into the wrong fields.
-        $rv .= prevent_form_autofill_password();
         $rv .= '
                 <div class="fp-login-input control-group clearfix">
                     <label class="control-label"></label>
index 9143b75..c610bfa 100644 (file)
@@ -16,7 +16,7 @@ Feature: Course files
     And I am on site homepage
     And I follow "Course 1"
     Then I should see "Legacy course files"
-    And I follow "Legacy course files"
+    And I navigate to "Legacy course files" node in "Course administration"
     And I press "Edit legacy course files"
     And "Add..." "link" should be visible
     And "Create folder" "link" should be visible
@@ -33,7 +33,7 @@ Feature: Course files
     And I am on site homepage
     And I follow "Course 1"
     Then I should see "Legacy course files"
-    And I follow "Legacy course files"
+    And I navigate to "Legacy course files" node in "Course administration"
     And I press "Edit legacy course files"
     And "Add..." "link" should not be visible
     And "Create folder" "link" should not be visible
index 5670d2c..db6d0e9 100644 (file)
@@ -22,7 +22,7 @@ Feature: I need to export grades as text
       | assign | C1 | a2 | Test assignment name 2 | Submit your online text | 1 |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "80.00" to the user "Student 1" for the grade item "Test assignment name"
     And I press "Save changes"
@@ -76,4 +76,4 @@ Feature: I need to export grades as text
     And I should see "80.00 %"
     And I should see "B-"
     And I should not see "40.00 %"
-    And I should not see ",F,"
\ No newline at end of file
+    And I should not see ",F,"
index 9048755..6530065 100644 (file)
@@ -21,7 +21,7 @@ Feature: I need to export grades as xml
       | assign | C1 | a1 | Test assignment name | Submit something! |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "80.00" to the user "Student 1" for the grade item "Test assignment name"
     And I press "Save changes"
index 71dad25..1ee18cf 100644 (file)
@@ -55,7 +55,7 @@ Feature: Using the AJAX grading feature of Grader report to update grades and fe
       | grade_report_showquickfeedback | 0 |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I click on student "Student 2" for grade item "Item VU"
     Then I should see a grade field for "Student 2" and grade item "Item VU"
     And I should not see a feedback field for "Student 2" and grade item "Item VU"
@@ -107,7 +107,7 @@ Feature: Using the AJAX grading feature of Grader report to update grades and fe
       | grade_report_showquickfeedback | 1 |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I click on student "Student 2" for grade item "Item VU"
     Then I should see a grade field for "Student 2" and grade item "Item VU"
     And I should see a feedback field for "Student 2" and grade item "Item VU"
@@ -142,7 +142,7 @@ Feature: Using the AJAX grading feature of Grader report to update grades and fe
       | grade_report_showquickfeedback | 1 |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I click on student "Student 2" for grade item "Item VU"
     Then I should see a grade field for "Student 2" and grade item "Item VU"
     And I should see a feedback field for "Student 2" and grade item "Item VU"
@@ -162,7 +162,7 @@ Feature: Using the AJAX grading feature of Grader report to update grades and fe
       | grade_report_showquickfeedback | 1 |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     Then I should not see a grade field for "Student 2" and grade item "Item VL"
     And I should not see a feedback field for "Student 2" and grade item "Item VL"
@@ -193,7 +193,7 @@ Feature: Using the AJAX grading feature of Grader report to update grades and fe
       | grade_report_showquickfeedback | 1 |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I change window size to "large"
     And I set "=[[i1]] + [[i3]] + [[gsc]]" calculation for grade item "Calc Item" with idnumbers:
index db1d5b7..09ecf62 100644 (file)
@@ -46,7 +46,7 @@ Feature: We can change what we are viewing on the grader report
     And I log out
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "80.00" to the user "Student 1" for the grade item "Test assignment name 1"
     And I give the grade "90.00" to the user "Student 1" for the grade item "Test assignment name 2"
@@ -60,7 +60,7 @@ Feature: We can change what we are viewing on the grader report
     And I open "Test assignment name 2" actions menu
     And I click on "Hide" "link" in the "Test assignment name 2" activity
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I select "Grader report" from the "Grade report" singleselect
     And I should see "Test assignment name 1"
     And I should see "Test assignment name 2"
@@ -97,7 +97,7 @@ Feature: We can change what we are viewing on the grader report
     And I log out
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I select "Grader report" from the "Grade report" singleselect
     And I should see "Test assignment name 1"
     And I should see "Test assignment name 2"
index 0cfc905..a488922 100644 (file)
@@ -30,7 +30,7 @@ Feature: A teacher checks the grade history report in a course
     And I add a "Assignment" to section "1" and I fill the form with:
       | Assignment name | Rewarding assignment |
       | Description | After writing your behat test go grab a beer! |
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "50.00" to the user "Student 1" for the grade item "The greatest assignment ever"
     And I give the grade "60.00" to the user "Student 1" for the grade item "Rewarding assignment"
@@ -40,7 +40,7 @@ Feature: A teacher checks the grade history report in a course
     And I log out
     And I log in as "teacher2"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "70.00" to the user "Student 1" for the grade item "The greatest assignment ever"
     And I give the grade "80.00" to the user "Student 1" for the grade item "Rewarding assignment"
index 22aba02..f2158da 100644 (file)
@@ -52,7 +52,7 @@ Feature: We can use Single view
       | gradereport/singleview:view | Allow      | teacher  | Course        | C1        |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
 
   @javascript
   Scenario: I can update grades, add feedback and exclude grades.
@@ -97,7 +97,7 @@ Feature: We can use Single view
     And I log out
     And I log in as "teacher2"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I click on "Single view" "option"
     And I click on "Student 4" "option"
     And the "Exclude for Test assignment one" "checkbox" should be disabled
index 01794bf..d7b270c 100644 (file)
@@ -35,7 +35,7 @@ Feature: View the user report as the student will see it
     And I navigate to "Gradebook setup" node in "Course administration"
     And I hide the grade item "Test assignment six"
     And I hide the grade item "Sub category 2"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I change window size to "large"
     And I give the grade "80.00" to the user "Student 1" for the grade item "Test assignment one"
@@ -83,7 +83,7 @@ Feature: View the user report as the student will see it
     And I log out
     And I log in as "student1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     Then the following should exist in the "user-grade" table:
       | Grade item              | Calculated weight | Grade  | Range | Percentage | Contribution to course total |
       | Test assignment one     | -                 | 80.00  | 0–100 | 80.00 %    | -                            |
@@ -121,7 +121,7 @@ Feature: View the user report as the student will see it
     And I log out
     And I log in as "student1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     Then the following should exist in the "user-grade" table:
       | Grade item              | Calculated weight | Grade  | Range | Percentage | Contribution to course total |
       | Test assignment one     | 50.00 %           | 80.00  | 0–100 | 80.00 %    | 26.67 %                      |
@@ -159,7 +159,7 @@ Feature: View the user report as the student will see it
     And I log out
     And I log in as "student1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     Then the following should exist in the "user-grade" table:
       | Grade item              | Calculated weight | Grade  | Range | Percentage | Contribution to course total |
       | Test assignment one     | 50.00 %           | 80.00  | 0–100 | 80.00 %    | 13.33 %                      |
@@ -204,7 +204,7 @@ Feature: View the user report as the student will see it
     And I log out
     And I log in as "student1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     Then the following should exist in the "user-grade" table:
       | Grade item              | Calculated weight | Grade  | Range | Percentage | Contribution to course total |
       | Test assignment one     | 50.00 %           | 80.00  | 0–100 | 80.00 %    | 13.33 %                      |
index 9bc1f8f..7f7b25e 100644 (file)
@@ -12,7 +12,7 @@ Feature: We can use the user report
       Given I log in as "admin"
       And I am on site homepage
       And I follow "Course 1"
-      And I navigate to "Grades" node in "Course administration"
+      And I click on "Grades" "link" in the "Navigation" "block"
       And I select "User report" from the "Grade report" singleselect
       And I select "All users (0)" from the "Select all or one user" singleselect
       Then I should see "No students enrolled in this course yet"
index e01b928..1618704 100644 (file)
@@ -20,7 +20,7 @@ Feature: Site settings can be used to hide parts of the gradebook UI
     And I log in as "admin"
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
 
   @javascript
@@ -32,7 +32,7 @@ Feature: Site settings can be used to hide parts of the gradebook UI
     And I press "Save changes"
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I click on "Edit  assign Assignment1" "link"
     And I should not see "Minimum grade"
 
@@ -44,7 +44,7 @@ Feature: Site settings can be used to hide parts of the gradebook UI
     And I press "Save changes"
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     Then "Edit calculation for   Course total" "link" should not exist
 
   @javascript
@@ -55,5 +55,5 @@ Feature: Site settings can be used to hide parts of the gradebook UI
     And I press "Save changes"
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And "tr .course input[type='text']" "css_element" should not exist
index 54c2cb7..dcbbd5c 100644 (file)
@@ -42,7 +42,7 @@ Feature: We can use calculated grade totals
     And I log out
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I change window size to "large"
     And I give the grade "60.00" to the user "Student 1" for the grade item "Test assignment one"
@@ -253,12 +253,12 @@ Feature: We can use calculated grade totals
     And I log in as "student1"
     And I follow "Grades" in the user menu
     Then I should see "114.82 (18.27 %)" in the "overview-grade" "table"
-    And I follow "Course 1"
+    And I click on "Course 1" "link" in the "region-main" "region"
     And "Test outcome item one" row "Grade" column of "user-grade" table should contain "Excellent (100.00 %)"
     And I log out
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I expand "Setup" node
     And I follow "Gradebook setup"
     And I set the following settings for grade item "Test outcome item one":
@@ -267,12 +267,12 @@ Feature: We can use calculated grade totals
     And I log in as "student1"
     And I follow "Grades" in the user menu
     Then I should see "114.00 (18.39 %)" in the "overview-grade" "table"
-    And I follow "Course 1"
+    And I click on "Course 1" "link" in the "region-main" "region"
     And "Test outcome item one" row "Grade" column of "user-grade" table should contain "Excellent (100.00 %)"
     And I log out
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I expand "Setup" node
     And I follow "Gradebook setup"
     And I set the following settings for grade item "Course 1":
@@ -282,7 +282,7 @@ Feature: We can use calculated grade totals
     And I log in as "student1"
     And I follow "Grades" in the user menu
     Then I should see "110.00 (17.74 %)" in the "overview-grade" "table"
-    And I follow "Course 1"
+    And I click on "Course 1" "link" in the "region-main" "region"
     And "Test outcome item one" row "Grade" column of "user-grade" table should contain "Excellent (100.00 %)"
 
   Scenario: Natural aggregation on outcome items with modified weights
@@ -297,7 +297,7 @@ Feature: We can use calculated grade totals
     And the following "grade items" exist:
       | itemname              | course | outcome | gradetype | scale      |
       | Test outcome item one | C1     | OT1     | Scale     | Test Scale |
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I expand "Setup" node
     And I follow "Gradebook setup"
     And I set the following settings for grade item "Course 1":
@@ -318,7 +318,7 @@ Feature: We can use calculated grade totals
     And I log in as "student1"
     And I follow "Grades" in the user menu
     Then I should see "4.00 (100.00 %)" in the "overview-grade" "table"
-    And I follow "Course 1"
+    And I click on "Course 1" "link" in the "region-main" "region"
     And "Test outcome item one" row "Grade" column of "user-grade" table should contain "Excellent (100.00 %)"
 
   Scenario: Natural aggregation
@@ -363,7 +363,7 @@ Feature: We can use calculated grade totals
     And I log in as "student1"
     And I follow "Grades" in the user menu
     And I should see "113.75 (23.45 %)" in the "overview-grade" "table"
-    And I follow "Course 1"
+    And I click on "Course 1" "link" in the "region-main" "region"
     And the following should exist in the "user-grade" table:
       | Grade item | Calculated weight | Grade | Range | Contribution to course total |
       | Test assignment six | 70.00 % | 5.00 (50.00 %) | 0–10 | 1.80 % |
@@ -379,7 +379,7 @@ Feature: We can use calculated grade totals
     And I log in as "admin"
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I set the following settings for grade item "Sub category 1":
       | Aggregation          | Natural |
@@ -553,7 +553,7 @@ Feature: We can use calculated grade totals
     And I log in as "student1"
     And I follow "Grades" in the user menu
     And I should see "45.00 (13.85 %)" in the "overview-grade" "table"
-    And I follow "Course 1"
+    And I click on "Course 1" "link" in the "region-main" "region"
     And the following should exist in the "user-grade" table:
       | Grade item            | Calculated weight | Grade           | Contribution to course total |
       | Test assignment six   | 0.00 %            | 5.00 (50.00 %)  | 0.00 %                         |
index fd792e0..5f2e6e1 100644 (file)
@@ -35,7 +35,7 @@ Feature: Changing the aggregation of an item affects its weight and extra credit
       | grade_aggregations_visible | Mean of grades,Weighted mean of grades,Simple weighted mean of grades,Mean of grades (with extra credits),Median of grades,Lowest grade,Highest grade,Mode of grades,Natural |
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I navigate to "Grader report" node in "Grade administration"
     And I turn editing mode on
     And I follow "Edit   Cat mean"
index e52ab6a..eefea37 100644 (file)
@@ -24,7 +24,7 @@ Feature: Average grades are displayed in the gradebook
     And I am on site homepage
     And I follow "Course 1"
     # Enable averages
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I navigate to "Course grade settings" node in "Grade administration > Setup"
     And I set the following fields to these values:
       | Show average | Show |
@@ -52,7 +52,7 @@ Feature: Average grades are displayed in the gradebook
 
   Scenario: Grade a grade item and ensure the results display correctly in the gradebook
     # Check the admin grade table
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     Then I should see "50.00" in the ".avg.r0.lastrow .c1" "css_element"
     Then I should see "50.00" in the ".avg.r0.lastrow .c2" "css_element"
     And I log out
@@ -61,7 +61,7 @@ Feature: Average grades are displayed in the gradebook
     And I log in as "student1"
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     Then I should see "50.00" in the ".level2.column-grade" "css_element"
     Then I should see "50.00" in the ".level2.column-average" "css_element"
     And I log out
index 3eb9dfe..d39b632 100644 (file)
@@ -21,7 +21,7 @@ Feature: Calculated grade items can be used in the gradebook
     And I log in as "admin"
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I navigate to "Gradebook setup" node in "Grade administration > Setup"
 
   @javascript
index 1199365..6271c9f 100644 (file)
@@ -22,7 +22,7 @@ Feature: Gradebook calculations for calculated grade items before the fix 201506
     And I log in as "admin"
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I navigate to "Gradebook setup" node in "Grade administration > Setup"
 
   @javascript
index e899835..97c4fff 100644 (file)
@@ -30,7 +30,7 @@ Feature: We can understand the gradebook user report
     And I log out
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "60.00" to the user "Student 1" for the grade item "Test assignment one"
     And I give the grade "20.00" to the user "Student 1" for the grade item "Test assignment two"
index 7f60a15..e59d032 100644 (file)
@@ -21,7 +21,7 @@ Feature: Extra credit contributions are normalised when going out of bounds
       | grade_aggregations_visible | Simple weighted mean of grades,Mean of grades (with extra credits),Natural |
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I navigate to "Gradebook setup" node in "Grade administration > Setup"
     And I press "Add grade item"
     And I set the following fields to these values:
@@ -47,7 +47,7 @@ Feature: Extra credit contributions are normalised when going out of bounds
     And I log out
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "80.00" to the user "Student 1" for the grade item "Manual item 1"
     And I give the grade "10.00" to the user "Student 1" for the grade item "Manual item 2"
index edcc64a..51f127d 100644 (file)
@@ -22,7 +22,7 @@ Feature: We can change the maximum and minimum number of points for manual items
     And I log in as "teacher1"
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I navigate to "Gradebook setup" node in "Grade administration > Setup"
     And I press "Add grade item"
     And I set the following fields to these values:
@@ -37,7 +37,7 @@ Feature: We can change the maximum and minimum number of points for manual items
 
   Scenario: Change maximum number of points on a graded item.
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "10.00" to the user "Student 1" for the grade item "Manual item 1"
     And I give the grade "8.00" to the user "Student 2" for the grade item "Manual item 1"
index a85f780..519e750 100644 (file)
@@ -35,7 +35,7 @@ Feature: Student and teacher's view of aggregated grade items is consistent when
     When I log out
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "50.00" to the user "Student 1" for the grade item "Test assignment one"
     And I give the grade "50.00" to the user "Student 1" for the grade item "Test assignment three"
@@ -44,7 +44,7 @@ Feature: Student and teacher's view of aggregated grade items is consistent when
       | Hidden | 1 |
     And I press "Save changes"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I select "User report" from the "Grade report" singleselect
     And I select "Myself" from the "View report as" singleselect
     And I select "Student 1" from the "Select all or one user" singleselect
@@ -57,7 +57,7 @@ Feature: Student and teacher's view of aggregated grade items is consistent when
     When I log out
     And I log in as "student1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I navigate to "User report" node in "Grade administration"
     Then the following should exist in the "user-grade" table:
       | Grade item | Calculated weight | Grade | Range | Percentage | Contribution to course total |
index 73c04f1..868a2ce 100644 (file)
@@ -22,7 +22,7 @@ Feature: We can customise the letter boundary of a course.
       | assign | C1 | a1 | Test assignment one | Submit something! | 100 |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I select "Course grade settings" from the "Grade report" singleselect
     And I set the following fields to these values:
       | Grade display type | Letter |
index e451824..bd81919 100644 (file)
@@ -23,7 +23,7 @@ Feature: We can customise the letter boundary of a course.
       | assign | C1 | a1 | Test assignment one | Submit something! | 100 |
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I select "Course grade settings" from the "Grade report" singleselect
     And I set the following fields to these values:
       | Grade display type | Letter |
index a886c39..7d720a4 100644 (file)
@@ -27,7 +27,7 @@ Feature: We can use a minimum grade different than zero
       | grade_aggregations_visible | Mean of grades,Weighted mean of grades,Simple weighted mean of grades,Mean of grades (with extra credits),Median of grades,Lowest grade,Highest grade,Mode of grades,Natural |
     And I am on site homepage
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I navigate to "Gradebook setup" node in "Grade administration > Setup"
     And I press "Add grade item"
     And I set the following fields to these values:
@@ -86,7 +86,7 @@ Feature: We can use a minimum grade different than zero
     And I log out
     And I log in as "teacher1"
     And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     When I give the grade "-25.00" to the user "Student 1" for the grade item "Manual item 1"
     And I give the grade "50.00" to the user "Student 1" for the grade item "Manual item 2"
index 971461a..f38dbfe 100644 (file)
@@ -26,7 +26,7 @@ Feature: We can choose what min or max grade to use when aggregating grades.
       | grade_minmaxtouse | Min and max grades as specified in grade item settings |
     And I am on site homepage
     And I follow "C1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I navigate to "Gradebook setup" node in "Grade administration > Setup"
     And I press "Add grade item"
     And I set the following fields to these values:
@@ -68,7 +68,7 @@ Feature: We can choose what min or max grade to use when aggregating grades.
     And I log out
     And I log in as "teacher1"
     And I follow "C1"
-    And I navigate to "Grades" node in "Course administration"
+    And I click on "Grades" "link" in the "Navigation" "block"
     And I turn editing mode on
     And I give the grade "75.00" to the user "Student 1" for the grade item "MI 1"
     And I give the grade "25.00" to the user "Student 1" for the grade item "MI 2"