Merge branch 'MDL-55188-master' of git://github.com/abgreeve/moodle
authorDavid Monllao <davidm@moodle.com>
Mon, 30 Jul 2018 15:33:21 +0000 (17:33 +0200)
committerDavid Monllao <davidm@moodle.com>
Mon, 30 Jul 2018 15:33:21 +0000 (17:33 +0200)
16 files changed:
admin/tool/policy/tests/behat/consent.feature
auth/shibboleth/auth.php
auth/shibboleth/lang/en/auth_shibboleth.php
auth/shibboleth/lib.php [new file with mode: 0644]
auth/shibboleth/settings.php
auth/tests/behat/displayloginfailures.feature
auth/tests/behat/validateagedigitalconsentmap.feature
backup/moodle2/tests/behat/import_multiple_times.feature
grade/edit/letter/index.php
lib/gradelib.php
lib/outputrenderers.php
lib/tests/gradelib_test.php
lib/upgrade.txt
mod/lesson/locallib.php
question/templates/tag_condition.mustache
user/tests/behat/view_participants.feature

index d345b23..2b9b026 100644 (file)
@@ -364,7 +364,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
     And I log out
     # Create new policy document.
     And I log in as "admin"
-    And I navigate to "Manage policies" node in "Site administration > Privacy and policies"
+    And I navigate to "Manage policies" node in "Site administration > Users > Privacy and policies"
     And I should see "Policies and agreements"
     And I should see "New policy"
     And I follow "New policy"
@@ -419,7 +419,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
     And I log out
     # Create new version of the policy document.
     And I log in as "admin"
-    And I navigate to "Manage policies" node in "Site administration > Privacy and policies"
+    And I navigate to "Manage policies" node in "Site administration > Users > Privacy and policies"
     When I follow "Actions"
     Then I should see "View"
     And I should see "Edit"
index fe6244c..39ca032 100644 (file)
@@ -277,6 +277,32 @@ class auth_plugin_shibboleth extends auth_plugin_base {
             return;
         }
     }
+
+    /**
+     * Return a list of identity providers to display on the login page.
+     *
+     * @param string $wantsurl The requested URL.
+     * @return array List of arrays with keys url, iconurl and name.
+     */
+    public function loginpage_idp_list($wantsurl) {
+        $config = get_config('auth_shibboleth');
+        $result = [];
+
+        // Before displaying the button check that Shibboleth is set-up correctly.
+        if (empty($config->user_attribute)) {
+            return $result;
+        }
+
+        $url = new moodle_url('/auth/shibboleth/index.php');
+        $iconurl = moodle_url::make_pluginfile_url(context_system::instance()->id,
+                                                   'auth_shibboleth',
+                                                   'logo',
+                                                   null,
+                                                   '/',
+                                                   $config->auth_logo);
+        $result[] = ['url' => $url, 'iconurl' => $iconurl, 'name' => $config->login_name];
+        return $result;
+    }
 }
 
 
index 659e4d1..8ef9ec1 100644 (file)
@@ -25,6 +25,8 @@
 
 $string['auth_shib_auth_method'] = 'Authentication method name';
 $string['auth_shib_auth_method_description'] = 'Provide a name for the Shibboleth authentication method that is familiar to your users. This could be the name of your Shibboleth federation, e.g. <tt>SWITCHaai Login</tt> or <tt>InCommon Login</tt> or similar.';
+$string['auth_shib_auth_logo'] = 'Authentication method logo';
+$string['auth_shib_auth_logo_description'] = 'Provide a logo for the Shibboleth authentication method that is familiar to your users. This could be the logo of your Shibboleth federation, e.g. <tt>SWITCHaai Login</tt> or <tt>InCommon Login</tt> or similar.';
 $string['auth_shib_contact_administrator'] = 'In case you are not associated with the given organizations and you need access to a course on this server, please contact the <a href="mailto:{$a}">Moodle Administrator</a>.';
 $string['auth_shibbolethdescription'] = 'Using this method users are created and authenticated using <a href="http://shibboleth.internet2.edu/">Shibboleth</a>.<br />Be sure to read the <a href="../auth/shibboleth/README.txt">README</a> for Shibboleth on how to set up your Moodle with Shibboleth';
 $string['auth_shibboleth_errormsg'] = 'Please select the organization you are member of!';
