mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 00:12:56 +02:00
Merge branch 'MDL-30545' of git://github.com/timhunt/moodle
This commit is contained in:
commit
b0ba493cd0
@ -414,32 +414,97 @@ function message_get_my_providers() {
|
||||
function message_get_providers_for_user($userid) {
|
||||
global $DB, $CFG;
|
||||
|
||||
$systemcontext = context_system::instance();
|
||||
|
||||
$providers = get_message_providers();
|
||||
|
||||
// Remove all the providers we aren't allowed to see now
|
||||
foreach ($providers as $providerid => $provider) {
|
||||
if (!empty($provider->capability)) {
|
||||
if (!has_capability($provider->capability, $systemcontext, $userid)) {
|
||||
unset($providers[$providerid]); // Not allowed to see this
|
||||
continue;
|
||||
// Ensure user is not allowed to configure instantmessage if it is globally disabled.
|
||||
if (!$CFG->messaging) {
|
||||
foreach ($providers as $providerid => $provider) {
|
||||
if ($provider->name == 'instantmessage') {
|
||||
unset($providers[$providerid]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure user is not allowed to configure instantmessage if it is globally disabled.
|
||||
if (!$CFG->messaging && $provider->name == 'instantmessage') {
|
||||
// If the component is an enrolment plugin, check it is enabled
|
||||
foreach ($providers as $providerid => $provider) {
|
||||
list($type, $name) = normalize_component($provider->component);
|
||||
if ($type == 'enrol' && !enrol_is_enabled($name)) {
|
||||
unset($providers[$providerid]);
|
||||
}
|
||||
}
|
||||
|
||||
// Now we need to check capabilities. We need to eliminate the providers
|
||||
// where the user does not have the corresponding capability anywhere.
|
||||
// Here we deal with the common simple case of the user having the
|
||||
// capability in the system context. That handles $CFG->defaultuserroleid.
|
||||
// For the remaining providers/capabilities, we need to do a more complex
|
||||
// query involving all overrides everywhere.
|
||||
$unsureproviders = array();
|
||||
$unsurecapabilities = array();
|
||||
$systemcontext = context_system::instance();
|
||||
foreach ($providers as $providerid => $provider) {
|
||||
if (empty($provider->capability) || has_capability($provider->capability, $systemcontext, $userid)) {
|
||||
// The provider is relevant to this user.
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the component is an enrolment plugin, check it is enabled
|
||||
list($type, $name) = normalize_component($provider->component);
|
||||
if ($type == 'enrol') {
|
||||
if (!enrol_is_enabled($name)) {
|
||||
unset($providers[$providerid]);
|
||||
continue;
|
||||
}
|
||||
$unsureproviders[$providerid] = $provider;
|
||||
$unsurecapabilities[$provider->capability] = 1;
|
||||
unset($providers[$providerid]);
|
||||
}
|
||||
|
||||
if (empty($unsureproviders)) {
|
||||
// More complex checks are not required.
|
||||
return $providers;
|
||||
}
|
||||
|
||||
// Now check the unsure capabilities.
|
||||
list($capcondition, $params) = $DB->get_in_or_equal(
|
||||
array_keys($unsurecapabilities), SQL_PARAMS_NAMED);
|
||||
$params['userid'] = $userid;
|
||||
|
||||
$sql = "SELECT DISTINCT rc.capability, 1
|
||||
|
||||
FROM {role_assignments} ra
|
||||
JOIN {context} actx ON actx.id = ra.contextid
|
||||
JOIN {role_capabilities} rc ON rc.roleid = ra.roleid
|
||||
JOIN {context} cctx ON cctx.id = rc.contextid
|
||||
|
||||
WHERE ra.userid = :userid
|
||||
AND rc.capability $capcondition
|
||||
AND rc.permission > 0
|
||||
AND (CONCAT(actx.path, '/') LIKE CONCAT(cctx.path, '/%') OR CONCAT(cctx.path, '/') LIKE CONCAT(actx.path, '/%'))";
|
||||
|
||||
if (!empty($CFG->defaultfrontpageroleid)) {
|
||||
$frontpagecontext = context_course::instance(SITEID);
|
||||
|
||||
list($capcondition2, $params2) = $DB->get_in_or_equal(
|
||||
array_keys($unsurecapabilities), SQL_PARAMS_NAMED);
|
||||
$params = array_merge($params, $params2);
|
||||
$params['frontpageroleid'] = $CFG->defaultfrontpageroleid;
|
||||
$params['frontpagepathpattern'] = $frontpagecontext->path . '/';
|
||||
|
||||
$sql .= "
|
||||
UNION DISTINCT
|
||||
|
||||
SELECT DISTINCT rc.capability, 1
|
||||
|
||||
FROM {role_capabilities} rc
|
||||
JOIN {context} cctx ON cctx.id = rc.contextid
|
||||
|
||||
WHERE rc.roleid = :frontpageroleid
|
||||
AND rc.capability $capcondition2
|
||||
AND rc.permission > 0
|
||||
AND CONCAT(cctx.path, '/') LIKE :frontpagepathpattern";
|
||||
}
|
||||
|
||||
$relevantcapabilities = $DB->get_records_sql_menu($sql, $params);
|
||||
|
||||
// Add back any providers based on the detailed capability check.
|
||||
foreach ($unsureproviders as $providerid => $provider) {
|
||||
if (array_key_exists($provider->capability, $relevantcapabilities)) {
|
||||
$providers[$providerid] = $provider;
|
||||
}
|
||||
}
|
||||
|
||||
|
157
lib/tests/messagelib_test.php
Normal file
157
lib/tests/messagelib_test.php
Normal file
@ -0,0 +1,157 @@
|
||||
<?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 messagelib.php.
|
||||
*
|
||||
* @package core_message
|
||||
* @copyright 2012 The Open Universtiy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
class messagelib_testcase extends advanced_testcase {
|
||||
|
||||
public function test_message_get_providers_for_user() {
|
||||
global $CFG, $DB;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$generator = $this->getDataGenerator();
|
||||
|
||||
// Create a course category and course
|
||||
$cat = $generator->create_category(array('parent' => 0));
|
||||
$course = $generator->create_course(array('category' => $cat->id));
|
||||
$quiz = $generator->create_module('quiz', array('course' => $course->id));
|
||||
$user = $generator->create_user();
|
||||
|
||||
$coursecontext = context_course::instance($course->id);
|
||||
$quizcontext = context_module::instance($quiz->cmid);
|
||||
$frontpagecontext = context_course::instance(SITEID);
|
||||
|
||||
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
|
||||
|
||||
// The user is a student in a course, and has the capability for quiz
|
||||
// confirmation emails in one quiz in that course.
|
||||
role_assign($studentrole->id, $user->id, $coursecontext->id);
|
||||
assign_capability('mod/quiz:emailconfirmsubmission', CAP_ALLOW, $studentrole->id, $quizcontext->id);
|
||||
|
||||
// Give this message type to the front page role.
|
||||
assign_capability('mod/quiz:emailwarnoverdue', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagecontext->id);
|
||||
|
||||
$providers = message_get_providers_for_user($user->id);
|
||||
$this->assertTrue($this->message_type_present('mod_forum', 'posts', $providers));
|
||||
$this->assertTrue($this->message_type_present('mod_quiz', 'confirmation', $providers));
|
||||
$this->assertTrue($this->message_type_present('mod_quiz', 'attempt_overdue', $providers));
|
||||
$this->assertFalse($this->message_type_present('mod_quiz', 'submission', $providers));
|
||||
|
||||
// A user is a student in a different course, they should not get confirmation.
|
||||
$course2 = $generator->create_course(array('category' => $cat->id));
|
||||
$user2 = $generator->create_user();
|
||||
$coursecontext2 = context_course::instance($course2->id);
|
||||
role_assign($studentrole->id, $user2->id, $coursecontext2->id);
|
||||
accesslib_clear_all_caches_for_unit_testing();
|
||||
$providers = message_get_providers_for_user($user2->id);
|
||||
$this->assertTrue($this->message_type_present('mod_forum', 'posts', $providers));
|
||||
$this->assertFalse($this->message_type_present('mod_quiz', 'confirmation', $providers));
|
||||
|
||||
// Now remove the frontpage role id, and attempt_overdue message should go away.
|
||||
unset_config('defaultfrontpageroleid');
|
||||
accesslib_clear_all_caches_for_unit_testing();
|
||||
|
||||
$providers = message_get_providers_for_user($user->id);
|
||||
$this->assertTrue($this->message_type_present('mod_quiz', 'confirmation', $providers));
|
||||
$this->assertFalse($this->message_type_present('mod_quiz', 'attempt_overdue', $providers));
|
||||
$this->assertFalse($this->message_type_present('mod_quiz', 'submission', $providers));
|
||||
}
|
||||
|
||||
public function test_message_get_providers_for_user_more() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
// Create a course
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$coursecontext = context_course::instance($course->id);
|
||||
|
||||
// It would probably be better to use a quiz instance as it has capability controlled messages
|
||||
// however mod_quiz doesn't have a data generator
|
||||
// Instead we're going to use backup notifications and give and take away the capability at various levels
|
||||
$assign = $this->getDataGenerator()->create_module('assign', array('course'=>$course->id));
|
||||
$modulecontext = context_module::instance($assign->id);
|
||||
|
||||
// Create and enrol a teacher
|
||||
$teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
|
||||
$teacher = $this->getDataGenerator()->create_user();
|
||||
role_assign($teacherrole->id, $teacher->id, $coursecontext);
|
||||
$enrolplugin = enrol_get_plugin('manual');
|
||||
$enrolplugin->add_instance($course);
|
||||
$enrolinstances = enrol_get_instances($course->id, false);
|
||||
foreach ($enrolinstances as $enrolinstance) {
|
||||
if ($enrolinstance->enrol === 'manual') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$enrolplugin->enrol_user($enrolinstance, $teacher->id);
|
||||
|
||||
// Make the teacher the current user
|
||||
$this->setUser($teacher);
|
||||
|
||||
// Teacher shouldn't have the required capability so they shouldn't be able to see the backup message
|
||||
$this->assertFalse(has_capability('moodle/site:config', $modulecontext));
|
||||
$providers = message_get_providers_for_user($teacher->id);
|
||||
$this->assertFalse($this->message_type_present('moodle', 'backup', $providers));
|
||||
|
||||
// Give the user the required capability in an activity module
|
||||
// They should now be able to see the backup message
|
||||
assign_capability('moodle/site:config', CAP_ALLOW, $teacherrole->id, $modulecontext->id, true);
|
||||
accesslib_clear_all_caches_for_unit_testing();
|
||||
$modulecontext = context_module::instance($assign->id);
|
||||
$this->assertTrue(has_capability('moodle/site:config', $modulecontext));
|
||||
|
||||
$providers = message_get_providers_for_user($teacher->id);
|
||||
$this->assertTrue($this->message_type_present('moodle', 'backup', $providers));
|
||||
|
||||
// Prohibit the capability for the user at the course level
|
||||
// This overrules the CAP_ALLOW at the module level
|
||||
// They should not be able to see the backup message
|
||||
assign_capability('moodle/site:config', CAP_PROHIBIT, $teacherrole->id, $coursecontext->id, true);
|
||||
accesslib_clear_all_caches_for_unit_testing();
|
||||
$modulecontext = context_module::instance($assign->id);
|
||||
$this->assertFalse(has_capability('moodle/site:config', $modulecontext));
|
||||
|
||||
$providers = message_get_providers_for_user($teacher->id);
|
||||
// Actually, handling PROHIBITs would be too expensive. We do not
|
||||
// care if users with PROHIBITs see a few more preferences than they should.
|
||||
// $this->assertFalse($this->message_type_present('moodle', 'backup', $providers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a particular message type in the list of message types.
|
||||
* @param string $name a message name.
|
||||
* @param array $providers as returned by message_get_providers_for_user.
|
||||
* @return bool whether the message type is present.
|
||||
*/
|
||||
protected function message_type_present($component, $name, $providers) {
|
||||
foreach ($providers as $provider) {
|
||||
if ($provider->component == $component && $provider->name == $name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1026,6 +1026,8 @@ function quiz_process_options($quiz) {
|
||||
$quiz->feedbackboundaries[-1] = $quiz->grade + 1;
|
||||
$quiz->feedbackboundaries[$numboundaries] = 0;
|
||||
$quiz->feedbackboundarycount = $numboundaries;
|
||||
} else {
|
||||
$quiz->feedbackboundarycount = -1;
|
||||
}
|
||||
|
||||
// Combing the individual settings into the review columns.
|
||||
|
106
mod/quiz/tests/generator/lib.php
Normal file
106
mod/quiz/tests/generator/lib.php
Normal file
@ -0,0 +1,106 @@
|
||||
<?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/>.
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Quiz module test data generator class
|
||||
*
|
||||
* @package mod_quiz
|
||||
* @copyright 2012 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class mod_quiz_generator extends phpunit_module_generator {
|
||||
|
||||
/**
|
||||
* Create new quiz module instance.
|
||||
* @param array|stdClass $record
|
||||
* @param array $options (mostly course_module properties)
|
||||
* @return stdClass activity record with extra cmid field
|
||||
*/
|
||||
public function create_instance($record = null, array $options = null) {
|
||||
global $CFG;
|
||||
require_once("$CFG->dirroot/mod/quiz/locallib.php");
|
||||
|
||||
$this->instancecount++;
|
||||
$i = $this->instancecount;
|
||||
|
||||
$record = (object)(array)$record;
|
||||
$options = (array)$options;
|
||||
|
||||
if (empty($record->course)) {
|
||||
throw new coding_exception('module generator requires $record->course');
|
||||
}
|
||||
if (isset($options['idnumber'])) {
|
||||
$record->cmidnumber = $options['idnumber'];
|
||||
} else {
|
||||
$record->cmidnumber = '';
|
||||
}
|
||||
|
||||
$alwaysvisible = mod_quiz_display_options::DURING | mod_quiz_display_options::IMMEDIATELY_AFTER |
|
||||
mod_quiz_display_options::LATER_WHILE_OPEN | mod_quiz_display_options::AFTER_CLOSE;
|
||||
|
||||
$defaultquizsettings = array(
|
||||
'name' => get_string('pluginname', 'data').' '.$i,
|
||||
'intro' => 'Test quiz ' . $i,
|
||||
'introformat' => FORMAT_MOODLE,
|
||||
'timeopen' => 0,
|
||||
'timeclose' => 0,
|
||||
'preferredbehaviour' => 'deferredfeedback',
|
||||
'attempts' => 0,
|
||||
'attemptonlast' => 0,
|
||||
'grademethod' => QUIZ_GRADEHIGHEST,
|
||||
'decimalpoints' => 2,
|
||||
'questiondecimalpoints' => -1,
|
||||
'reviewattempt' => $alwaysvisible,
|
||||
'reviewcorrectness' => $alwaysvisible,
|
||||
'reviewmarks' => $alwaysvisible,
|
||||
'reviewspecificfeedback' => $alwaysvisible,
|
||||
'reviewgeneralfeedback' => $alwaysvisible,
|
||||
'reviewrightanswer' => $alwaysvisible,
|
||||
'reviewoverallfeedback' => $alwaysvisible,
|
||||
'questionsperpage' => 1,
|
||||
'shufflequestions' => 0,
|
||||
'shuffleanswers' => 1,
|
||||
'questions' => '',
|
||||
'sumgrades' => 0,
|
||||
'grade' => 0,
|
||||
'timecreated' => time(),
|
||||
'timemodified' => time(),
|
||||
'timelimit' => 0,
|
||||
'overduehandling' => 'autoabandon',
|
||||
'graceperiod' => 86400,
|
||||
'quizpassword' => '',
|
||||
'subnet' => '',
|
||||
'browsersecurity' => '',
|
||||
'delay1' => 0,
|
||||
'delay2' => 0,
|
||||
'showuserpicture' => 0,
|
||||
'showblocks' => 0,
|
||||
'navmethod' => QUIZ_NAVMETHOD_FREE,
|
||||
);
|
||||
|
||||
foreach ($defaultquizsettings as $name => $value) {
|
||||
if (!isset($record->{$name})) {
|
||||
$record->{$name} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$record->coursemodule = $this->precreate_course_module($record->course, $options);
|
||||
$id = quiz_add_instance($record);
|
||||
return $this->post_add_instance($id, $record->coursemodule);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user