/.buildpath
/.cache
phpunit.xml
-# Composer support - only composer.json is to be in git, the rest is installed in each checkout.
+# Composer support. Do not ignore composer.json, or composer.lock. These should be shipped by us.
composer.phar
-composer.lock
/vendor/
/behat.yml
*/yui/build/*/*-coverage.js
module.exports = function(grunt) {
var path = require('path'),
- tasks = {};
+ tasks = {},
+ cwd = process.env.PWD || process.cwd();
// Project configuration.
grunt.initConfig({
['**/src/*.js', '!**/node_modules/**'],
'',
{
- cwd: process.env.PWD,
+ cwd: cwd,
rename: function(destBase, destPath) {
destPath = destPath.replace('src', 'build');
destPath = destPath.replace('.js', '.min.js');
- destPath = path.resolve(process.env.PWD, destPath);
+ destPath = path.resolve(cwd, destPath);
return destPath;
}
}
},
shifter;
+ args.push( path.normalize(__dirname + '/node_modules/shifter/bin/shifter'));
+
// Determine the most appropriate options to run with based upon the current location.
- if (path.basename(process.env.PWD) === 'src') {
+ if (path.basename(cwd) === 'src') {
// Detect whether we're in a src directory.
grunt.log.debug('In a src directory');
args.push('--walk');
options.walk = true;
- } else if (path.basename(path.dirname(process.env.PWD)) === 'src') {
+ } else if (path.basename(path.dirname(cwd)) === 'src') {
// Detect whether we're in a module directory.
grunt.log.debug('In a module directory');
options.module = true;
}
// Actually run shifter.
- shifter = exec(process.cwd() + '/node_modules/shifter/bin/shifter', args, {
- cwd: process.env.PWD,
+ shifter = exec("node", args, {
+ cwd: cwd,
stdio: 'inherit',
env: process.env
});
tasks.startup = function() {
// Are we in a YUI directory?
- if (path.basename(path.resolve(process.env.PWD, '../../')) == 'yui') {
+ if (path.basename(path.resolve(cwd, '../../')) == 'yui') {
grunt.task.run('shifter');
// Are we in an AMD directory?
- } else if (path.basename(process.env.PWD) == 'amd') {
+ } else if (path.basename(cwd) == 'amd') {
grunt.task.run('jshint');
grunt.task.run('uglify');
} else {
$dbproblems = $DB->diagnose();
$maintenancemode = !empty($CFG->maintenance_enabled);
-// Available updates for Moodle core
+// Available updates for Moodle core.
$updateschecker = \core\update\checker::instance();
$availableupdates = array();
-$availableupdates['core'] = $updateschecker->get_update_info('core',
- array('minmaturity' => $CFG->updateminmaturity, 'notifybuilds' => $CFG->updatenotifybuilds));
-
-// Available updates for contributed plugins
-$pluginman = core_plugin_manager::instance();
-foreach ($pluginman->get_plugins() as $plugintype => $plugintypeinstances) {
- foreach ($plugintypeinstances as $pluginname => $plugininfo) {
- if (!empty($plugininfo->availableupdates)) {
- foreach ($plugininfo->availableupdates as $pluginavailableupdate) {
- if ($pluginavailableupdate->version > $plugininfo->versiondisk) {
- if (!isset($availableupdates[$plugintype.'_'.$pluginname])) {
- $availableupdates[$plugintype.'_'.$pluginname] = array();
+$availableupdatesfetch = null;
+
+if (empty($CFG->disableupdatenotifications)) {
+ // Only compute the update information when it is going to be displayed to the user.
+ $availableupdates['core'] = $updateschecker->get_update_info('core',
+ array('minmaturity' => $CFG->updateminmaturity, 'notifybuilds' => $CFG->updatenotifybuilds));
+
+ // Available updates for contributed plugins
+ $pluginman = core_plugin_manager::instance();
+ foreach ($pluginman->get_plugins() as $plugintype => $plugintypeinstances) {
+ foreach ($plugintypeinstances as $pluginname => $plugininfo) {
+ if (!empty($plugininfo->availableupdates)) {
+ foreach ($plugininfo->availableupdates as $pluginavailableupdate) {
+ if ($pluginavailableupdate->version > $plugininfo->versiondisk) {
+ if (!isset($availableupdates[$plugintype.'_'.$pluginname])) {
+ $availableupdates[$plugintype.'_'.$pluginname] = array();
+ }
+ $availableupdates[$plugintype.'_'.$pluginname][] = $pluginavailableupdate;
}
- $availableupdates[$plugintype.'_'.$pluginname][] = $pluginavailableupdate;
}
}
}
}
-}
-// The timestamp of the most recent check for available updates
-$availableupdatesfetch = $updateschecker->get_last_timefetched();
+ // The timestamp of the most recent check for available updates
+ $availableupdatesfetch = $updateschecker->get_last_timefetched();
+}
$buggyiconvnomb = (!function_exists('mb_convert_encoding') and @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
//check if the site is registered on Moodle.org
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('registrationconfirmed', 'hub'), 3, 'main');
- $hublink = html_writer::tag('a', $hubname, array('href' => $url));
$registeredhub->token = $newtoken;
$registeredhub->confirmed = 1;
$registrationmanager->update_registeredhub($registeredhub);
// Display notification message.
- $notificationmessage = $OUTPUT->notification(
- get_string('registrationconfirmedon', 'hub', $hublink), 'notifysuccess');
- echo $notificationmessage;
+ echo $OUTPUT->notification(get_string('registrationconfirmedon', 'hub'), 'notifysuccess');
//display continue button
$registrationpage = new moodle_url('/admin/registration/index.php');
class core_register_renderer extends plugin_renderer_base {
/**
- * Display Moodle.org registration message about benefit to register on Moodle.org
+ * Display message about the benefits of registering on Moodle.org
*
* @return string
*/
public function moodleorg_registration_message() {
-
$moodleorgstatslink = html_writer::link('http://moodle.net/stats',
get_string('statsmoodleorg', 'admin'),
array('target' => '_blank'));
- $hublink = html_writer::link('https://moodle.net/mod/page/view.php?id=1',
- get_string('moodleorghubname', 'admin'),
- array('target' => '_blank'));
-
- $moodleorgregmsg = get_string('registermoodleorg', 'admin', $hublink);
+ $moodleorgregmsg = get_string('registermoodleorg', 'admin');
$items = array(get_string('registermoodleorgli1', 'admin'),
get_string('registermoodleorgli2', 'admin', $moodleorgstatslink));
$moodleorgregmsg .= html_writer::alist($items);
'customusermenuitems',
new lang_string('customusermenuitems', 'admin'),
new lang_string('configcustomusermenuitems', 'admin'),
- 'mygrades,grades|/grade/report/mygrades.php|grades
+ 'grades,grades|/grade/report/mygrades.php|grades
messages,message|/message/index.php|message
-mypreferences,moodle|/user/preferences.php|preferences',
+preferences,moodle|/user/preferences.php|preferences',
PARAM_TEXT,
'50',
'10'
$ADMIN->add('courses',
new admin_externalpage('restorecourse', new lang_string('restorecourse', 'admin'),
new moodle_url('/backup/restorefile.php', array('contextid' => context_system::instance()->id)),
- array('moodle/course:create')
+ array('moodle/restore:restorecourse')
)
);
// activity modules
$ADMIN->add('modules', new admin_category('modsettings', new lang_string('activitymodules')));
- $temp = new admin_settingpage('managemodulescommon', new lang_string('commonsettings', 'admin'));
+ $ADMIN->add('modsettings', new admin_page_managemods());
+ $temp = new admin_settingpage('managemodulescommon', new lang_string('commonactivitysettings', 'admin'));
$temp->add(new admin_setting_configcheckbox('requiremodintro',
get_string('requiremodintro', 'admin'), get_string('requiremodintro_desc', 'admin'), 0));
$ADMIN->add('modsettings', $temp);
- $ADMIN->add('modsettings', new admin_page_managemods());
foreach (core_plugin_manager::instance()->get_plugins_of_type('mod') as $plugin) {
/** @var \core\plugininfo\mod $plugin */
$plugin->load_settings($ADMIN, 'modsettings', $hassiteconfig);
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000;
-$plugin->requires = 2014110400;
+$plugin->version = 2015051100;
+$plugin->requires = 2015050500;
$plugin->component = 'tool_assignmentupgrade';
-$plugin->dependencies = array('mod_assign' => 2014110400);
+$plugin->dependencies = array('mod_assign' => 2015050500);
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000;
-$plugin->requires = 2014110400;
+$plugin->version = 2015051100;
+$plugin->requires = 2015050500;
$plugin->component = 'tool_availabilityconditions';
$cwd = getcwd();
$output = null;
-$installcomposer = true;
// If behat dependencies not downloaded then do it first, else symfony/process can't be used.
-if ($options['parallel'] && !file_exists(__DIR__ . "/../../../../vendor/autoload.php")) {
- $installcomposer = false;
- testing_update_composer_dependencies();
-}
+testing_update_composer_dependencies();
+// Check whether the behat test environment needs to be updated.
chdir(__DIR__);
exec("php $utilfile --diag $paralleloption", $output, $code);
-// Check if composer needs to be updated.
-if ($installcomposer &&
- ($code == BEHAT_EXITCODE_INSTALL || $code == BEHAT_EXITCODE_REINSTALL || $code == BEHAT_EXITCODE_COMPOSER)) {
- testing_update_composer_dependencies();
- // Check again for behat test site and see if it's install or re-install.
- chdir(__DIR__);
- exec("php $utilfile --diag $paralleloption", $output, $code);
-}
-
if ($code == 0) {
echo "Behat test environment already installed\n";
$time = microtime(true);
array_walk($unrecognised, function (&$v) {
- if ($x = preg_filter("#^(-+\w+)=(.+)#", "\$1='\$2'", $v)) {
+ if ($x = preg_filter("#^(-+\w+)=(.+)#", "\$1=\"\$2\"", $v)) {
$v = $x;
} else if (!preg_match("#^-#", $v)) {
$v = escapeshellarg($v);
echo "Invalid profile passed: " . $profile;
exit(1);
}
- $extraopts[] = '--profile=\'' . $profile . "'";
+ $extraopts[] = '--profile="' . $profile . '"';
// By default, profile tags will be used.
if (!empty($CFG->behat_config[$profile]['filters']['tags'])) {
$tags = $CFG->behat_config[$profile]['filters']['tags'];
$cwd = getcwd();
// For drop option check if parallel site.
-if ((empty($options['parallel'])) && $options['drop']) {
+if ((empty($options['parallel'])) && ($options['drop']) || $options['updatesteps']) {
// Get parallel run info from first run.
$options['parallel'] = behat_config_manager::get_parallel_test_runs($options['fromrun']);
}
}
}
+} else if ($options['updatesteps']) {
+ // Rewrite config file to ensure we have all the features covered.
+ if (empty($options['parallel'])) {
+ behat_config_manager::update_config_file();
+ } else {
+ // Update config file, ensuring we have up-to-date behat.yml.
+ for ($i = $options['fromrun']; $i <= $options['torun']; $i++) {
+ $CFG->behatrunprocess = $i;
+ behat_config_manager::update_config_file();
+ }
+ unset($CFG->behatrunprocess);
+ }
+
+ // Do it sequentially as it's fast and need to be displayed nicely.
+ foreach (array_chunk($cmds, 1, true) as $cmd) {
+ $processes = cli_execute_parallel($cmd, __DIR__);
+ print_sequential_output($processes);
+ }
+ exit(0);
+
} else {
// We should never reach here.
echo $help;
exit(1);
}
- // Rewrite config file to ensure we have all the features covered.
- behat_config_manager::update_config_file();
-
// Run behat command to get steps in feature files.
$featurestepscmd = behat_command::get_behat_command(true);
$featurestepscmd .= ' --config ' . behat_config_manager::get_behat_cli_config_filepath();
$steps[$step[0]] = $step[1];
}
}
+
+ if ($existing = @json_decode(file_get_contents($featurestepfile), true)) {
+ $steps = array_merge($existing, $steps);
+ }
arsort($steps);
if (!@file_put_contents($featurestepfile, json_encode($steps, JSON_PRETTY_PRINT))) {
When I log in as "admin"
And I am on site homepage
And I follow "Course 1"
- And I follow "Grades"
+ And I navigate to "Grades" node in "Course administration"
And I expand "Setup" node
And I follow "Categories and items"
Then I should see "Test Grade Item 1"
When I log in as "admin"
And I am on site homepage
And I follow "Course 1"
- And I follow "Grades"
+ And I navigate to "Grades" node in "Course administration"
And I follow "Scales"
Then I should see "Test Scale 1"
And I should see "Disappointing, Good, Very good, Excellent"
When I log in as "admin"
And I am on site homepage
And I follow "Course 1"
- And I follow "Grades"
+ And I navigate to "Grades" node in "Course administration"
And I expand "Setup" node
And I follow "Categories and items"
Then I should see "Test Outcome Grade Item 1"
@javascript
Scenario: Basic forms manipulation
Given I log in as "admin"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
And I follow "Edit profile"
When I set the field "First name" to "Field value"
And I set the field "Select a country" to "Japan"
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And I log in as "admin"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
And I follow "Edit profile"
@javascript
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2014110400; // Requires this Moodle version
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->component = 'tool_behat'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2014110400; // Requires this Moodle version.
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2015050500; // Requires this Moodle version.
$plugin->component = 'tool_capability'; // Full name of the plugin (used for diagnostics).
// Moodle v2.8.0 release upgrade line.
// Put any upgrade step following this.
+ // Moodle v2.9.0 release upgrade line.
+ // Put any upgrade step following this.
+
return true;
}
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000;
-$plugin->requires = 2014110400;
+$plugin->version = 2015051100;
+$plugin->requires = 2015050500;
$plugin->component = 'tool_customlang'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2014110400; // Requires this Moodle version.
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2015050500; // Requires this Moodle version.
$plugin->component = 'tool_dbtransfer'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014112700;
-$plugin->requires = 2014112700;
+$plugin->version = 2015051100;
+$plugin->requires = 2015050500;
$plugin->component = 'tool_filetypes';
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000;
-$plugin->requires = 2014110400;
+$plugin->version = 2015051100;
+$plugin->requires = 2015050500;
$plugin->component = 'tool_generator';
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2014110400; // Requires this Moodle version
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->component = 'tool_health'; // Full name of the plugin (used for diagnostics)
$plugin->maturity = MATURITY_ALPHA; // this version's maturity level
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2014110400; // Requires this Moodle version
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->component = 'tool_innodb'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'tool_installaddon';
-$plugin->version = 2014111000;
-$plugin->requires = 2014110400;
+$plugin->version = 2015051100;
+$plugin->requires = 2015050500;
$plugin->maturity = MATURITY_STABLE;
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2014110400; // Requires this Moodle version
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->component = 'tool_langimport'; // Full name of the plugin (used for diagnostics)
// Moodle v2.8.0 release upgrade line.
// Put any upgrade step following this.
+ // Moodle v2.9.0 release upgrade line.
+ // Put any upgrade step following this.
+
return true;
}
// Moodle v2.8.0 release upgrade line.
// Put any upgrade step following this.
+ // Moodle v2.9.0 release upgrade line.
+ // Put any upgrade step following this.
+
return true;
}
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2014110400; // Requires this Moodle version.
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2015050500; // Requires this Moodle version.
$plugin->component = 'logstore_database'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2014110400; // Requires this Moodle version.
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2015050500; // Requires this Moodle version.
$plugin->component = 'logstore_legacy'; // Full name of the plugin (used for diagnostics).
// Moodle v2.8.0 release upgrade line.
// Put any upgrade step following this.
+ // Moodle v2.9.0 release upgrade line.
+ // Put any upgrade step following this.
+
return true;
}
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2014110400; // Requires this Moodle version.
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2015050500; // Requires this Moodle version.
$plugin->component = 'logstore_standard'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2014110400; // Requires this Moodle version.
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2015050500; // Requires this Moodle version.
$plugin->component = 'tool_log'; // Full name of the plugin (used for diagnostics).
$settings->add(new admin_setting_heading('messageinbound_mailboxconfiguration',
new lang_string('mailboxconfiguration', 'tool_messageinbound'),
new lang_string('messageinboundmailboxconfiguration_desc', 'tool_messageinbound'), ''));
- $settings->add(new admin_setting_configtext('messageinbound_mailbox',
+ $settings->add(new admin_setting_configtext_with_maxlength('messageinbound_mailbox',
new lang_string('mailbox', 'tool_messageinbound'),
- null, '', PARAM_RAW));
+ null, '', PARAM_RAW, null, 15));
$settings->add(new admin_setting_configtext('messageinbound_domain',
new lang_string('domain', 'tool_messageinbound'),
null, '', PARAM_RAW));
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000;
-$plugin->requires = 2014110400;
+$plugin->version = 2015051100;
+$plugin->requires = 2015050500;
$plugin->component = 'tool_messageinbound';
/**
* Gets a list of courses where the current user can subscribe to rules as a dropdown.
*
+ * @param bool $choose A flag for whether to show the 'choose...' option in the select box.
* @return \single_select|bool returns the list of courses, or false if the select box
* should not be displayed.
*/
- public function get_user_courses_select() {
- global $DB;
-
- // If the number of courses on the site exceed the maximum drop down limit do not display the select box.
- $numcourses = $DB->count_records('course');
- if ($numcourses > COURSE_MAX_COURSES_PER_DROPDOWN) {
+ public function get_user_courses_select($choose = false) {
+ $options = tool_monitor_get_user_courses();
+ // If we have no options then don't create a select element.
+ if (!$options) {
return false;
}
- $orderby = 'visible DESC, sortorder ASC';
- $options = array();
- if ($courses = get_user_capability_course('tool/monitor:subscribe', null, true, 'fullname', $orderby)) {
- foreach ($courses as $course) {
- $options[$course->id] = format_string($course->fullname, true,
- array('context' => \context_course::instance($course->id)));
- }
- }
- // If there are no options to display, then don't display anything.
- if (count($options) === 0) {
- return false;
+ $selected = $this->courseid;
+ $nothing = array();
+ if ($choose) {
+ $selected = null;
+ $nothing = array('choosedots');
}
$url = new \moodle_url('/admin/tool/monitor/index.php');
- $select = new \single_select($url, 'courseid', $options, $this->courseid);
+ $select = new \single_select($url, 'courseid', $options, $selected, $nothing);
$select->set_label(get_string('selectacourse', 'tool_monitor'));
return $select;
}
// Moodle v2.8.0 release upgrade line.
// Put any upgrade step following this.
+ // Moodle v2.9.0 release upgrade line.
+ // Put any upgrade step following this.
+
return true;
}
require_once(__DIR__ . '/../../../config.php');
require_once($CFG->libdir.'/adminlib.php');
+require_once($CFG->dirroot . '/admin/tool/monitor/lib.php');
-$courseid = optional_param('courseid', SITEID, PARAM_INT);
+$courseid = optional_param('courseid', 0, PARAM_INT);
$action = optional_param('action', '', PARAM_ALPHA);
$cmid = optional_param('cmid', 0, PARAM_INT);
$ruleid = optional_param('ruleid', 0, PARAM_INT);
$subscriptionid = optional_param('subscriptionid', 0, PARAM_INT);
$confirm = optional_param('confirm', false, PARAM_BOOL);
-require_login();
-
-// We need to explicitly check that the course id is something legitimate.
+$choose = false;
+// Validate course id.
if (empty($courseid)) {
- $courseid = SITEID;
+ require_login();
+ $context = context_system::instance();
+ // check system level capability.
+ if (!has_capability('tool/monitor:subscribe', $context)) {
+ // If not system level then check to see if they have access to any course level rules.
+ if (tool_monitor_get_user_courses()){
+ // Make them choose a course.
+ $choose = true;
+ } else {
+ // return error.
+ print_error('rulenopermission', 'tool_monitor');
+ }
+ }
+} else {
+ // They might want to see rules for this course.
+ $course = get_course($courseid);
+ require_login($course);
+ $context = context_course::instance($course->id);
+ // Check for caps.
+ require_capability('tool/monitor:subscribe', $context);
}
-$coursecontext = context_course::instance($courseid);
-
if (!get_config('tool_monitor', 'enablemonitor')) {
// This should never happen as the this page does not appear in navigation when the tool is disabled.
throw new coding_exception('Event monitoring is disabled');
}
-$sitename = format_string($SITE->fullname, true, array('context' => $coursecontext));
+// Use the user context here so that the header shows user information.
$PAGE->set_context(context_user::instance($USER->id));
// Set up the page.
$indexurl = new moodle_url('/admin/tool/monitor/index.php', array('courseid' => $courseid));
$PAGE->set_url($indexurl);
$PAGE->set_pagelayout('report');
-$PAGE->set_title($sitename);
+$PAGE->set_title(get_string('managesubscriptions', 'tool_monitor'));
$PAGE->set_heading(fullname($USER));
-$settingsnode = $PAGE->settingsnav->find('monitor', null)->make_active();
+$settingsnode = $PAGE->settingsnav->find('monitor', null);
+if ($settingsnode) {
+ $settingsnode->make_active();
+}
// Create/delete subscription if needed.
if (!empty($action)) {
} else {
$subscription = \tool_monitor\subscription_manager::get_subscription($subscriptionid);
echo $OUTPUT->header();
- echo $OUTPUT->confirm(get_string('subareyousure', 'tool_monitor', $subscription->get_name($coursecontext)),
+ echo $OUTPUT->confirm(get_string('subareyousure', 'tool_monitor', $subscription->get_name($context)),
$confirmurl, $cancelurl);
echo $OUTPUT->footer();
exit();
$totalrules = \tool_monitor\rule_manager::count_rules_by_courseid($courseid);
$rules = new \tool_monitor\output\managesubs\rules('toolmonitorrules', $indexurl, $courseid);
-$usercourses = $rules->get_user_courses_select();
-if (!empty($usercourses)) {
- echo $renderer->render($usercourses);
-} else {
- // Nothing to show at all. Show a notification.
- echo $OUTPUT->notification(get_string('rulenopermission', 'tool_monitor'), 'notifyproblem');
-}
+$usercourses = $rules->get_user_courses_select($choose);
+// There must be user courses otherwise we wouldn't make it this far.
+echo $renderer->render($usercourses);
// Render the current subscriptions list.
$totalsubs = \tool_monitor\subscription_manager::count_user_subscriptions();
-if (!empty($totalsubs)) {
+if (!empty($totalsubs) && !$choose) {
// Show the subscriptions section only if there are subscriptions.
$subs = new \tool_monitor\output\managesubs\subs('toolmonitorsubs', $indexurl, $courseid);
echo $OUTPUT->heading(get_string('currentsubscriptions', 'tool_monitor'), 3);
}
// Render the potential rules list.
-// Check the capability here before displaying any rules to subscribe to.
-if (has_capability('tool/monitor:subscribe', $coursecontext)) {
+if (!$choose) {
echo $OUTPUT->heading(get_string('rulescansubscribe', 'tool_monitor'), 3);
echo $renderer->render($rules);
}
// Check if the user can manage the course rules we are viewing.
-$canmanagerules = has_capability('tool/monitor:managerules', $coursecontext);
+$canmanagerules = has_capability('tool/monitor:managerules', $context);
if (empty($totalrules)) {
// No rules present. Show a link to manage rules page if permissions permit.
// Don't show the setting if the event monitor isn't turned on. No access to other peoples subscriptions.
if (get_config('tool_monitor', 'enablemonitor') && $USER->id == $user->id) {
- // The $course->id will always be the course that corresponds to the current context.
- $courseid = $course->id;
- // A $course->id of $SITE->id might either be the frontpage or the site. So if we get the site ID back, check the...
- // ...courseid parameter passed to the page so we can know if we are looking at the frontpage rules or site level rules.
- if ($course->id == $SITE->id && optional_param('courseid', $course->id, PARAM_INT) == 0) {
- $courseid = 0;
+ // Now let's check to see if the user has any courses / site rules that they can subscribe to.
+ if ($courses = tool_monitor_get_user_courses()) {
+ $url = new moodle_url('/admin/tool/monitor/index.php');
+ $subsnode = navigation_node::create(get_string('managesubscriptions', 'tool_monitor'), $url,
+ navigation_node::TYPE_SETTING, null, 'monitor', new pix_icon('i/settings', ''));
+
+ if (isset($subsnode) && !empty($navigation)) {
+ $navigation->add_node($subsnode);
+ }
}
- $url = new moodle_url('/admin/tool/monitor/index.php', array('courseid' => $courseid));
- $subsnode = navigation_node::create(get_string('managesubscriptions', 'tool_monitor'), $url,
- navigation_node::TYPE_SETTING, null, 'monitor', new pix_icon('i/settings', ''));
+ }
+}
- if (isset($subsnode) && !empty($navigation)) {
- $navigation->add_node($subsnode);
+/**
+ * Get a list of courses and also include 'Site' for site wide rules.
+ *
+ * @return array|bool Returns an array of courses or false if the user has no permission to subscribe to rules.
+ */
+function tool_monitor_get_user_courses() {
+ $orderby = 'visible DESC, sortorder ASC';
+ $options = array();
+ if (has_capability('tool/monitor:subscribe', context_system::instance())) {
+ $options[0] = get_string('site');
+ }
+ if ($courses = get_user_capability_course('tool/monitor:subscribe', null, true, 'fullname', $orderby)) {
+ foreach ($courses as $course) {
+ $options[$course->id] = format_string($course->fullname, true,
+ array('context' => context_course::instance($course->id)));
}
}
+ // If there are no courses and there is no site permission then return false.
+ if (count($options) < 1) {
+ return false;
+ } else {
+ return $options;
+ }
}
Scenario: Subscribe to a rule on course level
Given I log in as "teacher1"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Course 1"
When I follow "Subscribe to rule \"New rule course level\""
Scenario: Delete a subscription on course level
Given I log in as "teacher1"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Course 1"
And I follow "Subscribe to rule \"New rule course level\""
Scenario: Subscribe to a rule on site level
Given I log in as "admin"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Acceptance test site"
When I follow "Subscribe to rule \"New rule site level\""
Scenario: Delete a subscription on site level
Given I log in as "admin"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Acceptance test site"
And I follow "Subscribe to rule \"New rule site level\""
Scenario: Receiving notification on site level
Given I log in as "admin"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
And I follow "Messaging"
And I click on "input[name^=tool_monitor_notification_loggedin]" "css_element"
And I press "Save changes"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Acceptance test site"
And I follow "Subscribe to rule \"New rule site level\""
Scenario: Receiving notification on course level
Given I log in as "teacher1"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
And I follow "Messaging"
And I click on "input[name^=tool_monitor_notification_loggedin]" "css_element"
And I press "Save changes"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Course 1"
And I follow "Subscribe to rule \"New rule course level\""
Scenario: Navigating via quick link to rules
Given I log in as "admin"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
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 should see "You can subscribe to rules from the Event monitoring page."
And I log out
And I log in as "teacher1"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
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 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"
- And I set the field "courseid" to "Choose..."
+ And I follow "Preferences" in the user menu
+ And I follow "Event monitoring"
And I should not see "You can manage rules from the Event monitoring rules page."
And I log out
And I log in as "teacher2"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Course 1"
And I should not see "You can manage rules the from the Event monitoring rules page."
| tool/monitor:managerules | Prohibit |
And I log out
And I log in as "teacher1"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
And I follow "Event monitoring"
When 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 should not see "You can manage rules from the Event monitoring rules page."
And I log out
And I log in as "teacher2"
- And I follow "My preferences" in the user menu
+ And I follow "Preferences" in the user menu
And I follow "Event monitoring"
And I set the field "Select a course" to "Course 1"
And I should not see "You can manage rules from the Event monitoring rules page."
defined('MOODLE_INTERNAL') || die;
-$plugin->version = 2014111001; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2014110400; // Requires this Moodle version.
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2015050500; // Requires this Moodle version.
$plugin->component = 'tool_monitor'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2014110400; // Requires this Moodle version
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->component = 'tool_multilangupgrade'; // Full name of the plugin (used for diagnostics)
require_once(__DIR__.'/../../../../lib/testing/lib.php');
echo "Initialising Moodle PHPUnit test environment...\n";
+testing_update_composer_dependencies();
$output = null;
exec('php --version', $output, $code);
passthru("php util.php --buildconfig", $code);
+echo "\n";
+echo "PHPUnit test environment setup complete.\n";
exit(0);
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2014110400; // Requires this Moodle version
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->component = 'tool_phpunit'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2014110400; // Requires this Moodle version
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->component = 'tool_profiling'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2014110400; // Requires this Moodle version
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->component = 'tool_replace'; // Full name of the plugin (used for diagnostics)
$plugin->maturity = MATURITY_ALPHA; // this version's maturity level
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000;
-$plugin->requires = 2014110400;
+$plugin->version = 2015051100;
+$plugin->requires = 2015050500;
$plugin->component = 'tool_spamcleaner'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2014110400; // Requires this Moodle version
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->component = 'tool_task'; // Full name of the plugin (used for diagnostics)
function($, ajax, log, notification, templates, config, str) {
/**
- * Handle a template loaded response.
+ * Search through a template for a template docs comment.
*
- * @param {String} templateName The template name
- * @param {String} source The template source
+ * @param {String} templateSource The raw template
+ * @param {String} templateName The name of the template used to search for docs tag
+ * @return {String|boolean} the correct comment or false
*/
- var templateLoaded = function(templateName, source) {
- str.get_string('templateselected', 'tool_templatelibrary', templateName).done(function(s) {
- $('[data-region="displaytemplateheader"]').text(s);
- }).fail(notification.exception);
+ var findDocsSection = function(templateSource, templateName) {
// Find the comment section marked with @template component/template.
- var marker = "@template " + templateName;
+ var marker = "@template " + templateName,
+ i = 0,
+ sections = [];
- var sections = source.match(/{{!([\s\S]*?)}}/g);
- var i = 0;
+ sections = templateSource.match(/{{!([\s\S]*?)}}/g);
// If no sections match - show the entire file.
if (sections !== null) {
// Remove {{! and }} from start and end.
var offset = start + marker.length + 1;
section = section.substr(offset, section.length - 2 - offset);
- source = section;
- break;
+ return section;
}
}
}
+ // No matching comment.
+ return false;
+ };
+
+ /**
+ * Handle a template loaded response.
+ *
+ * @param {String} templateName The template name
+ * @param {String} source The template source
+ * @param {String} originalSource The original template source (not theme overridden)
+ */
+ var templateLoaded = function(templateName, source, originalSource) {
+ str.get_string('templateselected', 'tool_templatelibrary', templateName).done(function(s) {
+ $('[data-region="displaytemplateheader"]').text(s);
+ }).fail(notification.exception);
+
+ // Find the comment section marked with @template component/template.
+ var docs = findDocsSection(source, templateName);
+
+ if (docs === false) {
+ // Docs was not in theme template, try original.
+ docs = findDocsSection(originalSource, templateName);
+ }
+
+ // If we found a docs section, limit the template library to showing this section.
+ if (docs) {
+ source = docs;
+ }
$('[data-region="displaytemplatesource"]').text(source);
/**
* Load the a template source from Moodle.
+ *
* @param {String} templateName
*/
var loadTemplate = function(templateName) {
var component = parts.shift();
var name = parts.shift();
- ajax.call([{
+ var promises = ajax.call([{
methodname: 'core_output_load_template',
args:{
component: component,
template: name,
themename: config.theme
- },
- done: function(source) { templateLoaded(templateName, source); },
- fail: notification.exception
+ }
+ }, {
+ methodname: 'tool_templatelibrary_load_canonical_template',
+ args:{
+ component: component,
+ template: name
+ }
}]);
+
+ // When returns a new promise that is resolved when all the passed in promises are resolved.
+ // The arguments to the done become the values of each resolved promise.
+ $.when.apply($, promises)
+ .done( function(source, originalSource) { templateLoaded(templateName, source, originalSource); })
+ .fail(notification.exception);
};
// Add the event listeners.
*/
namespace tool_templatelibrary;
-use stdClass;
use core_component;
+use core\output\mustache_template_finder;
use coding_exception;
+use moodle_exception;
use required_capability_exception;
+use stdClass;
/**
* API exposed by tool_templatelibrary
*
* @param string $component Filter the list to a single component.
* @param string $search Search string to optionally filter the list of templates.
+ * @param string $themename The name of the current theme.
* @return array[string] Where each template is in the form "component/templatename".
*/
- public static function list_templates($component = '', $search = '') {
+ public static function list_templates($component = '', $search = '', $themename = '') {
global $CFG;
$templatedirs = array();
$results = array();
- if ($component != '') {
+ if ($component !== '') {
// Just look at one component for templates.
- $dir = core_component::get_component_directory($component);
- if (!$dir) {
- return $templatedirs;
- }
+ $dirs = mustache_template_finder::get_template_directories_for_component($component, $themename);
- $templatedirs[$component] = $dir . '/templates';
+ $templatedirs[$component] = $dirs;
} else {
- // Look at all the templates dirs for all installed plugins.
- $dir = $CFG->libdir . '/templates';
- if (!empty($dir) && is_dir($dir)) {
- $templatedirs['core'] = $dir;
+ // Look at all the templates dirs for core.
+ $templatedirs['core'] = mustache_template_finder::get_template_directories_for_component('core', $themename);
+
+ // Look at all the templates dirs for subsystems.
+ $subsystems = core_component::get_core_subsystems();
+ foreach ($subsystems as $subsystem => $dir) {
+ $dir .= '/templates';
+ if (is_dir($dir)) {
+ $dirs = mustache_template_finder::get_template_directories_for_component('core_' . $subsystem, $themename);
+ $templatedirs['core_' . $subsystem] = $dirs;
+ }
}
+
+ // Look at all the templates dirs for plugins.
$plugintypes = core_component::get_plugin_types();
foreach ($plugintypes as $type => $dir) {
$plugins = core_component::get_plugin_list_with_file($type, 'templates', false);
foreach ($plugins as $plugin => $dir) {
if (!empty($dir) && is_dir($dir)) {
- $templatedirs[$type . '_' . $plugin] = $dir;
+ $pluginname = $type . '_' . $plugin;
+ $dirs = mustache_template_finder::get_template_directories_for_component($pluginname, $themename);
+ $templatedirs[$pluginname] = $dirs;
}
}
}
}
- foreach ($templatedirs as $templatecomponent => $dir) {
- // List it.
- $files = glob($dir . '/*.mustache');
+ foreach ($templatedirs as $templatecomponent => $dirs) {
+ foreach ($dirs as $dir) {
+ // List it.
+ $files = glob($dir . '/*.mustache');
- foreach ($files as $file) {
- $templatename = basename($file, '.mustache');
- if ($search == '' || strpos($templatename, $search) !== false) {
- $results[] = $templatecomponent . '/' . $templatename;
+ foreach ($files as $file) {
+ $templatename = basename($file, '.mustache');
+ if ($search == '' || strpos($templatename, $search) !== false) {
+ $results[$templatecomponent . '/' . $templatename] = 1;
+ }
}
}
}
+ $results = array_keys($results);
+ sort($results);
return $results;
}
+ /**
+ * Return a mustache template.
+ * Note - this function differs from the function core_output_load_template
+ * because it will never return a theme overridden version of a template.
+ *
+ * @param string $component The component that holds the template.
+ * @param string $template The name of the template.
+ * @return string the template
+ */
+ public static function load_canonical_template($component, $template) {
+ // Get the list of possible template directories.
+ $dirs = mustache_template_finder::get_template_directories_for_component($component);
+ $filename = false;
+
+ foreach ($dirs as $dir) {
+ // Skip theme dirs - we only want the original plugin/core template.
+ if (strpos($dir, "/theme/") === false) {
+ $candidate = $dir . $template . '.mustache';
+ if (file_exists($candidate)) {
+ $filename = $candidate;
+ break;
+ }
+ }
+ }
+ if ($filename === false) {
+ throw new moodle_exception('filenotfound', 'error');
+ }
+
+ $templatestr = file_get_contents($filename);
+ return $templatestr;
+ }
+
+
}
public static function list_templates_returns() {
return new external_multiple_structure(new external_value(PARAM_RAW, 'The template name (format is component/templatename)'));
}
+
+ /**
+ * Returns description of load_canonical_template() parameters.
+ *
+ * @return external_function_parameters
+ */
+ public static function load_canonical_template_parameters() {
+ return new external_function_parameters(
+ array('component' => new external_value(PARAM_COMPONENT, 'component containing the template'),
+ 'template' => new external_value(PARAM_ALPHANUMEXT, 'name of the template'))
+ );
+ }
+
+ /**
+ * Can this function be called directly from ajax?
+ *
+ * @return boolean
+ * @since Moodle 2.9
+ */
+ public static function load_canonical_template_is_allowed_from_ajax() {
+ return true;
+ }
+
+ /**
+ * Return a mustache template.
+ * Note - this function differs from the function core_output_load_template
+ * because it will never return a theme overridden version of a template.
+ *
+ * @param string $component The component that holds the template.
+ * @param string $template The name of the template.
+ * @return string the template
+ */
+ public static function load_canonical_template($component, $template) {
+ $params = self::validate_parameters(self::load_canonical_template_parameters(),
+ array('component' => $component,
+ 'template' => $template));
+
+ $component = $params['component'];
+ $template = $params['template'];
+
+ return api::load_canonical_template($component, $template);
+ }
+
+ /**
+ * Returns description of load_canonical_template() result value.
+ *
+ * @return external_description
+ */
+ public static function load_canonical_template_returns() {
+ return new external_value(PARAM_RAW, 'template');
+ }
}
foreach ($components as $component) {
$info = new stdClass();
$info->component = $component;
- if ($component == 'core') {
- $info->name = get_string('core_component', 'tool_templatelibrary');
+ if (strpos($component, 'core') === 0) {
+ $info->name = get_string('coresubsystem', 'tool_templatelibrary', $component);
} else {
$info->name = $pluginmanager->plugin_name($component);
}
'type' => 'read',
'capabilities'=> '',
),
+ 'tool_templatelibrary_load_canonical_template' => array(
+ 'classname' => 'tool_templatelibrary\external',
+ 'methodname' => 'load_canonical_template',
+ 'description' => 'Load a canonical template by name (not the theme overidden one).',
+ 'type' => 'read'
+ ),
+
);
$string['all'] = 'All components';
$string['component'] = 'Component';
-$string['core_component'] = 'Moodle core';
+$string['coresubsystem'] = 'Subsystem ({$a})';
$string['documentation'] = 'Documentation';
$string['example'] = 'Example';
$string['noresults'] = 'No results';
$this->assertEquals($result[0], "tool_templatelibrary/list_templates_page");
}
+ public function test_load_canonical_template() {
+ global $CFG;
+ $originaltheme = $CFG->theme;
+ // Change the theme to 'base' because it overrides these templates.
+ $CFG->theme = 'base';
+
+ $template = external::load_canonical_template('core', 'notification_problem');
+
+ // Only the base template should contain the docs.
+ $this->assertContains('@template core/notification_problem', $template);
+
+ // Restore the original theme.
+ $CFG->theme = $originaltheme;
+ }
}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2015021623; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2014110400; // Requires this Moodle version.
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2015050500; // Requires this Moodle version.
$plugin->component = 'tool_templatelibrary'; // Full name of the plugin (used for diagnostics).
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2014110400; // Requires this Moodle version
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->component = 'tool_unsuproles'; // Full name of the plugin (used for diagnostics)
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX).
-$plugin->requires = 2014110400; // Requires this Moodle version.
+$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2015050500; // Requires this Moodle version.
$plugin->component = 'tool_uploadcourse'; // Full name of the plugin (used for diagnostics).