diff --git a/auth/shibboleth/lib.php b/auth/shibboleth/lib.php
new file mode 100644 (file)
index 0000000..f8ac757
--- /dev/null
@@ -0,0 +1,64 @@
+<?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/>.
+
+/**
+ * This file contains the hooks for the Shibboleth authentication module.
+ *
+ * @package auth_shibboleth
+ * @copyright 2018 Fabrice Ménard
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Serves the logo file settings.
+ *
+ * @param stdClass $course course object
+ * @param stdClass $cm course module object
+ * @param stdClass $context context object
+ * @param string $filearea file area
+ * @param array $args extra arguments
+ * @param bool $forcedownload whether or not force download
+ * @param array $options additional options affecting the file serving
+ * @return bool false if file not found, does not return if found - justsend the file
+ */
+function auth_shibboleth_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
+    if ($context->contextlevel != CONTEXT_SYSTEM) {
+        return false;
+    }
+
+    if ($filearea !== 'logo' ) {
+        return false;
+    }
+
+    $itemid = 0;
+
+    $filename = array_pop($args);
+    if (!$args) {
+        $filepath = '/';
+    } else {
+        $filepath = '/'.implode('/', $args).'/';
+    }
+
+    $fs = get_file_storage();
+    $file = $fs->get_file($context->id, 'auth_shibboleth', $filearea, $itemid, $filepath, $filename);
+    if (!$file) {
+        return false;
+    }
+
+    send_stored_file($file, null, 0, $forcedownload, $options);
+}
index c901378..e4b4c3a 100644 (file)
@@ -63,6 +63,11 @@ if ($ADMIN->fulltree) {
             get_string('auth_shib_auth_method', 'auth_shibboleth'),
             get_string('auth_shib_auth_method_description', 'auth_shibboleth'), 'Shibboleth Login', PARAM_RAW_TRIMMED));
 
+    // Authentication method logo.
+    $settings->add(new admin_setting_configstoredfile('auth_shibboleth/auth_logo',
+                get_string('auth_shib_auth_logo', 'auth_shibboleth'),
+                get_string('auth_shib_auth_logo_description', 'auth_shibboleth'), 'logo', 0, ['accepted_types' => ['image']]));
+
     // Login directions.
     $settings->add(new admin_setting_configtextarea('auth_shibboleth/auth_instructions',
             get_string('auth_shib_instructions_key', 'auth_shibboleth'),
index 50b9ec6..4b6e2a9 100644 (file)
@@ -25,11 +25,11 @@ Feature: Test the 'showlogfailures' feature works.
     And I set the field "Password" to "teacher1"
     And I press "Log in"
     # Confirm the notices are displayed.
-    Then I should see "1 failed logins since your last login" in the "nav.navbar" "css_element"
+    Then I should see "1 failed logins since your last login" in the ".navbar" "css_element"
     And I should see "1 failed logins since your last login" in the "page-footer" "region"
     # Confirm the notices disappear when navigating to another page.
     And I am on homepage
-    And I should not see "1 failed logins since your last login" in the "nav.navbar" "css_element"
+    And I should not see "1 failed logins since your last login" in the ".navbar" "css_element"
     And I should not see "1 failed logins since your last login" in the "page-footer" "region"
 
   # Given the user has at least one failed login attempt, when they login, then they should see both header and footer notices.
@@ -46,10 +46,10 @@ Feature: Test the 'showlogfailures' feature works.
     And I set the field "Password" to "admin"
     And I press "Log in"
     # Confirm the notices are displayed.
-    Then I should see "1 failed logins since your last login" in the "nav.navbar" "css_element"
+    Then I should see "1 failed logins since your last login" in the ".navbar" "css_element"
     And I should see "1 failed logins since your last login (Logs)" in the "page-footer" "region"
     # Confirm that the link works and that the notices disappear when navigating to another page.
     And I click on "Logs" "link" in the "page-footer" "region"
     And I should see "User login failed" in the "table.reportlog" "css_element"
-    And I should not see "1 failed logins since your last login" in the "nav.navbar" "css_element"
+    And I should not see "1 failed logins since your last login" in the ".navbar" "css_element"
     And I should not see "1 failed logins since your last login (Logs)" in the "page-footer" "region"
index 9fe1753..7381991 100644 (file)
@@ -6,7 +6,7 @@ Feature: Test validation of 'Age of digital consent' setting.
 
   Background:
     Given I log in as "admin"
-    And I navigate to "Privacy settings" node in "Site administration > Privacy and policies"
+    And I navigate to "Privacy settings" node in "Site administration > Users > Privacy and policies"
 
   Scenario: Admin provides valid value for 'Age of digital consent'.
     Given I set the field "s__agedigitalconsentmap" to multiline:
index ccf6dd1..98d495f 100644 (file)
@@ -27,10 +27,10 @@ Feature: Import course's content's twice
     And I log in as "teacher1"
 
   Scenario: Import course's contents to another course
-    Given I am on "Course 2" course homepage with editing mode on
+    Given I am on "Course 2" course homepage
     And I should not see "Online users"
     And I should not see "Test quiz"
-    And  I import "Course 1" course into "Course 2" course using this options:
+    And I import "Course 1" course into "Course 2" course using this options:
     And I am on "Course 2" course homepage
     And I should see "Online users"
     And I should see "Test quiz"
index 393afe4..dedd4bf 100644 (file)
@@ -141,7 +141,7 @@ if (!$edit) {
         if (!$admin and empty($data->override)) {
             $records = $DB->get_records('grade_letters', array('contextid' => $context->id));
             foreach ($records as $record) {
-                $DB->delete_record('grade_letters', array('id' => $record->id));
+                $DB->delete_records('grade_letters', array('id' => $record->id));
                 // Trigger the letter grade deleted event.
                 $event = \core\event\grade_letter_deleted::create(array(
                     'objectid' => $record->id,
index cb31417..9e37c42 100644 (file)
@@ -1401,7 +1401,7 @@ function remove_grade_letters($context, $showfeedback) {
 
     $records = $DB->get_records('grade_letters', array('contextid' => $context->id));
     foreach ($records as $record) {
-        $DB->delete_record('grade_letters', array('id' => $record->id));
+        $DB->delete_records('grade_letters', array('id' => $record->id));
         // Trigger the letter grade deleted event.
         $event = \core\event\grade_letter_deleted::create(array(
             'objectid' => $record->id,
@@ -1473,7 +1473,7 @@ function grade_course_category_delete($categoryid, $newparentid, $showfeedback)
     $context = context_coursecat::instance($categoryid);
     $records = $DB->get_records('grade_letters', array('contextid' => $context->id));
     foreach ($records as $record) {
-        $DB->delete_record('grade_letters', array('id' => $record->id));
+        $DB->delete_records('grade_letters', array('id' => $record->id));
         // Trigger the letter grade deleted event.
         $event = \core\event\grade_letter_deleted::create(array(
             'objectid' => $record->id,
index 1223ef6..aea3ec8 100644 (file)
@@ -2681,29 +2681,12 @@ EOD;
     }
 
     /**
-     * Returns HTML to display the 'Update this Modulename' button that appears on module pages.
-     *
      * @deprecated since Moodle 3.2
-     *
-     * @param string $cmid the course_module id.
-     * @param string $modulename the module name, eg. "forum", "quiz" or "workshop"
-     * @return string the HTML for the button, if this user has permission to edit it, else an empty string.
      */
-    public function update_module_button($cmid, $modulename) {
-        global $CFG;
-
-        debugging('core_renderer::update_module_button() has been deprecated and should not be used anymore. Activity modules ' .
-            'should not add the edit module button, the link is already available in the Administration block. Themes can choose ' .
-            'to display the link in the buttons row consistently for all module types.', DEBUG_DEVELOPER);
-
-        if (has_capability('moodle/course:manageactivities', context_module::instance($cmid))) {
-            $modulename = get_string('modulename', $modulename);
-            $string = get_string('updatethis', '', $modulename);
-            $url = new moodle_url("$CFG->wwwroot/course/mod.php", array('update' => $cmid, 'return' => true, 'sesskey' => sesskey()));
-            return $this->single_button($url, $string);
-        } else {
-            return '';
-        }
+    public function update_module_button() {
+        throw new coding_exception('core_renderer::update_module_button() can not be used anymore. Activity ' .
+            'modules should not add the edit module button, the link is already available in the Administration block. ' .
+            'Themes can choose to display the link in the buttons row consistently for all module types.');
     }
 
     /**
index f178315..fcc42ad 100644 (file)
@@ -56,4 +56,52 @@ class core_gradelib_testcase extends advanced_testcase {
 
         $this->assertTrue(grade_update_mod_grades($modinstance));
     }
+
+    /**
+     * Tests the function remove_grade_letters().
+     */
+    public function test_remove_grade_letters() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        $course = $this->getDataGenerator()->create_course();
+
+        $context = context_course::instance($course->id);
+
+        // Add a grade letter to the course.
+        $letter = new stdClass();
+        $letter->letter = 'M';
+        $letter->lowerboundary = '100';
+        $letter->contextid = $context->id;
+        $DB->insert_record('grade_letters', $letter);
+
+        remove_grade_letters($context, false);
+
+        // Confirm grade letter was deleted.
+        $this->assertEquals(0, $DB->count_records('grade_letters'));
+    }
+
+    /**
+     * Tests the function grade_course_category_delete().
+     */
+    public function test_grade_course_category_delete() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        $category = coursecat::create(array('name' => 'Cat1'));
+
+        // Add a grade letter to the category.
+        $letter = new stdClass();
+        $letter->letter = 'M';
+        $letter->lowerboundary = '100';
+        $letter->contextid = context_coursecat::instance($category->id)->id;
+        $DB->insert_record('grade_letters', $letter);
+
+        grade_course_category_delete($category->id, '', false);
+
+        // Confirm grade letter was deleted.
+        $this->assertEquals(0, $DB->count_records('grade_letters'));
+    }
 }
index 20139a0..5d66dd7 100644 (file)
@@ -7,17 +7,19 @@ information provided here is intended especially for developers.
   callback. If a string is returned, it is displayed instead of the list if suggested items. This can be used, for
   example, to inform the user that there are too many items matching the current search criteria.
 * The following functions have been finally deprecated and can not be used any more:
-  - external_function_info()
-  - events_trigger()
-  - events_cron()
-  - events_dispatch()
-  - events_is_registered()
-  - events_load_def()
-  - events_pending_count()
-  - events_process_queued_handler()
-  - events_queue_handler()
-  - events_trigger_legacy()
-  - events_update_definition()
+    - external_function_info()
+    - core_renderer::update_module_button()
+    - external_function_info()
+    - events_trigger()
+    - events_cron()
+    - events_dispatch()
+    - events_is_registered()
+    - events_load_def()
+    - events_pending_count()
+    - events_process_queued_handler()
+    - events_queue_handler()
+    - events_trigger_legacy()
+    - events_update_definition()
 * Following api's have been removed in behat_config_manager, please use behat_config_util instead.
     - get_features_with_tags()
     - get_components_steps_definitions()
index 767b580..0d8d407 100644 (file)
@@ -4360,7 +4360,7 @@ abstract class lesson_page extends lesson_base {
             if (count($answers) > 1) {
                 $answer = array_shift($answers);
                 foreach ($answers as $a) {
-                    $DB->delete_record('lesson_answers', array('id' => $a->id));
+                    $DB->delete_records('lesson_answers', array('id' => $a->id));
                 }
             } else if (count($answers) == 1) {
                 $answer = array_shift($answers);
index 1da0211..41e25ae 100644 (file)
@@ -70,8 +70,8 @@ function(
     var root = $('[data-region="tag-condition-container-{{uniqid}}"]');
     var selectElement = root.find('[data-region="tag-select"]');
     var loadingContainer = root.find('[data-region="overlay-icon-container"]');
-    var placeholderText = '{{#str}} filterbytags, core_question {{/str}}';
-    var noSelectionText = '{{#str}} notagfiltersapplied, core_question {{/str}}';
+    var placeholderText = {{#quote}}{{#str}} filterbytags, core_question {{/str}}{{/quote}};
+    var noSelectionText = {{#quote}}{{#str}} notagfiltersapplied, core_question {{/str}}{{/quote}};
 
     AutoComplete.enhance(
         selectElement, // Element to enhance.
index 5c6d4f8..9ec26e4 100644 (file)
@@ -270,7 +270,7 @@ Feature: View course participants
     Given I log in as "admin"
     And I am on "Course 1" course homepage
     And I navigate to course participants
-    When I navigate to "Enrolment methods" in current page administration
+    When I navigate to "Users > Enrolment methods" in current page administration
     And I click on "Disable" "link" in the "Manual enrolments" "table_row"
     Then I navigate to course participants
     And I should see "Not current" in the "student0x" "table_row"