exit(1);
}
+// Force OPcache reset if used, we do not want any stale caches
+// when preparing test environment.
+if (function_exists('opcache_reset')) {
+ opcache_reset();
+}
+
$help =
"Command line Moodle installer, creates config.php and initializes database.
Please note you must execute this script with the same uid as apache
exit(1);
}
+// Force OPcache reset if used, we do not want any stale caches
+// when preparing test environment.
+if (function_exists('opcache_reset')) {
+ opcache_reset();
+}
+
$help =
"Advanced command line Moodle database installer.
Please note you must execute this script with the same uid as apache.
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+// Force OPcache reset if used, we do not want any stale caches
+// when detecting if upgrade necessary or when running upgrade.
+if (function_exists('opcache_reset') and !isset($_SERVER['REMOTE_ADDR'])) {
+ opcache_reset();
+}
+
define('CLI_SCRIPT', true);
define('CACHE_DISABLE_ALL', true);
// we redirect to self once we known no upgrades are necessary.
// Note: $_GET and $_POST are used here intentionally because our param cleaning is not loaded yet.
define('CACHE_DISABLE_ALL', true);
+
+ // Force OPcache reset if used, we do not want any stale caches
+ // when detecting if upgrade necessary or when running upgrade.
+ if (function_exists('opcache_reset')) {
+ opcache_reset();
+ }
}
require('../config.php');
if ($pluginman->is_plugin_folder_removable($pluginfo->component)) {
$continueurl = new moodle_url($PAGE->url, array('delete' => $pluginfo->component, 'sesskey' => sesskey(), 'confirm' => 1));
echo $output->plugin_uninstall_results_removable_page($pluginman, $pluginfo, $progress, $continueurl);
+ // Reset op code caches.
+ if (function_exists('opcache_reset')) {
+ opcache_reset();
+ }
exit();
} else {
echo $output->plugin_uninstall_results_page($pluginman, $pluginfo, $progress);
+ // Reset op code caches.
+ if (function_exists('opcache_reset')) {
+ opcache_reset();
+ }
exit();
}
}
// So long, and thanks for all the bugs.
fulldelete($pluginfo->rootdir);
+ // Reset op code caches.
+ if (function_exists('opcache_reset')) {
+ opcache_reset();
+ }
redirect($PAGE->url);
}
1800 => new lang_string('numminutes', '', 30),
2700 => new lang_string('numminutes', '', 45),
3600 => new lang_string('numminutes', '', 60))));
- $temp->add(new admin_setting_configselect('fullnamedisplay', new lang_string('fullnamedisplay', 'admin'), new lang_string('configfullnamedisplay', 'admin'),
- 'language', array('language' => new lang_string('language'),
- 'firstname lastname' => new lang_string('firstname').' + '.new lang_string('lastname'),
- 'lastname firstname' => new lang_string('lastname').' + '.new lang_string('firstname'),
- 'firstname' => new lang_string('firstname'))));
+
$temp->add(new admin_setting_configcheckbox('extendedusernamechars', new lang_string('extendedusernamechars', 'admin'), new lang_string('configextendedusernamechars', 'admin'), 0));
$temp->add(new admin_setting_configtext('sitepolicy', new lang_string('sitepolicy', 'admin'), new lang_string('sitepolicy_help', 'admin'), '', PARAM_RAW));
$temp->add(new admin_setting_configtext('sitepolicyguest', new lang_string('sitepolicyguest', 'admin'), new lang_string('sitepolicyguest_help', 'admin'), (isset($CFG->sitepolicy) ? $CFG->sitepolicy : ''), PARAM_RAW));
'department' => new lang_string('department'),
'institution' => new lang_string('institution'),
)));
+ $temp->add(new admin_setting_configtext('fullnamedisplay', new lang_string('fullnamedisplay', 'admin'), new lang_string('configfullnamedisplay', 'admin'), 'language', PARAM_TEXT, 50));
$temp->add(new admin_setting_configtext('maxusersperpage', new lang_string('maxusersperpage','admin'), new lang_string('configmaxusersperpage','admin'), 100, PARAM_INT));
$temp->add(new admin_setting_configcheckbox('enablegravatar', new lang_string('enablegravatar', 'admin'), new lang_string('enablegravatar_help', 'admin'), 0));
$temp->add(new admin_setting_configtext('gravatardefaulturl', new lang_string('gravatardefaulturl', 'admin'), new lang_string('gravatardefaulturl_help', 'admin'), 'mm'));
die(); // No access from web!
}
+// Force OPcache reset if used, we do not want any stale caches
+// when preparing test environment.
+if (function_exists('opcache_reset')) {
+ opcache_reset();
+}
+
// Is not really necessary but adding it as is a CLI_SCRIPT.
define('CLI_SCRIPT', true);
--- /dev/null
+<?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/>.
+
+/**
+ * Capability tool settings form.
+ *
+ * Do no include this file, it is automatically loaded by the class loader!
+ *
+ * @package tool_capability
+ * @copyright 2013 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once($CFG->libdir.'/formslib.php');
+
+/**
+ * Class tool_capability_settings_form
+ *
+ * The settings form for the comparison of roles/capabilities.
+ *
+ * @copyright 2013 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class tool_capability_settings_form extends moodleform {
+
+ /**
+ * The form definition.
+ */
+ public function definition() {
+ $form = $this->_form;
+ $capabilities = $this->_customdata['capabilities'];
+ $roles = $this->_customdata['roles'];
+ // Set the form ID.
+ $form->setAttributes(array('id' => 'capability-overview-form') + $form->getAttributes());
+
+ $form->addElement('header', 'reportsettings', get_string('reportsettings', 'tool_capability'));
+ $form->addElement('html', html_writer::tag('p', get_string('intro', 'tool_capability'), array('id' => 'intro')));
+
+ $form->addElement('hidden', 'search');
+ $form->setType('search', PARAM_TEXT);
+
+ $attributes = array('multiple' => 'multiple', 'size' => 10, 'data-search' => 'capability');
+ $form->addElement('select', 'capability', get_string('capabilitylabel', 'tool_capability'), $capabilities, $attributes);
+ $form->setType('capability', PARAM_CAPABILITY);
+
+ $attributes = array('multiple' => 'multiple', 'size' => 10);
+ $form->addElement('select', 'roles', get_string('roleslabel', 'tool_capability'), $roles, $attributes);
+ $form->setType('roles', PARAM_TEXT);
+
+ $form->addElement('submit', 'submitbutton', get_string('getreport', 'tool_capability'));
+ }
+
+}
\ No newline at end of file
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
- * For a given capability, show what permission it has for every role, and
- * everywhere that it is overridden.
+ * For a given capability, show what permission it has for every role, and everywhere that it is overridden.
*
- * @package tool
- * @subpackage capability
+ * @package tool_capability
* @copyright 2008 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(dirname(__FILE__) . '/../../../config.php');
+require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/capability/locallib.php');
require_once($CFG->libdir.'/adminlib.php');
-// Check permissions.
-require_login();
-$systemcontext = context_system::instance();
-require_capability('moodle/role:manage', $systemcontext);
-
// Get URL parameters.
-$capability = optional_param('capability', '', PARAM_CAPABILITY);
-$roleids = optional_param_array('roles', array('0'), PARAM_INT);
-
-// Clean the passed in list of role ids. If 'All' selected as an option, or
-// if none were selected, do all roles.
-$allroles = role_fix_names(get_all_roles());
-$cleanedroleids = array();
-foreach ($roleids as $roleid) {
- if ($roleid == 0) {
- $cleanedroleids = array_keys($allroles);
- break;
- }
- if (array_key_exists($roleid, $allroles)) {
- $cleanedroleids[] = $roleid;
- }
-}
-if (empty($cleanedroleids)) {
- $cleanedroleids = array_keys($allroles);
-}
-
-// Include the required JavaScript.
-$PAGE->requires->js_init_call('M.tool_capability.init', array(get_string('search')));
+$systemcontext = context_system::instance();
+$contextid = optional_param('context', $systemcontext->id, PARAM_INT);
-// Log.
-add_to_log(SITEID, "admin", "tool capability", "tool/capability/index.php?capability=$capability", $capability);
+// Check permissions.
+list($context, $course, $cm) = get_context_info_array($contextid);
+require_login($course, false, $cm);
+require_capability('moodle/role:manage', $context);
// Print the header.
admin_externalpage_setup('toolcapability');
-echo $OUTPUT->header();
-// Prepare the list of capabilities to choose from
-$allcapabilities = fetch_context_capabilities($systemcontext);
+// Prepare the list of capabilities to choose from.
$capabilitychoices = array();
-foreach ($allcapabilities as $cap) {
+foreach ($context->get_capabilities() as $cap) {
$capabilitychoices[$cap->name] = $cap->name . ': ' . get_capability_string($cap->name);
}
-// Prepare the list of roles to choose from
+$allroles = role_fix_names(get_all_roles($context));
+// Prepare the list of roles to choose from.
$rolechoices = array('0' => get_string('all'));
foreach ($allroles as $role) {
$rolechoices[$role->id] = $role->localname;
}
-if (count($cleanedroleids) == count($allroles)) {
- // Select 'All', rather than each role individually.
- $selectedroleids = array('0');
-} else {
- $selectedroleids = $cleanedroleids;
-}
-// Print the settings form.
-echo $OUTPUT->box_start('generalbox boxwidthwide boxaligncenter');
-echo '<form method="get" action="" id="settingsform"><div>';
-echo $OUTPUT->heading(get_string('reportsettings', 'tool_capability'));
-echo '<p id="intro">', get_string('intro', 'tool_capability') , '</p>';
-echo '<p><label for="menucapability"> ' . get_string('capabilitylabel', 'tool_capability') . '</label></p>';
-echo html_writer::select($capabilitychoices, 'capability', $capability, array(''=>'choose'), array('size'=>10));
-echo '<p><label for="menuroles"> ' . get_string('roleslabel', 'tool_capability') . '</label></p>';
-echo html_writer::select($rolechoices, 'roles[]', $selectedroleids, false, array('size'=>10, 'multiple'=>'multiple'));
-echo '<p><input type="submit" id="settingssubmit" value="' . get_string('getreport', 'tool_capability') . '" /></p>';
-echo '</div></form>';
-echo $OUTPUT->box_end();
+$form = new tool_capability_settings_form(null, array(
+ 'capabilities' => $capabilitychoices,
+ 'roles' => $rolechoices
+));
+$PAGE->requires->yui_module(
+ 'moodle-tool_capability-search',
+ 'M.tool_capability.init_capability_search',
+ array(array('strsearch' => get_string('search')))
+);
-// If we have a capability, generate the report.
-if ($capability) {
-
- // Work out the bits needed for the SQL WHERE clauses.
- $params = array($capability);
- $sqlroletest = '';
- if (count($cleanedroleids) != count($allroles)) {
- list($sqlroletest, $roleparams) = $DB->get_in_or_equal($cleanedroleids);
- $params = array_merge($params, $roleparams);
- $sqlroletest = 'AND roleid ' . $sqlroletest;
- }
+// Log.
+$capabilities = array();
+$rolestoshow = array();
+$roleids = array('0');
+$cleanedroleids = array();
+if ($data = $form->get_data()) {
- // Get all the role_capabilities rows for this capability - that is, all
- // role definitions, and all role overrides.
- $rolecaps = $DB->get_records_sql("
- SELECT id, roleid, contextid, permission
- FROM {role_capabilities}
- WHERE capability = ? $sqlroletest", $params);
-
- // In order to display a nice tree of contexts, we need to get all the
- // ancestors of all the contexts in the query we just did.
- $relevantpaths = $DB->get_records_sql_menu("
- SELECT DISTINCT con.path, 1
- FROM {context} con JOIN {role_capabilities} rc ON rc.contextid = con.id
- WHERE capability = ? $sqlroletest", $params);
- $requiredcontexts = array($systemcontext->id);
- foreach ($relevantpaths as $path => $notused) {
- $requiredcontexts = array_merge($requiredcontexts, explode('/', trim($path, '/')));
+ $roleids = array();
+ if (!empty($data->roles)) {
+ $roleids = $data->roles;
}
- $requiredcontexts = array_unique($requiredcontexts);
-
- // Now load those contexts.
- list($sqlcontexttest, $contextparams) = $DB->get_in_or_equal($requiredcontexts);
- $contexts = get_sorted_contexts('ctx.id ' . $sqlcontexttest, $contextparams);
- // Prepare some empty arrays to hold the data we are about to compute.
- foreach ($contexts as $conid => $con) {
- $contexts[$conid]->children = array();
- $contexts[$conid]->rolecapabilities = array();
+ $capabilities = array();
+ if (!empty($data->capability)) {
+ $capabilities = $data->capability;
}
- // Put the contexts into a tree structure.
- foreach ($contexts as $conid => $con) {
- $context = context::instance_by_id($conid);
- $parentcontextid = get_parent_contextid($context);
- if ($parentcontextid) {
- $contexts[$parentcontextid]->children[] = $conid;
+ if (in_array('0', $roleids)) {
+ $rolestoshow = $allroles;
+ } else {
+ $cleanedroleids = array_intersect(array_keys($allroles), $roleids);
+ if (count($cleanedroleids) === 0) {
+ $rolestoshow = $allroles;
+ } else {
+ foreach ($cleanedroleids as $id) {
+ $rolestoshow[$id] = $allroles[$id];
+ }
}
}
+}
- // Put the role capabilities into the context tree.
- foreach ($rolecaps as $rolecap) {
- $contexts[$rolecap->contextid]->rolecapabilities[$rolecap->roleid] = $rolecap->permission;
- }
+add_to_log(SITEID, "admin", "tool capability", "tool/capability/index.php", count($capabilities));
- // Fill in any missing rolecaps for the system context.
- foreach ($cleanedroleids as $roleid) {
- if (!isset($contexts[$systemcontext->id]->rolecapabilities[$roleid])) {
- $contexts[$systemcontext->id]->rolecapabilities[$roleid] = CAP_INHERIT;
- }
- }
+$renderer = $PAGE->get_renderer('tool_capability');
- // Print the report heading.
- echo $OUTPUT->heading(get_string('reportforcapability', 'tool_capability', get_capability_string($capability)), 2, 'main', 'report');
- if (count($cleanedroleids) != count($allroles)) {
- $rolenames = array();
- foreach ($cleanedroleids as $roleid) {
- $rolenames[] = $allroles[$roleid]->localname;
- }
- echo '<p>', get_string('forroles', 'tool_capability', implode(', ', $rolenames)), '</p>';
- }
+echo $OUTPUT->header();
+
+$form->display();
- // Now, recursively print the contexts, and the role information.
- print_report_tree($systemcontext->id, $contexts, $allroles);
+// If we have a capability, generate the report.
+if (count($capabilities) && count($rolestoshow)) {
+ /* @var tool_capability_renderer $renderer */
+ echo $renderer->capability_comparison_table($capabilities, $context->id, $rolestoshow);
}
// Footer.
// Start the list item, and print the context name as a link to the place to
// make changes.
- if ($contextid == get_system_context()->id) {
+ if ($contextid == context_system::instance()->id) {
$url = "$CFG->wwwroot/$CFG->admin/roles/manage.php";
$title = get_string('changeroles', 'tool_capability');
} else {
/**
* Strings for component 'tool_capability', language 'en', branch 'MOODLE_22_STABLE'
*
- * @package tool
- * @subpackage capability
+ * @package tool_capability
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
--- /dev/null
+<?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/>.
+
+/**
+ * Functions used by the capability tool.
+ *
+ * @package tool_capability
+ * @copyright 2013 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Calculates capability data organised by context for the given roles.
+ *
+ * @param string $capability The capability to get data for.
+ * @param array $roles An array of roles to get data for.
+ * @return context[] An array of contexts.
+ */
+function tool_capability_calculate_role_data($capability, array $roles) {
+ global $DB;
+
+ $systemcontext = context_system::instance();
+ $roleids = array_keys($roles);
+
+ // Work out the bits needed for the SQL WHERE clauses.
+ $params = array($capability);
+ list($sqlroletest, $roleparams) = $DB->get_in_or_equal($roleids);
+ $params = array_merge($params, $roleparams);
+ $sqlroletest = 'AND roleid ' . $sqlroletest;
+
+ // Get all the role_capabilities rows for this capability - that is, all
+ // role definitions, and all role overrides.
+ $sql = 'SELECT id, roleid, contextid, permission
+ FROM {role_capabilities}
+ WHERE capability = ? '.$sqlroletest;
+ $rolecaps = $DB->get_records_sql($sql, $params);
+
+ // In order to display a nice tree of contexts, we need to get all the
+ // ancestors of all the contexts in the query we just did.
+ $sql = 'SELECT DISTINCT con.path, 1
+ FROM {context} con
+ JOIN {role_capabilities} rc ON rc.contextid = con.id
+ WHERE capability = ? '.$sqlroletest;
+ $relevantpaths = $DB->get_records_sql_menu($sql, $params);
+ $requiredcontexts = array($systemcontext->id);
+ foreach ($relevantpaths as $path => $notused) {
+ $requiredcontexts = array_merge($requiredcontexts, explode('/', trim($path, '/')));
+ }
+ $requiredcontexts = array_unique($requiredcontexts);
+
+ // Now load those contexts.
+ list($sqlcontexttest, $contextparams) = $DB->get_in_or_equal($requiredcontexts);
+ $contexts = get_sorted_contexts('ctx.id ' . $sqlcontexttest, $contextparams);
+
+ // Prepare some empty arrays to hold the data we are about to compute.
+ foreach ($contexts as $conid => $con) {
+ $contexts[$conid]->children = array();
+ $contexts[$conid]->rolecapabilities = array();
+ }
+
+ // Put the contexts into a tree structure.
+ foreach ($contexts as $conid => $con) {
+ $context = context::instance_by_id($conid);
+ $parentcontextid = get_parent_contextid($context);
+ if ($parentcontextid) {
+ $contexts[$parentcontextid]->children[] = $conid;
+ }
+ }
+
+ // Put the role capabilities into the context tree.
+ foreach ($rolecaps as $rolecap) {
+ $contexts[$rolecap->contextid]->rolecapabilities[$rolecap->roleid] = $rolecap->permission;
+ }
+
+ // Fill in any missing rolecaps for the system context.
+ foreach ($roleids as $roleid) {
+ if (!isset($contexts[$systemcontext->id]->rolecapabilities[$roleid])) {
+ $contexts[$systemcontext->id]->rolecapabilities[$roleid] = CAP_INHERIT;
+ }
+ }
+
+ return $contexts;
+}
\ No newline at end of file
+++ /dev/null
-
-M.tool_capability = {
- select: null,
- input: null,
- button: null,
-
- init: function(Y, strsearch) {
- var context = M.tool_capability;
-
- // Find the form controls.
- context.select = document.getElementById('menucapability');
- context.button = document.getElementById('settingssubmit');
-
- // Create a div to hold the search UI.
- var div = document.createElement('div');
- div.id = 'capabilitysearchui';
-
- // Find the capability search input.
- var input = document.createElement('input');
- input.type = 'text';
- input.id = 'capabilitysearch';
- context.input = input;
-
- // Create a label for the search input.
- var label = document.createElement('label');
- label.htmlFor = input.id;
- label.appendChild(document.createTextNode(strsearch + ' '));
-
- // Tie it all together
- div.appendChild(label);
- div.appendChild(input);
- context.select.parentNode.insertBefore(div, context.select);
- Y.on('keyup', context.typed, input);
- Y.on('change', context.validate, context.select);
- context.select.options[0].style.display = 'none';
- context.validate();
- },
-
- typed: function() {
- var context = M.tool_capability;
-
- var filtertext = context.input.value;
- var options = context.select.options;
- var onlycapability = -1;
- for (var i = 1; i < options.length; i++) {
- if (options[i].text.indexOf(filtertext) >= 0) {
- options[i].disabled = false;
- options[i].style.display = 'block';
- if (onlycapability == -1) {
- onlycapability = i;
- } else {
- onlycapability = -2;
- }
- } else {
- options[i].disabled = true;
- options[i].selected = false;
- options[i].style.display = 'none';
- }
- }
- if (onlycapability >= 0) {
- options[onlycapability].selected = true;
- }
- if (onlycapability == -1) {
- context.input.className = "error";
- } else {
- context.input.className = "";
- }
- context.validate();
- },
-
- validate: function() {
- var context = M.tool_capability;
- context.button.disabled = (context.select.value == '');
- }
-}
\ No newline at end of file
--- /dev/null
+<?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/>.
+
+/**
+ * Capability tool renderer.
+ *
+ * @package tool_capability
+ * @copyright 2013 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * The primary renderer for the capability tool.
+ *
+ * @copyright 2013 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class tool_capability_renderer extends plugin_renderer_base {
+
+ /**
+ * Returns an array of permission strings.
+ *
+ * @return lang_string[]
+ */
+ protected function get_permission_strings() {
+ static $strpermissions;
+ if (!$strpermissions) {
+ $strpermissions = array(
+ CAP_INHERIT => new lang_string('inherit', 'role'),
+ CAP_ALLOW => new lang_string('allow', 'role'),
+ CAP_PREVENT => new lang_string('prevent', 'role'),
+ CAP_PROHIBIT => new lang_string('prohibit', 'role')
+ );
+ }
+ return $strpermissions;
+ }
+
+ /**
+ * Returns an array of permission CSS classes.
+ *
+ * @return string[]
+ */
+ protected function get_permission_classes() {
+ static $permissionclasses;
+ if (!$permissionclasses) {
+ $permissionclasses = array(
+ CAP_INHERIT => 'inherit',
+ CAP_ALLOW => 'allow',
+ CAP_PREVENT => 'prevent',
+ CAP_PROHIBIT => 'prohibit',
+ );
+ }
+ return $permissionclasses;
+ }
+
+ /**
+ * Produces a table to visually compare roles and capabilities.
+ *
+ * @param array $capabilities An array of capabilities to show comparison for.
+ * @param int $contextid The context we are displaying for.
+ * @param array $roles An array of roles to show comparison for.
+ * @return string
+ */
+ public function capability_comparison_table(array $capabilities, $contextid, array $roles) {
+
+ $strpermissions = $this->get_permission_strings();
+ $permissionclasses = $this->get_permission_classes();
+
+ if ($contextid === context_system::instance()->id) {
+ $strpermissions[CAP_INHERIT] = new lang_string('notset', 'role');
+ }
+
+ $table = new html_table();
+ $table->attributes['class'] = 'comparisontable';
+ $table->head = array(' ');
+ foreach ($roles as $role) {
+ $url = new moodle_url('/admin/roles/override.php', array('contextid' => $contextid, 'roleid' => $role->id));
+ $table->head[] = html_writer::div(html_writer::link($url, $role->localname));
+ }
+ $table->data = array();
+
+ foreach ($capabilities as $capability) {
+ $contexts = tool_capability_calculate_role_data($capability, $roles);
+ $captitle = new html_table_cell(get_capability_string($capability) . html_writer::span($capability));
+ $captitle->header = true;
+
+ $row = new html_table_row(array($captitle));
+
+ foreach ($roles as $role) {
+ if (isset($contexts[$contextid]->rolecapabilities[$role->id])) {
+ $permission = $contexts[$contextid]->rolecapabilities[$role->id];
+ } else {
+ $permission = CAP_INHERIT;
+ }
+ $cell = new html_table_cell($strpermissions[$permission]);
+ $cell->attributes['class'] = $permissionclasses[$permission];
+ $row->cells[] = $cell;
+ }
+
+ $table->data[] = $row;
+ }
+
+ // Start the list item, and print the context name as a link to the place to make changes.
+ if ($contextid == context_system::instance()->id) {
+ $url = new moodle_url('/admin/roles/manage.php');
+ $title = get_string('changeroles', 'tool_capability');
+ } else {
+ $url = new moodle_url('/admin/roles/override.php', array('contextid' => $contextid));
+ $title = get_string('changeoverrides', 'tool_capability');
+ }
+ $context = context::instance_by_id($contextid);
+ $html = $this->output->heading(html_writer::link($url, $context->get_context_name(), array('title' => $title)), 3);
+ $html .= html_writer::table($table);
+ // If there are any child contexts, print them recursively.
+ if (!empty($contexts[$contextid]->children)) {
+ foreach ($contexts[$contextid]->children as $childcontextid) {
+ $html .= $this->capability_comparison_table($capabilities, $childcontextid, $roles, true);
+ }
+ }
+ return $html;
+ }
+
+}
\ No newline at end of file
/**
* Capability overview settings
*
- * @package tool
- * @subpackage capability
+ * @package tool_capability
* @copyright 2008 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
-$ADMIN->add('roles', new admin_externalpage('toolcapability', get_string('pluginname', 'tool_capability'), "$CFG->wwwroot/$CFG->admin/tool/capability/index.php",'moodle/role:manage'));
+$ADMIN->add('roles', new admin_externalpage(
+ 'toolcapability',
+ get_string('pluginname', 'tool_capability'),
+ "$CFG->wwwroot/$CFG->admin/tool/capability/index.php",
+ 'moodle/role:manage'
+));
--- /dev/null
+.path-admin-tool-capability .comparisontable {margin-top:150px;}
+.path-admin-tool-capability .comparisontable th,
+.path-admin-tool-capability .comparisontable td {vertical-align:middle;padding:0.4em 0.5em 0.3em;}
+.path-admin-tool-capability .comparisontable thead th {vertical-align:bottom;background:none;}
+.path-admin-tool-capability .comparisontable thead th div {position:relative;}
+.path-admin-tool-capability .comparisontable thead th div > a {
+ position:absolute;
+ top:-1.75em;
+ left:1em;
+ width:150px;
+ text-align:left;
+ margin-bottom:1em;
+ text-indent:-1.45em;
+
+ -webkit-transform-origin: top left;
+ -moz-transform-origin: top left;
+ -ms-transform-origin: top left;
+ -o-transform-origin: top left;
+
+ -webkit-transform: rotate(315deg);
+ -moz-transform: rotate(315deg);
+ -ms-transform: rotate(315deg);
+ -o-transform: rotate(315deg);
+}
+.path-admin-tool-capability .comparisontable tbody th {background-color:#EEE;text-align:right;border:1px solid #DFDFDF;}
+.path-admin-tool-capability .comparisontable tbody th span {display:block;color:#666;font-size:80%;}
+.path-admin-tool-capability .comparisontable tbody td {border:1px solid #DFDFDF;}
+
+.path-admin-tool-capability .comparisontable .inherit {color:#666;}
+.path-admin-tool-capability .comparisontable .allow {color:#006600;font-weight:bold;}
+.path-admin-tool-capability .comparisontable .prevent {color:#ad6704;font-weight:bold;}
+.path-admin-tool-capability .comparisontable .prohibit {color:#880000;font-weight:bold;}
\ No newline at end of file
/**
* Version details.
*
- * @package tool
- * @subpackage capability
+ * @package tool_capability
* @copyright 2011 Petr Skoda
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2013050100; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires = 2013050100; // Requires this Moodle version
-$plugin->component = 'tool_capability'; // Full name of the plugin (used for diagnostics)
+$plugin->version = 2013050100; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires = 2013050100; // Requires this Moodle version.
+$plugin->component = 'tool_capability'; // Full name of the plugin (used for diagnostics).
--- /dev/null
+{
+ "name": "moodle-tool_capability-search",
+ "builds": {
+ "moodle-tool_capability-search": {
+ "jsfiles": [
+ "search.js"
+ ]
+ }
+ }
+}
--- /dev/null
+/**
+ * This file contains the capability overview search functionality.
+ *
+ * @module moodle-tool_capability-search
+ */
+
+/**
+ * Constructs a new capability search manager.
+ *
+ * @namespace M.tool_capability.search
+ * @class Search
+ * @constructor
+ * @extends Y.Base
+ */
+var SEARCH = function() {
+ SEARCH.superclass.constructor.apply(this, arguments);
+};
+SEARCH.prototype = {
+ /**
+ * The search form.
+ * @property form
+ * @type Node
+ * @protected
+ */
+ form : null,
+ /**
+ * The capability select node.
+ * @property select
+ * @type Node
+ * @protected
+ */
+ select: null,
+ /**
+ * An associative array of search option. Populated from the select node above during initialisation.
+ * @property selectoptions
+ * @type Object
+ * @protected
+ */
+ selectoptions : {},
+ /**
+ * The search input field.
+ * @property input
+ * @type Node
+ * @protected
+ */
+ input: null,
+ /**
+ * The submit button for the form.
+ * @property button
+ * @type Node
+ * @protected
+ */
+ button: null,
+ /**
+ * The last search node if there is one.
+ * If there is a last search node then the last search term will be persisted between requests.
+ * @property lastsearch
+ * @type Node
+ * @protected
+ */
+ lastsearch : null,
+ /**
+ * Constructs the search manager.
+ * @method initializer
+ */
+ initializer : function() {
+ this.form = Y.one('#capability-overview-form');
+ this.select = this.form.one('select[data-search=capability]');
+ this.select.setStyle('minWidth', this.select.get('offsetWidth'));
+ this.select.get('options').each(function(option) {
+ var capability = option.get('value');
+ this.selectoptions[capability] = option;
+ }, this);
+ this.button = this.form.all('input[type=submit]');
+ this.lastsearch = this.form.one('input[name=search]');
+
+ var div = Y.Node.create('<div id="capabilitysearchui"></div>'),
+ label = Y.Node.create('<label for="capabilitysearch">'+this.get('strsearch')+'</label>');
+ this.input = Y.Node.create('<input type="text" id="capabilitysearch" />');
+
+ div.append(label).append(this.input);
+
+ this.select.insert(div, 'before');
+ this.select.one('option').setStyle('display', 'none');
+
+ this.input.on('keyup', this.typed, this);
+ this.select.on('change', this.validate, this);
+
+ if (this.lastsearch) {
+ this.input.set('value', this.lastsearch.get('value'));
+ this.typed();
+ if (this.select.one('option[selected]')) {
+ this.select.set('scrollTop', this.select.one('option[selected]').get('getX'));
+ }
+ }
+
+ this.validate();
+ },
+ /**
+ * Disables the submit button if there are no capabilities selected.
+ * @method validate
+ */
+ validate : function() {
+ this.button.set('disabled', (this.select.get('value') === ''));
+ },
+ /**
+ * Called when ever the user types into the search field.
+ * This method hides any capabilities that don't match the search term.
+ * @method typed
+ */
+ typed : function() {
+ var search = this.input.get('value'),
+ matching = 0,
+ last = null,
+ capability;
+ if (this.lastsearch) {
+ this.lastsearch.set('value', search);
+ }
+ this.select.all('option').remove();
+ for (capability in this.selectoptions) {
+ if (capability.indexOf(search) >= 0) {
+ matching++;
+ this.select.append(this.selectoptions[capability]);
+ }
+ }
+ if (matching === 0) {
+ this.input.addClass("error");
+ } else {
+ this.input.removeClass("error");
+ if (matching === 1) {
+ last.set('selected', true);
+ }
+ }
+ this.validate();
+ }
+};
+Y.extend(SEARCH, Y.Base, SEARCH.prototype, {
+ NAME : 'tool_capability-search',
+ ATTRS : {
+ strsearch : {}
+ }
+});
+
+/**
+ * Core namespace.
+ * @static
+ * @class tool_capability
+ */
+M.tool_capability = M.tool_capability || {};
+
+/**
+ * Initialises capability search functionality.
+ * @static
+ * @method init_capability_search
+ * @param {Object} options
+ */
+M.tool_capability.init_capability_search = function(options) {
+ new SEARCH(options);
+};
\ No newline at end of file
--- /dev/null
+{
+ "moodle-tool_capability-search": {
+ "requires": [
+ "base",
+ "node"
+ ]
+ }
+}
require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/customlang/filter_form.php');
require_login(SITEID, false);
-require_capability('tool/customlang:edit', get_system_context());
+require_capability('tool/customlang:edit', context_system::instance());
$lng = required_param('lng', PARAM_LANG);
$currentpage = optional_param('p', 0, PARAM_INT);
require_once($CFG->libdir.'/adminlib.php');
require_login(SITEID, false);
-require_capability('tool/customlang:view', get_system_context());
+require_capability('tool/customlang:view', context_system::instance());
$action = optional_param('action', '', PARAM_ALPHA);
$confirm = optional_param('confirm', false, PARAM_BOOL);
// pre-output actions
if ($action === 'checkout') {
require_sesskey();
- require_capability('tool/customlang:edit', get_system_context());
+ require_capability('tool/customlang:edit', context_system::instance());
if (empty($lng)) {
print_error('missingparameter');
}
if ($action === 'checkin') {
require_sesskey();
- require_capability('tool/customlang:edit', get_system_context());
+ require_capability('tool/customlang:edit', context_system::instance());
if (empty($lng)) {
print_error('missingparameter');
}
}
$menu = array();
-if (has_capability('tool/customlang:edit', get_system_context())) {
+if (has_capability('tool/customlang:edit', context_system::instance())) {
$menu['checkout'] = array(
'title' => get_string('checkout', 'tool_customlang'),
'url' => new moodle_url($PAGE->url, array('action' => 'checkout', 'lng' => $lng)),
}
$PAGE->set_url('/admin/tool/generator/index.php');
-$PAGE->set_context(get_system_context());
+$PAGE->set_context(context_system::instance());
$PAGE->set_pagelayout('base');
$generator = new generator_web();
$generator->setup();
die; // no access from web!
}
+// Force OPcache reset if used, we do not want any stale caches
+// when preparing test environment.
+if (function_exists('opcache_reset')) {
+ opcache_reset();
+}
+
require_once(__DIR__.'/../../../../lib/clilib.php');
require_once(__DIR__.'/../../../../lib/phpunit/bootstraplib.php');
require_once(__DIR__.'/../../../../lib/testing/lib.php');
}
$countries = get_string_manager()->get_list_of_countries(true);
+$namefields = get_all_user_name_fields(true);
foreach ($users as $key => $id) {
- $user = $DB->get_record('user', array('id'=>$id, 'deleted'=>0), 'id, firstname, lastname, username, email, country, lastaccess, city');
+ $user = $DB->get_record('user', array('id'=>$id, 'deleted'=>0), 'id, ' . $namefields . ', username,
+ email, country, lastaccess, city');
$user->fullname = fullname($user, true);
$user->country = @$countries[$user->country];
unset($user->firstname);
$countries = get_string_manager()->get_list_of_countries(true);
+$namefields = get_all_user_name_fields(true);
foreach ($users as $key => $id) {
- $user = $DB->get_record('user', array('id'=>$id), 'id, firstname, lastname, username, email, country, lastaccess, city');
+ $user = $DB->get_record('user', array('id'=>$id), 'id, ' . $namefields . ', username, email, country, lastaccess, city');
$user->fullname = fullname($user, true);
$user->country = @$countries[$user->country];
unset($user->firstname);
/// User removal
// Find users in DB that aren't in ldap -- to be removed!
// this is still not as scalable (but how often do we mass delete?)
- if ($this->config->removeuser != AUTH_REMOVEUSER_KEEP) {
- $sql = 'SELECT u.*
+
+ if ($this->config->removeuser == AUTH_REMOVEUSER_FULLDELETE) {
+ $sql = "SELECT u.*
FROM {user} u
- LEFT JOIN {tmp_extuser} e ON (u.username = e.username AND u.mnethostid = e.mnethostid)
- WHERE u.auth = ?
+ LEFT JOIN {tmp_extuser} e ON (u.username = e.username AND u.mnethostid = e.mnethostid)
+ WHERE u.auth = :auth
AND u.deleted = 0
- AND e.username IS NULL';
- $remove_users = $DB->get_records_sql($sql, array($this->authtype));
+ AND e.username IS NULL";
+ $remove_users = $DB->get_records_sql($sql, array('auth'=>$this->authtype));
if (!empty($remove_users)) {
print_string('userentriestoremove', 'auth_ldap', count($remove_users));
-
foreach ($remove_users as $user) {
- if ($this->config->removeuser == AUTH_REMOVEUSER_FULLDELETE) {
- if (delete_user($user)) {
- echo "\t"; print_string('auth_dbdeleteuser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
- } else {
- echo "\t"; print_string('auth_dbdeleteusererror', 'auth_db', $user->username); echo "\n";
- }
- } else if ($this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) {
- $updateuser = new stdClass();
- $updateuser->id = $user->id;
- $updateuser->auth = 'nologin';
- $DB->update_record('user', $updateuser);
- echo "\t"; print_string('auth_dbsuspenduser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
- $euser = $DB->get_record('user', array('id' => $user->id));
- events_trigger('user_updated', $euser);
+ if (delete_user($user)) {
+ echo "\t"; print_string('auth_dbdeleteuser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
+ } else {
+ echo "\t"; print_string('auth_dbdeleteusererror', 'auth_db', $user->username); echo "\n";
}
}
} else {
print_string('nouserentriestoremove', 'auth_ldap');
}
- unset($remove_users); // free mem!
+ unset($remove_users); // Free mem!
+
+ } else if ($this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) {
+ $sql = "SELECT u.*
+ FROM {user} u
+ LEFT JOIN {tmp_extuser} e ON (u.username = e.username AND u.mnethostid = e.mnethostid)
+ WHERE u.auth = :auth
+ AND u.deleted = 0
+ AND u.suspended = 0
+ AND e.username IS NULL";
+ $remove_users = $DB->get_records_sql($sql, array('auth'=>$this->authtype));
+
+ if (!empty($remove_users)) {
+ print_string('userentriestoremove', 'auth_ldap', count($remove_users));
+
+ foreach ($remove_users as $user) {
+ $updateuser = new stdClass();
+ $updateuser->id = $user->id;
+ $updateuser->suspended = 1;
+ $DB->update_record('user', $updateuser);
+ echo "\t"; print_string('auth_dbsuspenduser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
+ $euser = $DB->get_record('user', array('id' => $user->id));
+ events_trigger('user_updated', $euser);
+ session_kill_user($user->id);
+ }
+ } else {
+ print_string('nouserentriestoremove', 'auth_ldap');
+ }
+ unset($remove_users); // Free mem!
}
/// Revive suspended users
$sql = "SELECT u.id, u.username
FROM {user} u
JOIN {tmp_extuser} e ON (u.username = e.username AND u.mnethostid = e.mnethostid)
- WHERE u.auth = 'nologin' AND u.deleted = 0";
- $revive_users = $DB->get_records_sql($sql);
+ WHERE (u.auth = 'nologin' OR (u.auth = ? AND u.suspended = 1)) AND u.deleted = 0";
+ // Note: 'nologin' is there for backwards compatibility.
+ $revive_users = $DB->get_records_sql($sql, array($this->authtype));
if (!empty($revive_users)) {
print_string('userentriestorevive', 'auth_ldap', count($revive_users));
$updateuser = new stdClass();
$updateuser->id = $user->id;
$updateuser->auth = $this->authtype;
+ $updateuser->suspended = 0;
$DB->update_record('user', $updateuser);
echo "\t"; print_string('auth_dbreviveduser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
$euser = $DB->get_record('user', array('id' => $user->id));
$id = $DB->insert_record('user', $user);
echo "\t"; print_string('auth_dbinsertuser', 'auth_db', array('name'=>$user->username, 'id'=>$id)); echo "\n";
- $euser = $DB->get_record('user', array('id' => $user->id));
+ $euser = $DB->get_record('user', array('id' => $id));
events_trigger('user_created', $euser);
if (!empty($this->config->forcechangepassword)) {
set_user_preference('auth_forcepasswordchange', 1, $id);
defined('MOODLE_INTERNAL') || die();
-class auth_ldap_testcase extends advanced_testcase {
+class auth_ldap_plugin_testcase extends advanced_testcase {
public function test_auth_ldap() {
global $CFG, $DB;
$auth->sync_users(true);
ob_end_clean();
- $this->assertEquals(4, $DB->count_records('user', array('auth'=>'ldap')));
- $this->assertEquals(1, $DB->count_records('user', array('auth'=>'nologin', 'username'=>'username1')));
- $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
+ $this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
+ $this->assertEquals(0, $DB->count_records('user', array('auth'=>'nologin', 'username'=>'username1')));
+ $this->assertEquals(1, $DB->count_records('user', array('auth'=>'ldap', 'suspended'=>'1', 'username'=>'username1')));
$this->assertEquals(0, $DB->count_records('user', array('deleted'=>1)));
$this->assertEquals(2, $DB->count_records('role_assignments'));
$this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id)));
$this->assertEquals(2, $DB->count_records('role_assignments'));
$this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id)));
+ $DB->set_field('user', 'auth', 'nologin', array('username'=>'username1'));
+
+ ob_start();
+ $auth->sync_users(true);
+ ob_end_clean();
+
+ $this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
+ $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
+ $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1)));
+ $this->assertEquals(2, $DB->count_records('role_assignments'));
+ $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id)));
set_config('removeuser', AUTH_REMOVEUSER_FULLDELETE, 'auth/ldap');
}
// check remote login permissions
- if (! has_capability('moodle/site:mnetlogintoremote', get_system_context())
+ if (! has_capability('moodle/site:mnetlogintoremote', context_system::instance())
or is_mnet_remote_user($USER)
or isguestuser()
or !isloggedin()) {
// Then, the fields potentially needing anonymization
$anonfields = array(
- 'username', 'idnumber', 'firstname', 'lastname',
- 'email', 'icq', 'skype',
+ 'username', 'idnumber', 'email', 'icq', 'skype',
'yahoo', 'aim', 'msn', 'phone1',
'phone2', 'institution', 'department', 'address',
'city', 'country', 'lastip', 'picture',
'url', 'description', 'descriptionformat', 'imagealt', 'auth');
+ $anonfields = array_merge($anonfields, get_all_user_name_fields());
// Add anonymized fields to $userfields with custom final element
foreach ($anonfields as $field) {
// Build the array of contexts we are going to look
$systemctx = context_system::instance();
$coursectx = context_course::instance($courseid);
- $parentctxs= get_parent_contexts($coursectx);
+ $parentctxs = $coursectx->get_parent_context_ids();
foreach ($parentctxs as $parentctx) {
// Exclude system context
if ($parentctx == $systemctx->id) {
fflush($handle);
fclose($handle);
$locking->unlock('configwrite', 'config');
+ // Tell PHP to recompile the script.
+ core_component::invalidate_opcode_php_cache($cachefile);
} else {
throw new cache_exception('ex_configcannotsave', 'cache', '', null, 'Unable to open the cache config file.');
}
*/
public static function get_store_instance_actions($name, array $storedetails) {
$actions = array();
- if (has_capability('moodle/site:config', get_system_context())) {
+ if (has_capability('moodle/site:config', context_system::instance())) {
$baseurl = new moodle_url('/cache/admin.php', array('store' => $name, 'sesskey' => sesskey()));
if (empty($storedetails['default'])) {
$actions[] = array(
}
}
if ($group === false) {
- if (!empty($CFG->calendar_adminseesall) && has_any_capability($allgroupscaps, get_system_context())) {
+ if (!empty($CFG->calendar_adminseesall) && has_any_capability($allgroupscaps, context_system::instance())) {
$group = true;
} else if ($isloggedin) {
$groupids = array();
function calendar_get_allowed_types(&$allowed, $course = null) {
global $USER, $CFG, $DB;
$allowed = new stdClass();
- $allowed->user = has_capability('moodle/calendar:manageownentries', get_system_context());
+ $allowed->user = has_capability('moodle/calendar:manageownentries', context_system::instance());
$allowed->groups = false; // This may change just below
$allowed->courses = false; // This may change just below
$allowed->site = has_capability('moodle/calendar:manageentries', context_course::instance(SITEID));
// Create a few events and do asserts.
$this->create_calendar_event('test', $USER->id);
- $count = count($DB->get_records("event", array('name' => 'test')));
+ $where = $DB->sql_compare_text('name') ." = ?";
+ $count = count($DB->get_records_select("event", $where, array('test')));
$this->assertEquals(1, $count);
$aftercount = count($DB->get_records("event"));
$this->assertEquals($prevcount + 1, $aftercount);
$this->create_calendar_event('user', $USER->id, 'user', 3);
- $count = count($DB->get_records("event", array('name' => 'user')));
+ $where = $DB->sql_compare_text('name') ." = ?";
+ $count = count($DB->get_records_select("event", $where, array('user')));
+
$this->assertEquals(3, $count);
$aftercount = count($DB->get_records("event"));
$this->assertEquals($prevcount + 4, $aftercount);
}
$context = context_coursecat::instance($parent);
} else {
- $context = get_system_context();
+ $context = context_system::instance();
}
$PAGE->set_context($context);
$category = new stdClass();
// get list of categories to use as parents, with site as the first one
$options = array();
- if (has_capability('moodle/category:manage', get_system_context()) || $category->parent == 0) {
+ if (has_capability('moodle/category:manage', context_system::instance()) || $category->parent == 0) {
$options[0] = get_string('top');
}
if ($category->id) {
foreach ($rs as $instance) {
$coursecontext = context_course::instance($instance->courseid);
- $contextids = get_parent_contexts($coursecontext);
+ $contextids = $coursecontext->get_parent_context_ids();
array_pop($contextids); // Remove system context, we are interested in categories only.
list($contextids, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED, 'c');
// First find out if any parent category context contains interesting role assignments.
$coursecontext = context_course::instance($course->id);
- $contextids = get_parent_contexts($coursecontext);
+ $contextids = $coursecontext->get_parent_context_ids();
array_pop($contextids); // Remove system context, we are interested in categories only.
list($roleids, $params) = $DB->get_in_or_equal(array_keys($roles), SQL_PARAMS_NAMED, 'r');
if (!has_capability('moodle/course:enrolconfig', $coursecontext) or !has_capability('enrol/cohort:config', $coursecontext)) {
return false;
}
- list($sqlparents, $params) = $DB->get_in_or_equal(get_parent_contexts($coursecontext));
+ list($sqlparents, $params) = $DB->get_in_or_equal($coursecontext->get_parent_context_ids());
$sql = "SELECT id, contextid
FROM {cohort}
WHERE contextid $sqlparents
$enrolled[] = $instance->customint1;
}
}
- list($sqlparents, $params) = $DB->get_in_or_equal(get_parent_contexts($context));
+ list($sqlparents, $params) = $DB->get_in_or_equal($context->get_parent_context_ids());
$sql = "SELECT id, name, idnumber, contextid
FROM {cohort}
WHERE contextid $sqlparents
$course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
$coursecontext = context_course::instance($courseid, IGNORE_MISSING);
if ($courseid == SITEID) {
- $context = get_system_context();
+ $context = context_system::instance();
} else {
$context = $coursecontext;
}
public function get_total_other_users() {
global $DB;
if ($this->totalotherusers === null) {
- list($ctxcondition, $params) = $DB->get_in_or_equal(get_parent_contexts($this->context, true), SQL_PARAMS_NAMED, 'ctx');
+ list($ctxcondition, $params) = $DB->get_in_or_equal($this->context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'ctx');
$params['courseid'] = $this->course->id;
$sql = "SELECT COUNT(DISTINCT u.id)
FROM {role_assignments} ra
}
$key = md5("$sort-$direction-$page-$perpage");
if (!array_key_exists($key, $this->otherusers)) {
- list($ctxcondition, $params) = $DB->get_in_or_equal(get_parent_contexts($this->context, true), SQL_PARAMS_NAMED, 'ctx');
+ list($ctxcondition, $params) = $DB->get_in_or_equal($this->context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'ctx');
$params['courseid'] = $this->course->id;
$params['cid'] = $this->course->id;
$sql = "SELECT ra.id as raid, ra.contextid, ra.component, ctx.contextlevel, ra.roleid, u.*, ue.lastseen
$PAGE->set_url('/error/');
$PAGE->set_title($site->fullname .':Error');
$PAGE->set_heading($site->fullname .': Error 404');
- $PAGE->set_context(get_system_context());
+ $PAGE->set_context(context_system::instance());
$PAGE->navbar->add('Error 404 - File not Found');
echo $OUTPUT->header();
echo $OUTPUT->box(get_string('pagenotexist', 'error'). '<br />'.s($requesturi), 'generalbox boxaligncenter');
$browser = get_file_browser();
if (empty($fileinfo['contextid'])) {
- $context = get_system_context();
+ $context = context_system::instance();
} else {
$context = context::instance_by_id($fileinfo['contextid']);
}
*
* @category grading
* @example $manager = get_grading_manager($areaid);
- * @example $manager = get_grading_manager(get_system_context());
+ * @example $manager = get_grading_manager(context_system::instance());
* @example $manager = get_grading_manager($context, 'mod_assignment', 'submission');
* @param stdClass|int|null $context_or_areaid if $areaid is passed, no other parameter is needed
* @param string|null $component the frankenstyle name of the component
case 'ajax_getmembersingroup':
$roles = array();
- if ($groupmemberroles = groups_get_members_by_role($groupids[0], $courseid, 'u.id, u.firstname, u.lastname')) {
+ if ($groupmemberroles = groups_get_members_by_role($groupids[0], $courseid, 'u.id, ' . get_all_user_name_fields(true, 'u'))) {
foreach($groupmemberroles as $roleid=>$roledata) {
$shortroledata = new stdClass();
$shortroledata->name = $roledata->name;
$atleastonemember = false;
if ($singlegroup) {
- if ($groupmemberroles = groups_get_members_by_role($groupids[0], $courseid, 'u.id, u.firstname, u.lastname')) {
+ if ($groupmemberroles = groups_get_members_by_role($groupids[0], $courseid, 'u.id, ' . get_all_user_name_fields(true, 'u'))) {
foreach($groupmemberroles as $roleid=>$roledata) {
echo '<optgroup label="'.s($roledata->name).'">';
foreach($roledata->users as $member) {
list($sort, $sortparams) = users_order_by_sql('u');
-$sql = "SELECT g.id AS groupid, gg.groupingid, u.id AS userid, u.firstname, u.lastname, u.idnumber, u.username
+$allnames = get_all_user_name_fields(true, 'u');
+$sql = "SELECT g.id AS groupid, gg.groupingid, u.id AS userid, $allnames, u.idnumber, u.username
FROM {groups} g
LEFT JOIN {groupings_groups} gg ON g.id = gg.groupid
LEFT JOIN {groups_members} gm ON g.id = gm.groupid
$user->lastname = $row->lastname;
$user->username = $row->username;
$user->idnumber = $row->idnumber;
+ foreach (get_all_user_name_fields() as $addname) {
+ $user->$addname = $row->$addname;
+ }
if (!$row->groupingid) {
$row->groupingid = -1;
}
$string['configfrontpagecourselimit'] = 'Maximum number of courses';
$string['configfrontpagecourselimithelp'] = 'Maximum number of courses to be displayed on the site\'s front page in course listings.';
$string['configfrontpageloggedin'] = 'The items selected above will be displayed on the site\'s front page when a user is logged in.';
-$string['configfullnamedisplay'] = 'This defines how names are shown when they are displayed in full. For most mono-lingual sites the most efficient setting is "First name + Surname", but you may choose to hide surnames altogether, or to leave it up to the current language pack to decide (some languages have different conventions).';
+$string['configfullnamedisplay'] = 'This defines how names are shown when they are displayed in full. For most mono-lingual sites the most efficient setting is "firstname lastname", but you may choose to hide surnames altogether, or to leave it up to the current language pack to decide (some languages have different conventions). Placeholders that can be used are: firstname, lastname, firstnamephonetic, lastnamephonetic, middlename, and alternatename.';
$string['configgeoipfile'] = 'Location of GeoIP City binary data file. This file is not part of Moodle distribution and must be obtained separately from <a href="http://www.maxmind.com/">MaxMind</a>. You can either buy a commercial version or use the free version.<br />Simply download <a href="http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz" >http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz</a> and extract it into "{$a}" directory on your server.';
$string['configgetremoteaddrconf'] = 'If your server is behind a reverse proxy, you can use this setting to specify which HTTP headers can be trusted to contain the remote IP address. The headers are read in order, using the first one that is available.';
$string['configgradebookroles'] = 'This setting allows you to control who appears on the gradebook. Users need to have at least one of these roles in a course to be shown in the gradebook for that course.';
$string['frontpageroles'] = 'Front page roles';
$string['frontpagesettings'] = 'Front page settings';
$string['fullnamedisplay'] = 'Full name format';
+$string['fullnamedisplayprivate'] = 'Full name format - private';
$string['gdrecommended'] = 'GD extension is used for conversion of images, some features such as user profile images will not be available if missing.';
$string['gdrequired'] = 'The GD extension is now required by Moodle for image conversion.';
$string['generalsettings'] = 'General settings';
$string['addinganew'] = 'Adding a new {$a}';
$string['addinganewto'] = 'Adding a new {$a->what} to {$a->to}';
$string['addingdatatoexisting'] = 'Adding data to existing';
+$string['additionalnames'] = 'Additional names';
$string['addlinkhere'] = 'Add link here';
$string['addnewcategory'] = 'Add new category';
$string['addnewcourse'] = 'Add a new course';
$string['allteachers'] = 'All teachers';
$string['alphanumerical'] = 'Can only contain alphanumeric characters, hyphen (-) or period (.)';
$string['alreadyconfirmed'] = 'Registration has already been confirmed';
+$string['alternatename'] = 'Alternate name';
$string['always'] = 'Always';
$string['and'] = '{$a->one} and {$a->two}';
$string['answer'] = 'Answer';
$string['findmorecourses'] = 'Find more courses...';
$string['firstaccess'] = 'First access';
$string['firstname'] = 'First name';
+$string['firstnamephonetic'] = 'First name - phonetic';
$string['firsttime'] = 'Is this your first time here?';
$string['folder'] = 'Folder';
$string['folderclosed'] = 'Closed folder';
$string['lastlogin'] = 'Last login';
$string['lastmodified'] = 'Last modified';
$string['lastname'] = 'Surname';
+$string['lastnamephonetic'] = 'Surname - phonetic';
$string['lastyear'] = 'Last year';
$string['latestlanguagepack'] = 'Check for latest language pack on moodle.org';
$string['layouttable'] = 'Layout table';
$string['messageprovider:instantmessage_help'] = 'This section configures what happens to messages that are sent to you directly from other users on this site.';
$string['messageselect'] = 'Select this user as a message recipient';
$string['messageselectadd'] = 'Send a message';
+$string['middlename'] = 'Middle name';
$string['migratinggrades'] = 'Migrating grades';
$string['min'] = 'min';
$string['mins'] = 'mins';
global $DB;
if (empty($fields)) {
- $fields = 'u.id, u.confirmed, u.username, u.firstname, u.lastname, '.
+ $allnames = get_all_user_name_fields(true, 'u');
+ $fields = 'u.id, u.confirmed, u.username, '. $allnames . ', ' .
'u.maildisplay, u.mailformat, u.maildigest, u.email, u.emailstop, u.city, '.
'u.country, u.picture, u.idnumber, u.department, u.institution, '.
'u.lang, u.timezone, u.lastaccess, u.mnethostid, r.name AS rolename, r.sortorder, '.
$fs = get_file_storage();
$fs->delete_area_files($this->_id);
+ // Delete all repository instances attached to this context.
+ require_once($CFG->dirroot . '/repository/lib.php');
+ repository::delete_all_for_context($this->_id);
+
// delete all advanced grading data attached to this context
require_once($CFG->dirroot.'/grade/grading/lib.php');
grading_manager::delete_all_for_context($this->_id);
try {
- // we ignore the strictness completely because system context must except except during install
+ // We ignore the strictness completely because system context must exist except during install.
$record = $DB->get_record('context', array('contextlevel'=>CONTEXT_SYSTEM), '*', MUST_EXIST);
} catch (dml_exception $e) {
//table or record does not exist
// before removing devs will be warned with a debugging message first,
// then we will add error message and only after that we can remove the functions
// completely.
-
-
-/**
- * Not available any more, use load_temp_course_role() instead.
- *
- * @deprecated since 2.2
- * @param stdClass $context
- * @param int $roleid
- * @param array $accessdata
- * @return array
- */
-function load_temp_role($context, $roleid, array $accessdata) {
- debugging('load_temp_role() is deprecated, please use load_temp_course_role() instead, temp role not loaded.');
- return $accessdata;
-}
-
-/**
- * Not available any more, use remove_temp_course_roles() instead.
- *
- * @deprecated since 2.2
- * @param stdClass $context
- * @param array $accessdata
- * @return array access data
- */
-function remove_temp_roles($context, array $accessdata) {
- debugging('remove_temp_role() is deprecated, please use remove_temp_course_roles() instead.');
- return $accessdata;
-}
-
-/**
- * Returns system context or null if can not be created yet.
- *
- * @deprecated since 2.2, use context_system::instance()
- * @param bool $cache use caching
- * @return context system context (null if context table not created yet)
- */
-function get_system_context($cache = true) {
- return context_system::instance(0, IGNORE_MISSING, $cache);
-}
-
-/**
- * Recursive function which, given a context, find all parent context ids,
- * and return the array in reverse order, i.e. parent first, then grand
- * parent, etc.
- *
- * @deprecated since 2.2, use $context->get_parent_context_ids() instead
- * @param context $context
- * @param bool $includeself optional, defaults to false
- * @return array
- */
-function get_parent_contexts(context $context, $includeself = false) {
- return $context->get_parent_context_ids($includeself);
-}
-
/**
* Return the id of the parent of this context, or false if there is no parent (only happens if this
* is the site context.)
// Calculate number of instances in order to display them for the Moodle administrator
if (!empty($instanceoptionnames)) {
$params = array();
- $params['context'] = array(get_system_context());
+ $params['context'] = array(context_system::instance());
$params['onlyvisible'] = false;
$params['type'] = $typename;
$admininstancenumber = count(repository::static_function($typename, 'get_instances', $params));
$assign = true;
}
if (!empty($assign)) {
- $systemcontext = get_system_context();
+ $systemcontext = context_system::instance();
assign_capability('webservice/xmlrpc:use', $permission, $CFG->defaultuserroleid, $systemcontext->id, true);
assign_capability('webservice/rest:use', $permission, $CFG->defaultuserroleid, $systemcontext->id, true);
}
$userfrom = new stdClass();
$userfrom->id = $admin->id;
$userfrom->email = !empty($CFG->badges_defaultissuercontact) ? $CFG->badges_defaultissuercontact : $admin->email;
+ foreach (get_all_user_name_fields() as $addname) {
+ $userfrom->$addname = !empty($CFG->badges_defaultissuername) ? '' : $admin->$addname;
+ }
$userfrom->firstname = !empty($CFG->badges_defaultissuername) ? $CFG->badges_defaultissuername : $admin->firstname;
- $userfrom->lastname = !empty($CFG->badges_defaultissuername) ? '' : $admin->lastname;
$userfrom->maildisplay = true;
$issuedlink = html_writer::link(new moodle_url('/badges/badge.php', array('hash' => $issued)), $badge->name);
$context = $this->page->context;
$contexttest = 'bi.parentcontextid = :contextid2';
$parentcontextparams = array();
- $parentcontextids = get_parent_contexts($context);
+ $parentcontextids = $context->get_parent_context_ids();
if ($parentcontextids) {
list($parentcontexttest, $parentcontextparams) =
$DB->get_in_or_equal($parentcontextids, SQL_PARAMS_NAMED, 'parentcontext');
@chmod($cachefile, $CFG->filepermissions);
}
@unlink($cachefile.'.tmp'); // Just in case anything fails (race condition).
+ self::invalidate_opcode_php_cache($cachefile);
}
}
}
return $return;
}
+
+ /**
+ * Invalidate opcode cache for given file, this is intended for
+ * php files that are stored in dataroot.
+ *
+ * Note: we need it here because this class must be self-contained.
+ *
+ * @param string $file
+ */
+ public static function invalidate_opcode_php_cache($file) {
+ if (function_exists('opcache_invalidate')) {
+ if (!file_exists($file)) {
+ return;
+ }
+ opcache_invalidate($file, true);
+ }
+ }
}
list($sql2, $params2) = $DB->get_in_or_equal($managerroles, SQL_PARAMS_NAMED, 'rid');
list($sort, $sortparams) = users_order_by_sql('u');
$notdeleted = array('notdeleted'=>0);
+ $allnames = get_all_user_name_fields(true, 'u');
$sql = "SELECT ra.contextid, ra.id AS raid,
r.id AS roleid, r.name AS rolename, r.shortname AS roleshortname,
- rn.name AS rolecoursealias, u.id, u.username, u.firstname, u.lastname
+ rn.name AS rolecoursealias, u.id, u.username, $allnames
FROM {role_assignments} ra
JOIN {user} u ON ra.userid = u.id
JOIN {role} r ON ra.roleid = r.id
$user = new stdClass();
$user->id = $ruser->id;
$user->username = $ruser->username;
- $user->firstname = $ruser->firstname;
- $user->lastname = $ruser->lastname;
+ foreach (get_all_user_name_fields() as $addname) {
+ $user->$addname = $ruser->$addname;
+ }
$role = new stdClass();
$role->id = $ruser->roleid;
$role->name = $ruser->rolename;
array('id', 'username', 'email', 'firstname', 'lastname', 'city', 'country',
'lastaccess', 'confirmed', 'mnethostid'));
}
+ $namefields = get_all_user_name_fields(true);
+ $extrafields = "$extrafields, $namefields";
// warning: will return UNCONFIRMED USERS
- return $DB->get_records_sql("SELECT id, username, email, firstname, lastname, city, country,
- lastaccess, confirmed, mnethostid, suspended $extrafields
+ return $DB->get_records_sql("SELECT id, username, email, city, country, lastaccess, confirmed, mnethostid, suspended $extrafields
FROM {user}
WHERE $select
$sort", $params, $page, $recordsperpage);
$select";
$totalcount = $DB->count_records_sql($sql, $params);
-
- $sql = "SELECT l.*, u.firstname, u.lastname, u.picture
+ $allnames = get_all_user_name_fields(true, 'u');
+ $sql = "SELECT l.*, $allnames, u.picture
FROM {log} l
LEFT JOIN {user} u ON l.userid = u.id
$select
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="trustbitmask" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="imagealt" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="alt tag for user uploaded image"/>
+ <FIELD NAME="lastnamephonetic" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="Last name phonetic"/>
+ <FIELD NAME="firstnamephonetic" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="First name phonetic"/>
+ <FIELD NAME="middlename" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="Middle name"/>
+ <FIELD NAME="alternatename" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="Alternate name - Useful for three-name countries."/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<INDEX NAME="email" UNIQUE="false" FIELDS="email"/>
<INDEX NAME="auth" UNIQUE="false" FIELDS="auth"/>
<INDEX NAME="idnumber" UNIQUE="false" FIELDS="idnumber"/>
+ <INDEX NAME="firstnamephonetic" UNIQUE="false" FIELDS="firstnamephonetic"/>
+ <INDEX NAME="lastnamephonetic" UNIQUE="false" FIELDS="lastnamephonetic"/>
+ <INDEX NAME="middlename" UNIQUE="false" FIELDS="middlename"/>
+ <INDEX NAME="alternatename" UNIQUE="false" FIELDS="alternatename"/>
</INDEXES>
</TABLE>
<TABLE NAME="user_preferences" COMMENT="Allows modules to store arbitrary user preferences">
upgrade_main_savepoint(true, 2013061700.00);
}
+ if ($oldversion < 2013070800.00) {
+
+ // Remove orphan repository instances.
+ if ($DB->get_dbfamily() === 'mysql') {
+ $sql = "DELETE {repository_instances} FROM {repository_instances}
+ LEFT JOIN {context} ON {context}.id = {repository_instances}.contextid
+ WHERE {context}.id IS NULL";
+ } else {
+ $sql = "DELETE FROM {repository_instances}
+ WHERE NOT EXISTS (
+ SELECT 'x' FROM {context}
+ WHERE {context}.id = {repository_instances}.contextid)";
+ }
+ $DB->execute($sql);
+
+ // Main savepoint reached.
+ upgrade_main_savepoint(true, 2013070800.00);
+ }
+
+ if ($oldversion < 2013070800.01) {
+
+ // Define field lastnamephonetic to be added to user.
+ $table = new xmldb_table('user');
+ $field = new xmldb_field('lastnamephonetic', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'imagealt');
+ $index = new xmldb_index('lastnamephonetic', XMLDB_INDEX_NOTUNIQUE, array('lastnamephonetic'));
+
+ // Conditionally launch add field lastnamephonetic.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ $dbman->add_index($table, $index);
+ }
+
+ // Define field firstnamephonetic to be added to user.
+ $table = new xmldb_table('user');
+ $field = new xmldb_field('firstnamephonetic', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'lastnamephonetic');
+ $index = new xmldb_index('firstnamephonetic', XMLDB_INDEX_NOTUNIQUE, array('firstnamephonetic'));
+
+ // Conditionally launch add field firstnamephonetic.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ $dbman->add_index($table, $index);
+ }
+
+ // Define field alternatename to be added to user.
+ $table = new xmldb_table('user');
+ $field = new xmldb_field('middlename', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'firstnamephonetic');
+ $index = new xmldb_index('middlename', XMLDB_INDEX_NOTUNIQUE, array('middlename'));
+
+ // Conditionally launch add field firstnamephonetic.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ $dbman->add_index($table, $index);
+ }
+
+ // Define field alternatename to be added to user.
+ $table = new xmldb_table('user');
+ $field = new xmldb_field('alternatename', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'middlename');
+ $index = new xmldb_index('alternatename', XMLDB_INDEX_NOTUNIQUE, array('alternatename'));
+
+ // Conditionally launch add field alternatename.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ $dbman->add_index($table, $index);
+ }
+
+ // Main savepoint reached.
+ upgrade_main_savepoint(true, 2013070800.01);
+ }
+
return true;
}
debugging('get_context_instance_by_id() is deprecated, please use context::instance_by_id($id) instead.', DEBUG_DEVELOPER);
return context::instance_by_id($id, $strictness);
}
+
+/**
+ * @deprecated since Moodle 2.2
+ * @see load_temp_course_role()
+ */
+function load_temp_role($context, $roleid, array $accessdata) {
+ throw new coding_exception('load_temp_role() can not be used any more, please use load_temp_course_role()');
+}
+
+/**
+ * @deprecated since Moodle 2.2
+ * @see remove_temp_course_roles()
+ */
+function remove_temp_roles($context, array $accessdata) {
+ throw new coding_exception('remove_temp_roles() can not be used any more, please use remove_temp_course_roles()');
+}
+
+/**
+ * Returns system context or null if can not be created yet.
+ *
+ * @see context_system::instance()
+ * @deprecated since 2.2
+ * @param bool $cache use caching
+ * @return context system context (null if context table not created yet)
+ */
+function get_system_context($cache = true) {
+ debugging('get_system_context() is deprecated, please use context_system::instance() instead.', DEBUG_DEVELOPER);
+ return context_system::instance(0, IGNORE_MISSING, $cache);
+}
+
+/**
+ * Recursive function which, given a context, find all parent context ids,
+ * and return the array in reverse order, i.e. parent first, then grand
+ * parent, etc.
+ *
+ * @see context::get_parent_context_ids()
+ * @deprecated since 2.2, use $context->get_parent_context_ids() instead
+ * @param context $context
+ * @param bool $includeself optional, defaults to false
+ * @return array
+ */
+function get_parent_contexts(context $context, $includeself = false) {
+ debugging('get_parent_contexts() is deprecated, please use $context->get_parent_context_ids() instead.', DEBUG_DEVELOPER);
+ return $context->get_parent_context_ids($includeself);
+}
+
+/**
+ * This function has been deprecated please use {@link message_get_providers_for_user()} instead.
+ * @deprecated since 2.1
+ */
+function message_get_my_providers() {
+ throw new coding_exception('message_get_my_providers() is deprecated please use message_get_providers_for_user()');
+}
$this->store_settings($dbhost, $dbuser, $dbpass, $dbname, $prefix, $dboptions);
$dbhost = $this->dbhost;
- if (isset($dboptions['dbport'])) {
+ // Zero shouldn't be used as a port number so doing a check with empty() should be fine.
+ if (!empty($dboptions['dbport'])) {
if (stristr(PHP_OS, 'win') && !stristr(PHP_OS, 'darwin')) {
$dbhost .= ','.$dboptions['dbport'];
} else {
// Put any upgrade step following this.
+ // Moodle v2.6.0 release upgrade line.
+ // Put any upgrade step following this.
+
+ if ($oldversion < 2013061400) {
+ // Reset redesigned editor toolbar setting.
+ $oldorder = "fontselect,fontsizeselect,formatselect,|,undo,redo,|,search,replace,|,fullscreen
+
+bold,italic,underline,strikethrough,sub,sup,|,justifyleft,justifycenter,justifyright,|,cleanup,removeformat,pastetext,pasteword,|,forecolor,backcolor,|,ltr,rtl
+
+bullist,numlist,outdent,indent,|,link,unlink,|,image,nonbreaking,charmap,table,|,code";
+
+ $neworder = "formatselect,bold,italic,|,bullist,numlist,|,link,unlink,|,image
+
+undo,redo,|,underline,strikethrough,sub,sup,|,justifyleft,justifycenter,justifyright,|,outdent,indent,|,forecolor,backcolor,|,ltr,rtl,|,nonbreaking,charmap,table
+
+fontselect,fontsizeselect,code,search,replace,|,cleanup,removeformat,pastetext,pasteword,|,fullscreen";
+ $currentorder = get_config('editor_tinymce', 'customtoolbar');
+ if ($currentorder == $oldorder) {
+ unset_config('customtoolbar', 'editor_tinymce');
+ set_config('customtoolbar', $neworder, 'editor_tinymce');
+ }
+ upgrade_plugin_savepoint(true, 2013061400, 'editor', 'tinymce');
+ }
+
+ if ($oldversion < 2013070500) {
+ // Insert wrap plugin to nicely wrap the toolbars on small screens.
+ $oldorder = "formatselect,bold,italic,|,bullist,numlist,|,link,unlink,|,image
+
+undo,redo,|,underline,strikethrough,sub,sup,|,justifyleft,justifycenter,justifyright,|,outdent,indent,|,forecolor,backcolor,|,ltr,rtl,|,nonbreaking,charmap,table
+
+fontselect,fontsizeselect,code,search,replace,|,cleanup,removeformat,pastetext,pasteword,|,fullscreen";
+
+ $neworder = "formatselect,bold,italic,wrap,bullist,numlist,|,link,unlink,|,image
+
+undo,redo,|,underline,strikethrough,sub,sup,|,justifyleft,justifycenter,justifyright,wrap,outdent,indent,|,forecolor,backcolor,|,ltr,rtl,|,nonbreaking,charmap,table
+
+fontselect,fontsizeselect,wrap,code,search,replace,|,cleanup,removeformat,pastetext,pasteword,|,fullscreen";
+ $currentorder = get_config('editor_tinymce', 'customtoolbar');
+ if ($currentorder == $oldorder) {
+ unset_config('customtoolbar', 'editor_tinymce');
+ set_config('customtoolbar', $neworder, 'editor_tinymce');
+ } else {
+ // Simple auto conversion algorithm.
+ $toolbars = explode("\n", $oldorder);
+ $newtoolbars = array();
+ foreach ($toolbars as $toolbar) {
+ $sepcount = substr_count($toolbar, '|');
+
+ if ($sepcount > 0) {
+ // We assume the middle separator (rounding down).
+ $divisionindex = round($sepcount / 2, 0, PHP_ROUND_HALF_DOWN);
+
+ $buttons = explode(',', $toolbar);
+ $index = 0;
+ foreach ($buttons as $key => $button) {
+ if ($button === "|") {
+ if ($index == $divisionindex) {
+ $buttons[$key] = 'wrap';
+ break;
+ } else {
+ $index += 1;
+ }
+ }
+ }
+ $toolbar = implode(',', $buttons);
+ }
+ array_push($newtoolbars, $toolbar);
+ }
+ $neworder = implode("\n", $newtoolbars);
+
+ // Set the new config.
+ unset_config('customtoolbar', 'editor_tinymce');
+ set_config('customtoolbar', $neworder, 'editor_tinymce');
+ }
+ upgrade_plugin_savepoint(true, 2013070500, 'editor', 'tinymce');
+ }
+
return true;
}
$string['customconfig'] = 'Custom configuration';
$string['customconfig_desc'] = 'Custom advanced TinyMCE configuration in JSON format, for example: {"option1" : "value2", "option2" : "value2"}. Any options specified here override standard and plugin settings.';
$string['customtoolbar'] = 'Editor toolbar';
-$string['customtoolbar_desc'] = 'Each line contains a list of comma separated button names, use "|" as a group separator, empty lines are ignored. See <a href="{$a}" target="_blank">{$a}</a> for the list of default TinyMCE buttons.';
+$string['customtoolbar_desc'] = 'Each line contains a list of comma separated button names, use "|" as a group separator, empty lines are ignored. See <a href="{$a}" target="_blank">{$a}</a> for the list of default TinyMCE buttons.<br />The first row will always be shown, where as the visibility of second and third toolbars can be toggled';
$string['fontselectlist'] = 'Available fonts list';
$string['pluginname'] = 'TinyMCE HTML editor';
$string['settings'] = 'General settings';
if (check_browser_version('Safari iOS', 534)) {
return true;
}
+ if (check_browser_version('WebKit', 534)) {
+ return true;
+ }
return false;
}
}
}
- // Add button after emoticon button in advancedbuttons3.
- $added = $this->add_button_after($params, 3, 'moodlemedia', 'moodleemoticon', false);
+ // Add button after emoticon button in advancedbuttons1.
+ $added = $this->add_button_after($params, 1, 'moodlemedia', 'moodleemoticon', false);
// Note: We know that the emoticon button has already been added, if it
// exists, because I set the sort order higher for this. So, if no
// emoticon, add after 'image'.
if (!$added) {
- $this->add_button_after($params, 3, 'moodlemedia', 'image');
+ $this->add_button_after($params, 1, 'moodlemedia', 'image');
}
// Add JS file, which uses default name.
protected function update_init_params(array &$params, context $context,
array $options = null) {
- // Add button after 'unlink' in advancedbuttons3.
- $this->add_button_after($params, 3, 'moodlenolink', 'unlink');
+ // Add button after 'unlink' in advancedbuttons1.
+ $this->add_button_after($params, 1, 'moodlenolink', 'unlink');
// Add JS file, which uses default name.
$this->add_js_plugin($params);
--- /dev/null
+<?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/>.
+
+/**
+ * Strings for 'Toolbar Toggle' plugin.
+ *
+ * @package tinymce_pdw
+ * @copyright 2013 Jason Fowler
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$string['pluginname'] = 'Toolbar Toggle';
+
+/* All lang strings used from TinyMCE JavaScript code must be named 'pluginname:stringname', no need to create langs/en_dlg.js */
+$string['pdw:desc'] = 'Toolbar Toggle';
--- /dev/null
+<?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();
+
+/**
+ * Plugin for Moodle 'Toolbar Toggle' button.
+ *
+ * @package tinymce_pdw
+ * @copyright 2013 Jason Fowler
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class tinymce_pdw extends editor_tinymce_plugin {
+ protected function update_init_params(array &$params, context $context,
+ array $options = null) {
+
+ // Add button before 'undo' in advancedbuttons1.
+ $this->add_button_before($params, 1, ' | ', '');
+ $this->add_button_before($params, 1, 'pdw_toggle', '');
+ $params['pdw_toggle_on'] = 1;
+ $params['pdw_toggle_toolbars'] = '2,3';
+
+ // Add JS file, which uses default name.
+ $this->add_js_plugin($params);
+ }
+}
--- /dev/null
+Description of PDW Toolbar Toggle integration in Moodle
+=========================================================================================
+
+Copyright: Guido Neele (www.neele.name)
+License: MIT
+
+Moodle maintainer: Jason Fowler (phalacee)
+
+=========================================================================================
+Upgrade procedure:
+1/ extract standard PDW package into lib/editor/tinymce/plugins/pdw/tinymce/
+2/ bump up version.php
+3/ update lib/thirdpartylibs.xml
+4/ reimplement patch in MDL-23646
+5/ reminify the js manually (I used uglifyjs)
--- /dev/null
+/**\r
+ * PDW Toggle Toolbars v1.2\r
+ * Url: http://www.neele.name\r
+ * Author: Guido Neele\r
+ * \r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ * of this software and associated documentation files (the "Software"), to deal\r
+ * in the Software without restriction, including without limitation the rights\r
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ * copies of the Software, and to permit persons to whom the Software is\r
+ * furnished to do so, subject to the following conditions:\r
+ * \r
+ * The above copyright notice and this permission notice shall be included in\r
+ * all copies or substantial portions of the Software.\r
+ * \r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+ * THE SOFTWARE.\r
+ * Based on TinyMCE Wordpress plugin (Kitchen Sink)\r
+ */\r
+!function(){var DOM=tinymce.DOM;tinymce.PluginManager.requireLangPack("pdw");tinymce.create("tinymce.plugins.pdw",{init:function(ed,url){var t=this,tbIds=new Array,toolbars=new Array,i;toolbars=ed.settings.pdw_toggle_toolbars.split(",");for(i=0;i<toolbars.length;i++){tbIds[i]=ed.getParam("","toolbar"+toolbars[i].replace(" ",""))}ed.addCommand("mcePDWToggleToolbars",function(){var cm=ed.controlManager,id,j,Cookie=tinymce.util.Cookie,Toggle_PDW,Toggle=Cookie.getHash("TinyMCE_toggle")||new Object;for(j=0;j<tbIds.length;j++){obj=ed.controlManager.get(tbIds[j]);if(typeof obj=="undefined"){continue}id=obj.id;if(DOM.isHidden(id)){Toggle_PDW=0;var e=document.getElementById(id);if(e){e.style.display="table";t._resizeIframe(ed,tbIds[j],-26)}}else{Toggle_PDW=1;var e=document.getElementById(id);if(e){e.style.display="none"}t._resizeIframe(ed,tbIds[j],26)}}cm.setActive("pdw_toggle",Toggle_PDW);ed.settings.pdw_toggle_on=Toggle_PDW;Toggle[ed.id]=Toggle_PDW;Cookie.setHash("TinyMCE_toggle",Toggle)});ed.addButton("pdw_toggle",{title:ed.getLang("pdw.desc",0),cmd:"mcePDWToggleToolbars",image:url+"/img/toolbars.gif"});ed.onPostRender.add(function(){var toggle=tinymce.util.Cookie.getHash("TinyMCE_toggle")||new Object;var run=false;if(toggle[ed.id]==null){run=ed.settings.pdw_toggle_on==1?true:false}else if(toggle[ed.id]==1){run=true}if(run){var cm=ed.controlManager,tdId,id;for(i=0;i<toolbars.length;i++){tbId=ed.getParam("","toolbar"+toolbars[i].replace(" ",""));id=ed.controlManager.get(tbId).id;cm.setActive("pdw_toggle",1);DOM.hide(id);t._resizeIframe(ed,tbId,26)}}})},_resizeIframe:function(ed,tb_id,dy){var ifr=ed.getContentAreaContainer().firstChild;DOM.setStyle(ifr,"height",DOM.getSize(ifr).h+dy);ed.theme.deltaHeight+=dy},getInfo:function(){return{longname:"PDW Toggle Toolbars",author:"Guido Neele",authorurl:"http://www.neele.name/",infourl:"http://www.neele.name/pdw_toggle_toolbars",version:"1.2"}}});tinymce.PluginManager.add("pdw",tinymce.plugins.pdw)}();
\ No newline at end of file
--- /dev/null
+/**\r
+ * PDW Toggle Toolbars v1.2\r
+ * Url: http://www.neele.name\r
+ * Author: Guido Neele\r
+ * \r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ * of this software and associated documentation files (the "Software"), to deal\r
+ * in the Software without restriction, including without limitation the rights\r
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ * copies of the Software, and to permit persons to whom the Software is\r
+ * furnished to do so, subject to the following conditions:\r
+ * \r
+ * The above copyright notice and this permission notice shall be included in\r
+ * all copies or substantial portions of the Software.\r
+ * \r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+ * THE SOFTWARE.\r
+ * Based on TinyMCE Wordpress plugin (Kitchen Sink)\r
+ * \r
+ * Changes V1.1.1 --> V1.2\r
+ * \r
+ * heeae made some modifications and posted his work on Sourceforge. I thought the cookie support \r
+ * was really handy so I updated the script.\r
+ * http://sourceforge.net/tracker/?func=detail&atid=738747&aid=2904683&group_id=103281\r
+ *\r
+ * 1. Added cookie support.\r
+ * 2. Some optimization\r
+ * 3. Bug fix of fire ifr.clientHeight in FF 3 ( to DOM.getStyles)\r
+ *\r
+ * Thanks heeae!\r
+ * \r
+ * Changes V1.1 --> V1.1.1\r
+ *\r
+ * Bugfix for Firefox 3.6. Caused error while loading script.\r
+ *\r
+ * Added lines 72 - 76:\r
+ *\r
+ * obj = ed.controlManager.get(tbIds[j]);\r
+ * if(typeof obj =="undefined") {\r
+ * continue;\r
+ * }\r
+ * id = obj.id;\r
+ *\r
+ * instead of:\r
+ *\r
+ * try {\r
+ * id = ed.controlManager.get(tbIds[j]).id;\r
+ * }\r
+ * catch(e) {\r
+ * //if(typeof id == "undefined") continue;\r
+ * continue;\r
+ * }\r
+ *\r
+ * Thanks Anton for fixing this bug\r
+ * \r
+ */\r
+\r
+(function() {\r
+ var DOM = tinymce.DOM;\r
+ tinymce.PluginManager.requireLangPack('pdw');\r
+ \r
+ tinymce.create('tinymce.plugins.pdw', {\r
+ /**\r
+ * Initializes the plugin, this will be executed after the plugin has been created.\r
+ * This call is done before the editor instance has finished it's initialization so use the onInit event\r
+ * of the editor instance to intercept that event.\r
+ *\r
+ * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.\r
+ * @param {string} url Absolute URL to where the plugin is located.\r
+ */\r
+ init : function(ed, url) {\r
+ var t = this, tbIds = new Array(), toolbars = new Array(), i;\r
+ \r
+ // Split toolbars\r
+ toolbars = (ed.settings.pdw_toggle_toolbars).split(',');\r
+ \r
+ for(i = 0; i < toolbars.length; i++){\r
+ tbIds[i] = ed.getParam('', 'toolbar' + (toolbars[i]).replace(' ',''));\r
+ }\r
+ \r
+ // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample');\r
+ ed.addCommand('mcePDWToggleToolbars', function() {\r
+ \r
+ var cm = ed.controlManager, id, j, Cookie = tinymce.util.Cookie, Toggle_PDW, Toggle = Cookie.getHash("TinyMCE_toggle") || new Object();\r
+ for(j = 0; j < tbIds.length; j++){\r
+ \r
+ obj = ed.controlManager.get(tbIds[j]);\r
+ if(typeof obj =="undefined") {\r
+ continue;\r
+ }\r
+ id = obj.id;\r
+ \r
+ if (DOM.isHidden(id)) {\r
+ Toggle_PDW = 0;\r
+ var e = document.getElementById(id);\r
+ if (e) {\r
+ e.style.display = 'table';\r
+ t._resizeIframe(ed, tbIds[j], -26);\r
+ }\r
+ \r
+ } else {\r
+ Toggle_PDW = 1;\r
+ var e = document.getElementById(id);\r
+ if (e) {\r
+ e.style.display = 'none';\r
+ }\r
+ t._resizeIframe(ed, tbIds[j], 26);\r
+ }\r
+ }\r
+ cm.setActive('pdw_toggle', Toggle_PDW);\r
+ ed.settings.pdw_toggle_on = Toggle_PDW;\r
+ Toggle[ed.id] = Toggle_PDW;\r
+ Cookie.setHash("TinyMCE_toggle", Toggle);\r
+ });\r
+ \r
+ // Register pdw_toggle button\r
+ ed.addButton('pdw_toggle', {\r
+ title : ed.getLang('pdw.desc', 0),\r
+ cmd : 'mcePDWToggleToolbars',\r
+ image : url + '/img/toolbars.gif'\r
+ });\r
+ \r
+ ed.onPostRender.add(function(){\r
+ var toggle = tinymce.util.Cookie.getHash("TinyMCE_toggle") || new Object();\r
+ var run = false;\r
+ \r
+ // Check if value is stored in cookie\r
+ if(toggle[ed.id] == null){\r
+ // No cookie so check if the setting pdw_toggle_on is set to 1 then hide toolbars and set button active\r
+ run = ed.settings.pdw_toggle_on == 1 ? true : false;\r
+ } else if(toggle[ed.id] == 1){\r
+ run = true;\r
+ }\r
+ \r
+ if (run) {\r
+\r
+ var cm = ed.controlManager, tdId, id;\r
+ \r
+ for(i = 0; i < toolbars.length; i++){\r
+ tbId = ed.getParam('', 'toolbar' + (toolbars[i]).replace(' ',''));\r
+ id = ed.controlManager.get(tbId).id;\r
+ cm.setActive('pdw_toggle', 1);\r
+ DOM.hide(id);\r
+ t._resizeIframe(ed, tbId, 26);\r
+ }\r
+ }\r
+ });\r
+ },\r
+ \r
+ // Resizes the iframe by a relative height value\r
+ _resizeIframe : function(ed, tb_id, dy) {\r
+ var ifr = ed.getContentAreaContainer().firstChild;\r
+ \r
+ DOM.setStyle(ifr, 'height',DOM.getSize(ifr).h + dy); // Resize iframe\r
+ ed.theme.deltaHeight += dy; // For resize cookie\r
+ },\r
+\r
+ /**\r
+ * Returns information about the plugin as a name/value array.\r
+ * The current keys are longname, author, authorurl, infourl and version.\r
+ *\r
+ * @return {Object} Name/value array containing information about the plugin.\r
+ */\r
+ getInfo : function() {\r
+ return {\r
+ longname : 'PDW Toggle Toolbars',\r
+ author : 'Guido Neele',\r
+ authorurl : 'http://www.neele.name/',\r
+ infourl : 'http://www.neele.name/pdw_toggle_toolbars',\r
+ version : "1.2"\r
+ };\r
+ }\r
+ });\r
+\r
+ // Register plugin\r
+ tinymce.PluginManager.add('pdw', tinymce.plugins.pdw);\r
+})();\r
--- /dev/null
+tinyMCE.addI18n('en.pdw',{\r
+ desc : 'Show/hide toolbars'\r
+});\r
--- /dev/null
+tinyMCE.addI18n('nl.pdw',{\r
+ desc : 'Toon/verberg werkbalken'\r
+});\r
--- /dev/null
+<?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/>.
+
+/**
+ * TinyMCE image insert/edit plugin version details.
+ *
+ * @package tinymce_pdw
+ * @copyright 2013 Jason Fowler
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+// The current plugin version (Date: YYYYMMDDXX).
+$plugin->version = 2013070500;
+// Required Moodle version.
+$plugin->requires = 2013050100;
+// Full name of the plugin (used for diagnostics).
+$plugin->component = 'tinymce_pdw';
--- /dev/null
+<?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/>.
+
+/**
+ * Strings for 'wrap' plugin.
+ *
+ * @package tinymce_wrap
+ * @copyright 2013 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$string['pluginname'] = 'Wrap';
+
+/* All lang strings used from TinyMCE JavaScript code must be named 'pluginname:stringname', no need to create langs/en_dlg.js */
+$string['moodlewrap:desc'] = 'Wrap';
--- /dev/null
+<?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();
+
+/**
+ * Plugin for Moodle 'wrap' button.
+ *
+ * @package tinymce_wrap
+ * @copyright 2013 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class tinymce_wrap extends editor_tinymce_plugin {
+ /** @var array list of buttons defined by this plugin */
+ protected $buttons = array('wrap');
+
+ protected function update_init_params(array &$params, context $context,
+ array $options = null) {
+
+ // Add JS file, which uses default name.
+ $this->add_js_plugin($params);
+ }
+}
--- /dev/null
+// 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 for Moodle 'wrap' button.
+ *
+ * @package tinymce_wrap
+ * @copyright 2013 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+(function() {
+ tinymce.create('tinymce.ui.Wrap:tinymce.ui.Control', {
+ /**
+ * Constructor for the tinymce.Wrap class.
+ */
+ Wrap : function(id, s) {
+ this.parent(id, s);
+ this.groupEndClass = 'mceToolbarEnd';
+ this.groupStartClass = 'mceToolbarStart';
+ this.wrapClass = 'mceWrap';
+ this.setDisabled(true);
+ },
+
+ /**
+ * Returns the HTML for this control. This control actually ends the current td
+ * container and opens a new one so that the containers can be styled with CSS
+ * to wrap at certain screen widths.
+ * @return string HTML
+ */
+ renderHTML : function() {
+ var separator = tinymce.DOM.createHTML('span', {role : 'separator',
+ 'aria-orientation' : 'vertical',
+ tabindex : '-1'});
+ return '</td>' +
+ '<td style="position: relative" class="' + this.groupEndClass + '">' + separator + '</td>' +
+ '<td style="position: relative" class="' + this.groupStartClass + ' ' + this.wrapClass + '">' + separator + '</td>';
+ }
+
+
+ });
+
+ tinymce.create('tinymce.plugins.wrapPlugin', {
+ /**
+ * Returns a new instance of this control, in this case a custom Wrap class.
+ *
+ * @param string name - The name of the control to create. Return false if we can't create this control type.
+ * @param tinymce.ControlManager cc - Tinymce control manager class.
+ * @return mixed - false or the new control
+ */
+ createControl : function(name, cc) {
+ if (name === "wrap") {
+ return new tinymce.ui.Wrap();
+ }
+ return false;
+ },
+
+ /**
+ * Returns information about the plugin as a name/value array.
+ * The current keys are longname, author, authorurl, infourl and version.
+ *
+ * @return {Object} Name/value array containing information about the plugin.
+ */
+ getInfo : function() {
+ return {
+ longname : 'wrap plugin',
+ author : 'Damyon Wiese',
+ authorurl : 'http://moodle.com/hq',
+ infourl : 'http://docs.moodle.org/en/TinyMCE',
+ version : "1.0"
+ };
+ }
+ });
+
+ // Register plugin.
+ tinymce.PluginManager.add('wrap', tinymce.plugins.wrapPlugin);
+})();
--- /dev/null
+<?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/>.
+
+/**
+ * TinyMCE toolbar wrapping break
+ *
+ * @package tinymce_wrap
+ * @copyright 2013 Damyon Wiese
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+// The current plugin version (Date: YYYYMMDDXX).
+$plugin->version = 2013061900;
+// Required Moodle version.
+$plugin->requires = 2013050100;
+// Full name of the plugin (used for diagnostics).
+$plugin->component = 'tinymce_wrap';
require_once(__DIR__.'/adminlib.php');
$settings->add(new tiynce_subplugins_settings());
$settings->add(new admin_setting_heading('tinymcegeneralheader', new lang_string('settings'), ''));
- $default = "fontselect,fontsizeselect,formatselect,|,undo,redo,|,search,replace,|,fullscreen
+ $default = "formatselect,bold,italic,wrap,bullist,numlist,|,link,unlink,|,image
-bold,italic,underline,strikethrough,sub,sup,|,justifyleft,justifycenter,justifyright,|,cleanup,removeformat,pastetext,pasteword,|,forecolor,backcolor,|,ltr,rtl
+undo,redo,|,underline,strikethrough,sub,sup,|,justifyleft,justifycenter,justifyright,wrap,outdent,indent,|,forecolor,backcolor,|,ltr,rtl,|,nonbreaking,charmap,table
-bullist,numlist,outdent,indent,|,link,unlink,|,image,nonbreaking,charmap,table,|,code";
+fontselect,fontsizeselect,wrap,code,search,replace,|,cleanup,removeformat,pastetext,pasteword,|,fullscreen";
$settings->add(new admin_setting_configtextarea('editor_tinymce/customtoolbar',
get_string('customtoolbar', 'editor_tinymce'), get_string('customtoolbar_desc', 'editor_tinymce', 'http://www.tinymce.com/wiki.php/Buttons/controls'), $default, PARAM_RAW, 100, 8));
$settings->add(new admin_setting_configtextarea('editor_tinymce/fontselectlist',
color: red;
cursor: pointer;
}
-.mform .felement.feditor .mceStatusbar,
-.mform .felement.feditor iframe {
- min-width: 35em;
+
+@media (max-width: 480px) {
+ .mceToolbar td {
+ float: left;
+ display: inline-block;
+ }
+ .mceToolbar .mceWrap {
+ clear: left;
+ }
+
+ .o2k7Skin tr.mceLast .mceToolbar tr td.mceWrap,
+ .o2k7Skin tr.mceFirst .mceToolbar tr td.mceWrap {
+ margin-left: -3px;
+ }
+ .dir-rtl .o2k7Skin tr.mceLast .mceToolbar tr td.mceWrap,
+ .dir-rtl .o2k7Skin tr.mceFirst .mceToolbar tr td.mceWrap {
+ margin-left: 0px;
+ }
}
information provided here is intended especially for developers.
+=== 2.6 ===
+
+* added a new plugin to toggle the 2nd and 3rd toolbars
+* added a new plugin to wrap the toolbars on small screens.
+This plugin will be automatically added to existing toolbars by replacing the middle occurrence of | with "wrap".
+
=== 2.5 ===
* update filter related code to use short filter names instead
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2013050100; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version = 2013070500; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2013050100; // Requires this Moodle version
$plugin->component = 'editor_tinymce'; // Full name of the plugin (used for diagnostics)
$plugin->release = '3.5.8'; // This is NOT a directory name, see lib.php if you need to know where is the editor code!
} else if ($rcontext->contextlevel > $context->contextlevel) {
throw new restricted_context_exception();
} else {
- $parents = get_parent_contexts($context);
+ $parents = $context->get_parent_context_ids();
if (!in_array($rcontext->id, $parents)) {
throw new restricted_context_exception();
}
}
}
}
+
+ /**
+ * Used by tests to simulate submitted form data submission from the user.
+ *
+ * For form fields where no data is submitted the default for that field as set by set_data or setDefault will be passed to
+ * get_data.
+ *
+ * This method sets $_POST or $_GET and $_FILES with the data supplied. Our unit test code empties all these
+ * global arrays after each test.
+ *
+ * @param array $simulatedsubmitteddata An associative array of form values (same format as $_POST).
+ * @param array $simulatedsubmittedfiles An associative array of files uploaded (same format as $_FILES). Can be omitted.
+ * @param string $method 'post' or 'get', defaults to 'post'.
+ * @param null $formidentifier the default is to use the class name for this class but you may need to provide
+ * a different value here for some forms that are used more than once on the
+ * same page.
+ */
+ public static function mock_submit($simulatedsubmitteddata, $simulatedsubmittedfiles = array(), $method = 'post',
+ $formidentifier = null) {
+ $_FILES = $simulatedsubmittedfiles;
+ if ($formidentifier === null) {
+ $formidentifier = get_called_class();
+ }
+ $simulatedsubmitteddata['_qf__'.$formidentifier] = 1;
+ $simulatedsubmitteddata['sesskey'] = sesskey();
+ if (strtolower($method) === 'get') {
+ $_GET = $simulatedsubmitteddata;
+ } else {
+ $_POST = $simulatedsubmitteddata;
+ }
+ }
}
/**
$letters = array();
- $contexts = get_parent_contexts($context);
+ $contexts = $context->get_parent_context_ids();
array_unshift($contexts, $context->id);
foreach ($contexts as $ctxid) {
}
}
-/**
- * This function has been deprecated please use {@link message_get_providers_for_user()} instead.
- *
- * Returns the active providers for the current user, based on capability
- *
- * @see message_get_providers_for_user()
- * @deprecated since 2.1
- * @todo Remove in 2.5 (MDL-34454)
- * @return array An array of message providers
- */
-function message_get_my_providers() {
- global $USER;
- debugging('message_get_my_providers is deprecated please update your code', DEBUG_DEVELOPER);
- return message_get_providers_for_user($USER->id);
-}
-
/**
* Returns the active providers for the user specified, based on capability
*
// Load sectioncache field into memory as PHP object and check it's valid
$sectioncache = unserialize($course->sectioncache);
- if (!is_array($sectioncache) || empty($sectioncache)) {
+ if (!is_array($sectioncache)) {
// hmm, something is wrong - let's fix it
rebuild_course_cache($course->id);
$course->sectioncache = $DB->get_field('course', 'sectioncache', array('id'=>$course->id));
/**
* Returns a persons full name
*
- * Given an object containing firstname and lastname
+ * Given an object containing all of the users name
* values, this function returns a string with the
* full name of the person.
* The result may depend on system settings
*
* @global object
* @global object
- * @param object $user A {@link $USER} object to get full name of
+ * @param object $user A {@link $USER} object to get full name of.
* @param bool $override If true then the name will be first name followed by last name rather than adhering to fullnamedisplay setting.
* @return string
*/
$CFG->fullnamedisplay = $SESSION->fullnamedisplay;
}
- if (!isset($CFG->fullnamedisplay) or $CFG->fullnamedisplay === 'firstname lastname') {
- return $user->firstname .' '. $user->lastname;
+ $template = null;
+ // If the fullnamedisplay setting is available, set the template to that.
+ if (isset($CFG->fullnamedisplay)) {
+ $template = $CFG->fullnamedisplay;
+ }
+ // If the template is empty, or set to language, or $override is set, return the language string.
+ if (empty($template) || $template == 'language' || $override) {
+ return get_string('fullnamedisplay', null, $user);
+ }
- } else if ($CFG->fullnamedisplay == 'lastname firstname') {
- return $user->lastname .' '. $user->firstname;
+ // Get all of the name fields.
+ $allnames = get_all_user_name_fields();
+ $requirednames = array();
+ // With each name, see if it is in the display name template, and add it to the required names array if it is.
+ foreach ($allnames as $allname) {
+ if (strpos($template, $allname) !== false) {
+ $requirednames[] = $allname;
+ // If the field is in the template, but not set in the user object, then notify the programmer that it needs to be fixed.
+ if (!array_key_exists($allname, $user)) {
+ debugging('You need to update your sql query to include additional name fields in the user object.', DEBUG_DEVELOPER);
+ }
+ }
+ }
- } else if ($CFG->fullnamedisplay == 'firstname') {
- if ($override) {
- return get_string('fullnamedisplay', '', $user);
+ $displayname = $template;
+ // Switch in the actual data into the template.
+ foreach ($requirednames as $altname) {
+ if (isset($user->$altname)) {
+ // Using empty() on the below if statement causes breakages.
+ if ((string)$user->$altname == '') {
+ $displayname = str_replace($altname, 'EMPTY', $displayname);
+ } else {
+ $displayname = str_replace($altname, $user->$altname, $displayname);
+ }
} else {
- return $user->firstname;
+ $displayname = str_replace($altname, 'EMPTY', $displayname);
+ }
+ }
+ // Tidy up any misc. characters (Not perfect, but gets most characters).
+ // Don't remove the "u" at the end of the first expression unless you want garbled characters when combining hiragana or katakana and parenthesis.
+ $patterns = array();
+ // This regular expression replacement is to fix problems such as 'James () Kirk' Where 'Tiberius' (middlename) has not been filled in by a user.
+ // The special characters are Japanese brackets that are common enough to make special allowance for them (not covered by :punct:).
+ $patterns[] = '/[[:punct:]ćć]*EMPTY[[:punct:]ćć]*/u';
+ // This regular expression is to remove any double spaces in the display name.
+ $patterns[] = '/\s{2,}/';
+ foreach ($patterns as $pattern) {
+ $displayname = preg_replace($pattern, ' ', $displayname);
+ }
+
+ // Trimming $displayname will help the next check to ensure that we don't have a display name with spaces.
+ $displayname = trim($displayname);
+ if (empty($displayname)) {
+ // Going with just the first name if no alternate fields are filled out. May be changed later depending on what
+ // people in general feel is a good setting to fall back on.
+ $displayname = $user->firstname;
+ }
+ return $displayname;
+}
+
+/**
+ * A centralised location for the all name fields. Returns an array / sql string snippet.
+ *
+ * @param bool $returnsql True for an sql select field snippet.
+ * @param string $alias table alias to use in front of each field.
+ * @return array|string All name fields.
+ */
+function get_all_user_name_fields($returnsql = false, $alias = null) {
+ $alternatenames = array('firstnamephonetic',
+ 'lastnamephonetic',
+ 'middlename',
+ 'alternatename',
+ 'firstname',
+ 'lastname',);
+ if ($returnsql) {
+ if ($alias) {
+ foreach ($alternatenames as $key => $altname) {
+ $alternatenames[$key] = "$alias.$altname";
+ }
}
+ $alternatenames = implode(',', $alternatenames);
}
+ return $alternatenames;
+}
- return get_string('fullnamedisplay', '', $user);
+/**
+ * Returns an array of values in order of occurance in a provided string.
+ * The key in the result is the character postion in the string.
+ *
+ * @param array $values Values to be found in the string format
+ * @param string $stringformat The string which may contain values being searched for.
+ * @return array An array of values in order according to placement in the string format.
+ */
+function order_in_string($values, $stringformat) {
+ $valuearray = array();
+ foreach ($values as $value) {
+ $pattern = "/$value\b/";
+ // Using preg_match as strpos() may match values that are similar e.g. firstname and firstnamephonetic.
+ if (preg_match($pattern, $stringformat)) {
+ $replacement = "thing";
+ // replace the value with something more unique to ensure we get the right position when using strpos().
+ $newformat = preg_replace($pattern, $replacement, $stringformat);
+ $position = strpos($newformat, $replacement);
+ $valuearray[$position] = $value;
+ }
+ }
+ ksort($valuearray);
+ return $valuearray;
}
/**
// and re-populate it again
fulldelete($this->menucache);
$this->get_list_of_translations(true);
+
+ // Lang packs use PHP files in dataroot, it is better to invalidate opcode caches.
+ if (function_exists('opcache_reset')) {
+ opcache_reset();
+ }
}
/**
$categoryname = format_string($category->name, true, array('context' => $context));
$categorynode = $parent->add($categoryname, $url, $nodetype, $categoryname, $category->id);
if (empty($category->visible)) {
- if (has_capability('moodle/category:viewhiddencategories', get_system_context())) {
+ if (has_capability('moodle/category:viewhiddencategories', context_system::instance())) {
$categorynode->hidden = true;
} else {
$categorynode->display = false;
$coursenode->add('frontpageloaded', null, self::TYPE_CUSTOM, null, 'frontpageloaded')->display = false;
//Participants
- if (has_capability('moodle/course:viewparticipants', get_system_context())) {
+ if (has_capability('moodle/course:viewparticipants', context_system::instance())) {
$coursenode->add(get_string('participants'), new moodle_url('/user/index.php?id='.$course->id), self::TYPE_CUSTOM, get_string('participants'), 'participants');
}
}
$coursecontext = context_course::instance($course->id); // Course context
- $systemcontext = get_system_context();
+ $systemcontext = context_system::instance();
$currentuser = ($USER->id == $userid);
if ($currentuser) {
$enablemanagetokens = true;
} else if (!is_siteadmin($USER->id)
&& !empty($CFG->enablewebservices)
- && has_capability('moodle/webservice:createtoken', get_system_context()) ) {
+ && has_capability('moodle/webservice:createtoken', context_system::instance()) ) {
$enablemanagetokens = true;
}
// Security keys
* @var array List of mandatory fields in user record here. (do not include
* TEXT columns because it would break SELECT DISTINCT in MSSQL and ORACLE)
*/
- protected static $fields = array('id', 'picture', 'firstname', 'lastname', 'imagealt', 'email');
+ protected static $fields = array('id', 'picture', 'firstname', 'lastname', 'firstnamephonetic', 'lastnamephonetic',
+ 'middlename', 'alternatename', 'imagealt', 'email');
/**
* @var stdClass A user object with at least fields all columns specified
if ($tableprefix) {
$tableprefix .= '.';
}
- $fields = array();
foreach (self::$fields as $field) {
if ($field === 'id' and $idalias and $idalias !== 'id') {
$fields[$field] = "$tableprefix$field AS $idalias";
ini_set('display_errors', '1');
ini_set('log_errors', '1');
+// Make sure OPcache does not strip comments, we need them in phpunit!
+if (ini_get('opcache.enable') and strtolower(ini_get('opcache.enable')) !== 'off') {
+ if (!ini_get('opcache.save_comments') or strtolower(ini_get('opcache.save_comments')) === 'off') {
+ ini_set('opcache.enable', 0);
+ } else {
+ ini_set('opcache.load_comments', 1);
+ }
+}
+
require_once(__DIR__.'/bootstraplib.php');
require_once(__DIR__.'/../testing/lib.php');
require_once(__DIR__.'/classes/autoloader.php');
);
}
- return $class;
+ $classname = reset($candidates);
+ return new ReflectionClass($classname);
}
public function reload(ReflectionClass $aClass) {
$_SERVER = self::get_global_backup('_SERVER');
$CFG = self::get_global_backup('CFG');
$SITE = self::get_global_backup('SITE');
+ $_GET = array();
+ $_POST = array();
+ $_FILES = array();
+ $_REQUEST = array();
$COURSE = $SITE;
// reinitialise following globals
$this->assertTrue(isset($CFG->admin));
$this->assertEquals(1, $CFG->rolesactive);
+ // _GET change.
+ $_GET['__somethingthatwillnotnormallybepresent__'] = 'yy';
+ phpunit_util::reset_all_data(true);
+
+ $this->assertEquals(array(), $_GET);
+
+
+ // _POST change.
+ $_POST['__somethingthatwillnotnormallybepresent2__'] = 'yy';
+ phpunit_util::reset_all_data(true);
+ $this->assertEquals(array(), $_POST);
+
+ // _FILES change.
+ $_FILES['__somethingthatwillnotnormallybepresent3__'] = 'yy';
+ phpunit_util::reset_all_data(true);
+ $this->assertEquals(array(), $_FILES);
+
+ // _REQUEST change.
+ $_REQUEST['__somethingthatwillnotnormallybepresent4__'] = 'yy';
+ phpunit_util::reset_all_data(true);
+ $this->assertEquals(array(), $_REQUEST);
+
//silent changes
$_SERVER['xx'] = 'yy';
phpunit_util::reset_all_data(true);
$CFG->yui2version = '2.9.0';
$CFG->yui3version = '3.9.1';
+if (!defined('MOODLE_INTERNAL')) { // Necessary because cli installer has to define it earlier.
+ /** Used by library scripts to check they are being called by Moodle. */
+ define('MOODLE_INTERNAL', true);
+}
+
// core_component can be used in any scripts, it does not need anything else.
require_once($CFG->libdir .'/classes/component.php');
}
}
-/** Used by library scripts to check they are being called by Moodle */
-if (!defined('MOODLE_INTERNAL')) { // necessary because cli installer has to define it earlier
- define('MOODLE_INTERNAL', true);
-}
-
// Early profiling start, based exclusively on config.php $CFG settings
if (!empty($CFG->earlyprofilingenabled)) {
require_once($CFG->libdir . '/xhprof/xhprof_moodle.php');
// define SYSCONTEXTID in config.php if you want to save some queries,
// after install it must match the system context record id.
if (!defined('SYSCONTEXTID')) {
- get_system_context();
+ context_system::instance();
}
// Defining the site - aka frontpage course
switch ($column) {
case 'fullname':
- if ($this->is_sortable($column)) {
- $firstnamesortlink = $this->sort_link(get_string('firstname'),
- 'firstname', $primary_sort_column === 'firstname', $primary_sort_order);
-
- $lastnamesortlink = $this->sort_link(get_string('lastname'),
- 'lastname', $primary_sort_column === 'lastname', $primary_sort_order);
-
- $override = new stdClass();
- $override->firstname = 'firstname';
- $override->lastname = 'lastname';
- $fullnamelanguage = get_string('fullnamedisplay', '', $override);
-
- if (($CFG->fullnamedisplay == 'firstname lastname') or
- ($CFG->fullnamedisplay == 'firstname') or
- ($CFG->fullnamedisplay == 'language' and $fullnamelanguage == 'firstname lastname' )) {
- $this->headers[$index] = $firstnamesortlink . ' / ' . $lastnamesortlink;
- } else {
- $this->headers[$index] = $lastnamesortlink . ' / ' . $firstnamesortlink;
+ // Check the full name display for sortable fields.
+ $nameformat = $CFG->fullnamedisplay;
+ if ($nameformat == 'language') {
+ $nameformat = get_string('fullnamedisplay');
+ }
+ $requirednames = order_in_string(array('firstname', 'lastname'), $nameformat);
+
+ if (!empty($requirednames)) {
+ if ($this->is_sortable($column)) {
+ // Done this way for the possibility of more than two sortable full name display fields.
+ $this->headers[$index] = '';
+ foreach ($requirednames as $name) {
+ $sortname = $this->sort_link(get_string($name),
+ $name, $primary_sort_column === $name, $primary_sort_order);
+ $this->headers[$index] .= $sortname . ' / ';
+ }
+ $this->headers[$index] = substr($this->headers[$index], 0, -3);
}
}
break;
$record['lastname'] = 'Lastname'.$i;
}
+ if (!isset($record['firstnamephonetic'])) {
+ $firstnamephonetic = rand(0, 59);
+ $record['firstnamephonetic'] = $this->firstnames[$firstnamephonetic];
+ }
+
+ if (!isset($record['lasttnamephonetic'])) {
+ $lastnamephonetic = rand(0, 59);
+ $record['lastnamephonetic'] = $this->lastnames[$lastnamephonetic];
+ }
+
+ if (!isset($record['middlename'])) {
+ $middlename = rand(0, 59);
+ $record['middlename'] = $this->firstnames[$middlename];
+ }
+
+ if (!isset($record['alternatename'])) {
+ $alternatename = rand(0, 59);
+ $record['alternatename'] = $this->firstnames[$alternatename];
+ }
+
if (!isset($record['idnumber'])) {
$record['idnumber'] = '';
}
foreach ($DB->get_records('context') as $contextid=>$record) {
$context = context::instance_by_id($contextid);
- $this->assertSame(context::instance_by_id($contextid, IGNORE_MISSING), $context);
+ $this->assertSame(get_context_instance_by_id($contextid, IGNORE_MISSING), $context);
$this->assertSame(get_context_instance($record->contextlevel, $record->instanceid), $context);
$this->assertSame(get_parent_contexts($context), $context->get_parent_context_ids());
if ($context->id == SYSCONTEXTID) {
$this->assertDebuggingCalled('get_context_instance() is deprecated, please use context_xxxx::instance() instead.', DEBUG_DEVELOPER);
get_context_instance_by_id($record->id);
$this->assertDebuggingCalled('get_context_instance_by_id() is deprecated, please use context::instance_by_id($id) instead.', DEBUG_DEVELOPER);
+ get_system_context();
+ $this->assertDebuggingCalled('get_system_context() is deprecated, please use context_system::instance() instead.', DEBUG_DEVELOPER);
+ get_parent_contexts($context);
+ $this->assertDebuggingCalled('get_parent_contexts() is deprecated, please use $context->get_parent_context_ids() instead.', DEBUG_DEVELOPER);
$DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
create_contexts();
use Behat\Mink\Exception\ExpectationException as ExpectationException,
Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException,
- Behat\Mink\Exception\DriverException as DriverException;
+ Behat\Mink\Exception\DriverException as DriverException,
+ WebDriver\Exception\NoSuchElement as NoSuchElement;
/**
* Cross component steps definitions.
return false;
}
- $content = $metarefresh->getAttribute('content');
+ // Wrapped in try & catch in case the redirection has already been executed.
+ try {
+ $content = $metarefresh->getAttribute('content');
+ } catch (NoSuchElement $e) {
+ return false;
+ }
+
+ // Getting the refresh time and the url if present.
if (strstr($content, 'url') != false) {
- list($waittime, $url) = explode(';', $metarefresh->getAttribute('content'));
+ list($waittime, $url) = explode(';', $content);
// Cleaning the URL value.
$url = trim(substr($url, strpos($url, 'http')));
$this->assertEquals(convert_to_array($obj), (array)$obj);
// check that context object (with iterator) is converted to array properly
- $obj = get_system_context();
+ $obj = context_system::instance();
$ar = array(
'id' => $obj->id,
'contextlevel' => $obj->contextlevel,
$this->assertFalse(password_is_legacy_hash($user->password));
}
}
+
+ public function test_fullname() {
+ global $CFG;
+
+ $this->resetAfterTest();
+
+ // Create a user to test the name display on.
+ $record = array();
+ $record['firstname'] = 'Scott';
+ $record['lastname'] = 'Fletcher';
+ $record['firstnamephonetic'] = 'ć¹ć³ćć';
+ $record['lastnamephonetic'] = 'ćć¬ćć£ć¼';
+ $record['alternatename'] = 'No friends';
+ $user = $this->getDataGenerator()->create_user($record);
+
+ // back up config settings for restore later.
+ $originalcfg = new stdClass();
+ $originalcfg->fullnamedisplay = $CFG->fullnamedisplay;
+
+ // Testing existing fullnamedisplay settings.
+ $CFG->fullnamedisplay = 'firstname';
+ $testname = fullname($user);
+ $this->assertEquals($testname, $user->firstname);
+
+ $CFG->fullnamedisplay = 'firstname lastname';
+ $expectedname = "$user->firstname $user->lastname";
+ $testname = fullname($user);
+ $this->assertEquals($testname, $expectedname);
+
+ $CFG->fullnamedisplay = 'lastname firstname';
+ $expectedname = "$user->lastname $user->firstname";
+ $testname = fullname($user);
+ $this->assertEquals($testname, $expectedname);
+
+ $expectedname = get_string('fullnamedisplay', null, $user);
+ $CFG->fullnamedisplay = 'language';
+ $testname = fullname($user);
+ $this->assertEquals($testname, $expectedname);
+
+ // Test override parameter.
+ $CFG->fullnamedisplay = 'firstname';
+ $expectedname = "$user->firstname $user->lastname";
+ $testname = fullname($user, true);
+ $this->assertEquals($testname, $expectedname);
+
+ // Test additional name fields.
+ $CFG->fullnamedisplay = 'lastname lastnamephonetic firstname firstnamephonetic';
+ $expectedname = "$user->lastname $user->lastnamephonetic $user->firstname $user->firstnamephonetic";
+ $testname = fullname($user);
+ $this->assertEquals($testname, $expectedname);
+
+ // Test for handling missing data.
+ $user->middlename = null;
+ // Parenthesis with no data.
+ $CFG->fullnamedisplay = 'firstname (middlename) lastname';
+ $expectedname = "$user->firstname $user->lastname";
+ $testname = fullname($user);
+ $this->assertEquals($testname, $expectedname);
+
+ // Extra spaces due to no data.
+ $CFG->fullnamedisplay = 'firstname middlename lastname';
+ $expectedname = "$user->firstname $user->lastname";
+ $testname = fullname($user);
+ $this->assertEquals($testname, $expectedname);
+
+ // Regular expression testing.
+ // Remove some data from the user fields
+ $user->firstnamephonetic = '';
+ $user->lastnamephonetic = '';
+
+ // Removing empty brackets and excess whitespace.
+ // All of these configurations should resolve to just firstname lastname.
+ $configarray = array();
+ $configarray[] = 'firstname lastname [firstnamephonetic lastnamephonetic]';
+ $configarray[] = 'firstname lastname \'middlename\'';
+ $configarray[] = 'firstname "firstnamephonetic" lastname';
+ $configarray[] = 'firstname ćfirstnamephoneticć lastname ćlastnamephoneticć';
+
+ foreach ($configarray as $config) {
+ $CFG->fullnamedisplay = $config;
+ $expectedname = "$user->firstname $user->lastname";
+ $testname = fullname($user);
+ $this->assertEquals($testname, $expectedname);
+ }
+
+ // Check to make sure that other characters are left in place.
+ $configarray = array();
+ $configarray['0'] = new stdClass();
+ $configarray['0']->config = 'lastname firstname, middlename';
+ $configarray['0']->expectedname = "$user->lastname $user->firstname,";
+ $configarray['1'] = new stdClass();
+ $configarray['1']->config = 'lastname firstname + alternatename';
+ $configarray['1']->expectedname = "$user->lastname $user->firstname + $user->alternatename";
+ $configarray['2'] = new stdClass();
+ $configarray['2']->config = 'firstname aka: alternatename';
+ $configarray['2']->expectedname = "$user->firstname aka: $user->alternatename";
+ $configarray['3'] = new stdClass();
+ $configarray['3']->config = 'firstname (alternatename)';
+ $configarray['3']->expectedname = "$user->firstname ($user->alternatename)";
+ $configarray['4'] = new stdClass();
+ $configarray['4']->config = 'firstname [alternatename]';
+ $configarray['4']->expectedname = "$user->firstname [$user->alternatename]";
+ $configarray['5'] = new stdClass();
+ $configarray['5']->config = 'firstname "lastname"';
+ $configarray['5']->expectedname = "$user->firstname \"$user->lastname\"";
+
+ foreach ($configarray as $config) {
+ $CFG->fullnamedisplay = $config->config;
+ $expectedname = $config->expectedname;
+ $testname = fullname($user);
+ $this->assertEquals($testname, $expectedname);
+ }
+
+ // tidy up after we finish testing.
+ $CFG->fullnamedisplay = $originalcfg->fullnamedisplay;
+ }
+
+ public function test_get_all_user_name_fields() {
+ $this->resetAfterTest();
+
+ // Additional names in an array.
+ $testarray = array('firstnamephonetic',
+ 'lastnamephonetic',
+ 'middlename',
+ 'alternatename',
+ 'firstname',
+ 'lastname');
+ $this->assertEquals($testarray, get_all_user_name_fields());
+
+ // Additional names as a string.
+ $teststring = 'firstnamephonetic,lastnamephonetic,middlename,alternatename,firstname,lastname';
+ $this->assertEquals($teststring, get_all_user_name_fields(true));
+
+ // Additional names as a string with an alias.
+ $teststring = 't.firstnamephonetic,t.lastnamephonetic,t.middlename,t.alternatename,t.firstname,t.lastname';
+ $this->assertEquals($teststring, get_all_user_name_fields(true, 't'));
+ }
+
+ public function test_order_in_string() {
+ $this->resetAfterTest();
+
+ // Return an array in an order as they are encountered in a string.
+ $valuearray = array('second', 'firsthalf', 'first');
+ $formatstring = 'first firsthalf some other text (second)';
+ $expectedarray = array('0' => 'first', '6' => 'firsthalf', '33' => 'second');
+ $this->assertEquals($expectedarray, order_in_string($valuearray, $formatstring));
+
+ // Try again with a different order for the format.
+ $valuearray = array('second', 'firsthalf', 'first');
+ $formatstring = 'firsthalf first second';
+ $expectedarray = array('0' => 'firsthalf', '10' => 'first', '16' => 'second');
+ $this->assertEquals($expectedarray, order_in_string($valuearray, $formatstring));
+
+ // Try again with yet another different order for the format.
+ $valuearray = array('second', 'firsthalf', 'first');
+ $formatstring = 'start seconds away second firstquater first firsthalf';
+ $expectedarray = array('19' => 'second', '38' => 'first', '44' => 'firsthalf');
+ $this->assertEquals($expectedarray, order_in_string($valuearray, $formatstring));
+ }
}
<version>2012.08.22-20-00</version>
<licenseversion></licenseversion>
</library>
+ <library>
+ <location>lib/editor/tinymce/plugins/pdw/tinymce</location>
+ <name>PDW Toolbar Toggle</name>
+ <license>MIT</license>
+ <version>1.2</version>
+ <licenseversion></licenseversion>
+ </library>
</libraries>
information provided here is intended especially for developers.
=== 2.6 ===
+
* Use new core_component::* plugin listing and component normalisation methods.
* Use core_text::* instead of textlib:: and also core_collator::* instead of collatorlib::*.
* get_context_instance() is deprecated, please use use context_xxxx::instance().
* get_context_instance_by_id() is deprecated, please use context::instance_by_id($id).
+* load_temp_role() and remove_temp_roles() can not be used any more.
+* get_system_context() is deprecated, please use context_system::instance().
+* get_parent_contexts() is deprecated, please use $context->get_parent_context_ids().
+* Use new function moodleform::mock_submit() to simulate form submission in unit tests (backported).
=== 2.5.1 ===
if (count($tokens) > 0) {
$token = array_pop($tokens);
} else {
- if ( ($serviceshortname == MOODLE_OFFICIAL_MOBILE_SERVICE and has_capability('moodle/webservice:createmobiletoken', get_system_context()))
+ if ( ($serviceshortname == MOODLE_OFFICIAL_MOBILE_SERVICE and has_capability('moodle/webservice:createmobiletoken', context_system::instance()))
//Note: automatically token generation is not available to admin (they must create a token manually)
- or (!is_siteadmin($user) && has_capability('moodle/webservice:createtoken', get_system_context()))) {
+ or (!is_siteadmin($user) && has_capability('moodle/webservice:createtoken', context_system::instance()))) {
// if service doesn't exist, dml will throw exception
$service_record = $DB->get_record('external_services', array('shortname'=>$serviceshortname, 'enabled'=>1), '*', MUST_EXIST);
// create a new token
die();
}
-$roamingusers = get_users_by_capability(get_system_context(), 'moodle/site:mnetlogintoremote', 'u.id');
+$roamingusers = get_users_by_capability(context_system::instance(), 'moodle/site:mnetlogintoremote', 'u.id');
if (empty($roamingusers)) {
$capname = get_string('site:mnetlogintoremote', 'role');
$url = new moodle_url('/admin/roles/manage.php');
public function find_users($search) {
global $CFG, $DB;
- $systemcontext = get_system_context();
+ $systemcontext = context_system::instance();
$userids = get_users_by_capability($systemcontext, 'moodle/site:mnetlogintoremote', 'u.id');
if (empty($userids)) {
// Create the class for this controller.
$pluginmanager = new assign_plugin_manager(required_param('subtype', PARAM_PLUGIN));
-$PAGE->set_context(get_system_context());
+$PAGE->set_context(context_system::instance());
// Execute the controller.
$pluginmanager->execute(optional_param('action', null, PARAM_PLUGIN),
if ($data->id) {
// store the files
+ $data->timemodified = time();
$data = file_postupdate_standard_editor($data, 'content', $options, $context, 'mod_book', 'chapter', $data->id);
$DB->update_record('book_chapters', $data);
$DB->set_field('book', 'revision', $book->revision+1, array('id'=>$book->id));
// Get directory contents.
$userfolders = new DirectoryIterator($oldpresetdir);
// Store the system context, these are site wide presets.
- $context = get_system_context();
+ $context = context_system::instance();
// Create file storage object.
$fs = get_file_storage();
// Create array of accepted files.
*/
function data_get_advanced_search_sql($sort, $data, $recordids, $selectdata, $sortorder) {
global $DB;
+
+ $namefields = get_all_user_name_fields(true, 'u');
if ($sort == 0) {
- $nestselectsql = 'SELECT r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname
+ $nestselectsql = 'SELECT r.id, r.approved, r.timecreated, r.timemodified, r.userid, ' . $namefields . '
FROM {data_content} c,
{data_records} r,
{user} u ';
- $groupsql = ' GROUP BY r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname ';
+ $groupsql = ' GROUP BY r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname, ' . $namefields;
} else {
// Sorting through 'Other' criteria
if ($sort <= 0) {
$sortcontentfull = $sortfield->get_sort_sql($sortcontent);
}
- $nestselectsql = 'SELECT r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname, ' . $sortcontentfull . '
+ $nestselectsql = 'SELECT r.id, r.approved, r.timecreated, r.timemodified, r.userid, ' . $namefields . ',
+ ' . $sortcontentfull . '
AS sortorder
FROM {data_content} c,
{data_records} r,
{user} u ';
- $groupsql = ' GROUP BY r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname, ' .$sortcontentfull;
+ $groupsql = ' GROUP BY r.id, r.approved, r.timecreated, r.timemodified, r.userid, ' . $namefields . ', ' .$sortcontentfull;
}
// Default to a standard Where statement if $selectdata is empty.
$this->finalrecord[6]->userid = 6;
$this->finalrecord[6]->firstname = $user->firstname;
$this->finalrecord[6]->lastname = $user->lastname;
+ $this->finalrecord[6]->firstnamephonetic = $user->firstnamephonetic;
+ $this->finalrecord[6]->lastnamephonetic = $user->lastnamephonetic;
+ $this->finalrecord[6]->middlename = $user->middlename;
+ $this->finalrecord[6]->alternatename = $user->alternatename;
}
/**
$advparams = array();
// This is used for the initial reduction of advanced search results with required entries.
$entrysql = '';
+ $namefields = get_all_user_name_fields(true, 'u');
/// Find the field we are sorting on
if ($sort <= 0 or !$sortfield = data_get_field_from_id($sort, $data)) {
$ordering = "r.timecreated $order";
}
- $what = ' DISTINCT r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname';
+ $what = ' DISTINCT r.id, r.approved, r.timecreated, r.timemodified, r.userid, ' . $namefields;
$count = ' COUNT(DISTINCT c.recordid) ';
$tables = '{data_content} c,{data_records} r, {user} u ';
$where = 'WHERE c.recordid = r.id
$advparams = array_merge($advparams, $val->params);
}
} else if ($search) {
- $searchselect = " AND (".$DB->sql_like('c.content', ':search1', false)." OR ".$DB->sql_like('u.firstname', ':search2', false)." OR ".$DB->sql_like('u.lastname', ':search3', false)." ) ";
+ $searchselect = " AND (".$DB->sql_like('c.content', ':search1', false)."
+ OR ".$DB->sql_like('u.firstname', ':search2', false)."
+ OR ".$DB->sql_like('u.lastname', ':search3', false)." ) ";
$params['search1'] = "%$search%";
$params['search2'] = "%$search%";
$params['search3'] = "%$search%";
$sortcontent = $DB->sql_compare_text('c.' . $sortfield->get_sort_field());
$sortcontentfull = $sortfield->get_sort_sql($sortcontent);
- $what = ' DISTINCT r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname, ' . $sortcontentfull . ' AS sortorder ';
+ $what = ' DISTINCT r.id, r.approved, r.timecreated, r.timemodified, r.userid, ' . $namefields . ',
+ ' . $sortcontentfull . ' AS sortorder ';
$count = ' COUNT(DISTINCT c.recordid) ';
$tables = '{data_content} c, {data_records} r, {user} u ';
$where = 'WHERE c.recordid = r.id
}
if ($template->ispublic) {
- $systemcontext = get_system_context();
+ $systemcontext = context_system::instance();
require_capability('mod/feedback:createpublictemplate', $systemcontext);
require_capability('mod/feedback:deletetemplate', $systemcontext);
}
echo $OUTPUT->box_end();
}
//now we get the public templates if it is permitted
- $systemcontext = get_system_context();
+ $systemcontext = context_system::instance();
if (has_capability('mod/feedback:createpublictemplate', $systemcontext) AND
has_capability('mod/feedback:deletetemplate', $systemcontext)) {
$templates = feedback_get_template_list($course, 'public');
$savereturn = 'notsaved_name';
} else {
//If the feedback is located on the frontpage then templates can be public.
- if (has_capability('mod/feedback:createpublictemplate', get_system_context())) {
+ if (has_capability('mod/feedback:createpublictemplate', context_system::instance())) {
$create_template_formdata->ispublic = isset($create_template_formdata->ispublic) ? 1 : 0;
} else {
$create_template_formdata->ispublic = 0;
get_string('name', 'feedback'),
array('size'=>'40', 'maxlength'=>'200'));
- if (has_capability('mod/feedback:createpublictemplate', get_system_context())) {
+ if (has_capability('mod/feedback:createpublictemplate', context_system::instance())) {
$elementgroup[] = $mform->createElement('checkbox',
'ispublic',
get_string('public', 'feedback'),
if (!$item->feedback AND $item->template) {
$template = $DB->get_record('feedback_template', array('id'=>$item->template));
if ($template->ispublic) {
- $context = get_system_context();
+ $context = context_system::instance();
} else {
$context = context_course::instance($template->course);
}
//if the template is public the files are in the system context
//files in the feedback_item are in the feedback_context of the feedback
if ($ispublic) {
- $s_context = get_system_context();
+ $s_context = context_system::instance();
} else {
$s_context = context_course::instance($newtempl->course);
}
//files in the template_item are in the context of the current course
//files in the feedback_item are in the feedback_context of the feedback
if ($template->ispublic) {
- $s_context = get_system_context();
+ $s_context = context_system::instance();
} else {
$s_context = context_course::instance($feedback->course);
}
if ($template) {
if ($template->ispublic) {
- $context = get_system_context();
+ $context = context_system::instance();
} else {
$context = context_course::instance($template->course);
}
function forum_get_post_full($postid) {
global $CFG, $DB;
- return $DB->get_record_sql("SELECT p.*, d.forum, u.firstname, u.lastname, u.email, u.picture, u.imagealt
+ $allnames = get_all_user_name_fields(true, 'u');
+ return $DB->get_record_sql("SELECT p.*, d.forum, $allnames, u.email, u.picture, u.imagealt
FROM {forum_posts} p
JOIN {forum_discussions} d ON p.discussion = d.id
LEFT JOIN {user} u ON p.userid = u.id
function forum_get_discussion_posts($discussion, $sort, $forumid) {
global $CFG, $DB;
- return $DB->get_records_sql("SELECT p.*, $forumid AS forum, u.firstname, u.lastname, u.email, u.picture, u.imagealt
+ $allnames = get_all_user_name_fields(true, 'u');
+ return $DB->get_records_sql("SELECT p.*, $forumid AS forum, $allnames, u.email, u.picture, u.imagealt
FROM {forum_posts} p
LEFT JOIN {user} u ON p.userid = u.id
WHERE p.discussion = ?
$params[] = $USER->id;
}
+ $allnames = get_all_user_name_fields(true, 'u');
$params[] = $discussionid;
- if (!$posts = $DB->get_records_sql("SELECT p.*, u.firstname, u.lastname, u.email, u.picture, u.imagealt $tr_sel
+ if (!$posts = $DB->get_records_sql("SELECT p.*, $allnames, u.email, u.picture, u.imagealt $tr_sel
FROM {forum_posts} p
LEFT JOIN {user} u ON p.userid = u.id
$tr_join
function forum_get_child_posts($parent, $forumid) {
global $CFG, $DB;
- return $DB->get_records_sql("SELECT p.*, $forumid AS forum, u.firstname, u.lastname, u.email, u.picture, u.imagealt
+ $allnames = get_all_user_name_fields(true, 'u');
+ return $DB->get_records_sql("SELECT p.*, $forumid AS forum, $allnames, u.email, u.picture, u.imagealt
FROM {forum_posts} p
LEFT JOIN {user} u ON p.userid = u.id
WHERE p.parent = ?
FROM $fromsql
WHERE $selectsql";
+ $allnames = get_all_user_name_fields(true, 'u');
$searchsql = "SELECT p.*,
d.forum,
- u.firstname,
- u.lastname,
+ $allnames,
u.email,
u.picture,
u.imagealt
}
}
- return $DB->get_records_sql("SELECT p.*, d.forum, u.firstname, u.lastname, u.email, u.picture, u.imagealt
+ $allnames = get_all_user_name_fields(true, 'u');
+ return $DB->get_records_sql("SELECT p.*, d.forum, $allnames, u.email, u.picture, u.imagealt
FROM {forum} f
JOIN {forum_discussions} d ON d.forum = f.id
JOIN {forum_posts} p ON p.discussion = d.id
function forum_get_post_from_log($log) {
global $CFG, $DB;
+ $allnames = get_all_user_name_fields(true, 'u');
if ($log->action == "add post") {
- return $DB->get_record_sql("SELECT p.*, f.type AS forumtype, d.forum, d.groupid,
- u.firstname, u.lastname, u.email, u.picture
+ return $DB->get_record_sql("SELECT p.*, f.type AS forumtype, d.forum, d.groupid, $allnames, u.email, u.picture
FROM {forum_discussions} d,
{forum_posts} p,
{forum} f,
} else if ($log->action == "add discussion") {
- return $DB->get_record_sql("SELECT p.*, f.type AS forumtype, d.forum, d.groupid,
- u.firstname, u.lastname, u.email, u.picture
+ return $DB->get_record_sql("SELECT p.*, f.type AS forumtype, d.forum, d.groupid, $allnames, u.email, u.picture
FROM {forum_discussions} d,
{forum_posts} p,
{forum} f,
$umtable = " LEFT JOIN {user} um ON (d.usermodified = um.id)";
}
- $sql = "SELECT $postdata, d.name, d.timemodified, d.usermodified, d.groupid, d.timestart, d.timeend,
- u.firstname, u.lastname, u.email, u.picture, u.imagealt $umfields
+ $allnames = get_all_user_name_fields(true, 'u');
+ $sql = "SELECT $postdata, d.name, d.timemodified, d.usermodified, d.groupid, d.timestart, d.timeend, $allnames,
+ u.email, u.picture, u.imagealt $umfields
FROM {forum_discussions} d
JOIN {forum_posts} p ON p.discussion = d.id
JOIN {user} u ON p.userid = u.id
$groupselect = "";
}
- return $DB->get_records_sql("SELECT p.*, d.groupid, u.firstname, u.lastname, u.email, u.picture, u.imagealt,
+ $allnames = get_all_user_name_fields(true, 'u');
+ return $DB->get_records_sql("SELECT p.*, d.groupid, $allnames, u.email, u.picture, u.imagealt,
f.type as forumtype, f.name as forumname, f.id as forumid
FROM {forum_discussions} d,
{forum_posts} p,
function forum_subscribed_users($course, $forum, $groupid=0, $context = null, $fields = null) {
global $CFG, $DB;
+ $allnames = get_all_user_name_fields(true, 'u');
if (empty($fields)) {
$fields ="u.id,
u.username,
- u.firstname,
- u.lastname,
+ $allnames,
u.maildisplay,
u.mailformat,
u.maildigest,
// Build an object that represents the posting user
$postuser = new stdClass;
$postuser->id = $post->userid;
- $postuser->firstname = $post->firstname;
- $postuser->lastname = $post->lastname;
+ foreach (get_all_user_name_fields() as $addname) {
+ $postuser->$addname = $post->$addname;
+ }
$postuser->imagealt = $post->imagealt;
$postuser->picture = $post->picture;
$postuser->email = $post->email;
// Picture
$postuser = new stdClass();
$postuser->id = $post->userid;
- $postuser->firstname = $post->firstname;
- $postuser->lastname = $post->lastname;
+ foreach (get_all_user_name_fields() as $addname) {
+ $postuser->$addname = $post->$addname;
+ }
$postuser->imagealt = $post->imagealt;
$postuser->picture = $post->picture;
$postuser->email = $post->email;
$parenturl = (empty($post->lastpostid)) ? '' : '&parent='.$post->lastpostid;
$usermodified = new stdClass();
$usermodified->id = $post->usermodified;
- $usermodified->firstname = $post->umfirstname;
- $usermodified->lastname = $post->umlastname;
+ foreach (get_all_user_name_fields() as $addname) {
+ $temp = 'um' . $addname;
+ $usermodified->$addname = $post->$temp;
+ }
echo '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$post->usermodified.'&course='.$forum->course.'">'.
fullname($usermodified).'</a><br />';
echo '<a href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.$post->discussion.$parenturl.'">'.
$groupjoin = "";
}
+ $allnames = get_all_user_name_fields(true, 'u');
if (!$posts = $DB->get_records_sql("SELECT p.*, f.type AS forumtype, d.forum, d.groupid,
d.timestart, d.timeend, d.userid AS duserid,
- u.firstname, u.lastname, u.email, u.picture, u.imagealt, u.email
+ $allnames, u.email, u.picture, u.imagealt, u.email
FROM {forum_posts} p
JOIN {forum_discussions} d ON d.id = p.discussion
JOIN {forum} f ON f.id = d.forum
$tmpactivity->user = new stdClass();
$tmpactivity->user->id = $post->userid;
- $tmpactivity->user->firstname = $post->firstname;
- $tmpactivity->user->lastname = $post->lastname;
$tmpactivity->user->picture = $post->picture;
$tmpactivity->user->imagealt = $post->imagealt;
$tmpactivity->user->email = $post->email;
+ foreach (get_all_user_name_fields() as $addname) {
+ $tmpactivity->user->$addname = $post->$addname;
+ }
$activities[$index++] = $tmpactivity;
}
// Make sure the user has not been deleted
if ($user->deleted) {
$PAGE->set_title(get_string('userdeleted'));
- $PAGE->set_context(get_system_context());
+ $PAGE->set_context(context_system::instance());
echo $OUTPUT->header();
echo $OUTPUT->heading($PAGE->title);
echo $OUTPUT->footer();
// We are going to search for all of the users posts in all courses!
// a general require login here as we arn't actually within any course.
require_login();
- $PAGE->set_context(get_system_context());
+ $PAGE->set_context(context_system::instance());
// Now we need to get all of the courses to search.
// All courses where the user has posted within a forum will be returned.
global $CFG;
$output = '';
+
// Print quiz name and description.
$output .= $this->heading(format_string($quiz->name));
- if (trim(strip_tags($quiz->intro))) {
- $output .= $this->box(format_module_intro('quiz', $quiz, $cm->id), 'generalbox',
- 'intro');
- }
+ $output .= $this->quiz_intro($quiz, $cm);
- $output .= $this->box($this->access_messages($messages), 'quizinfo');
+ // Output any access messages.
+ if ($messages) {
+ $output .= $this->box($this->access_messages($messages), 'quizinfo');
+ }
// Show number of attempts summary to those who can view reports.
if (has_capability('mod/quiz:viewreports', $context)) {
* @return string HTML to output.
*/
public function quiz_intro($quiz, $cm) {
- if (trim(strip_tags($quiz->intro))) {
- return $this->box(format_module_intro('quiz', $quiz, $cm->id),
- 'generalbox', 'intro');
-
- } else {
+ if (html_is_blank($quiz->intro)) {
return '';
}
+
+ return $this->box(format_module_intro('quiz', $quiz, $cm->id), 'generalbox', 'intro');
}
/**
global $OUTPUT;
$user = new stdClass();
$user->id = $attempt->userid;
- $user->lastname = $attempt->lastname;
- $user->firstname = $attempt->firstname;
$user->imagealt = $attempt->imagealt;
$user->picture = $attempt->picture;
$user->email = $attempt->email;
+ foreach (get_all_user_name_fields() as $addname) {
+ $user->$addname = $attempt->$addname;
+ }
return $OUTPUT->user_picture($user);
}
$extrafields = get_extra_user_fields_sql($this->context, 'u', '',
array('id', 'idnumber', 'firstname', 'lastname', 'picture',
'imagealt', 'institution', 'department', 'email'));
+ $allnames = get_all_user_name_fields(true, 'u');
$fields .= '
quiza.uniqueid AS usageid,
quiza.id AS attempt,
u.id AS userid,
- u.idnumber,
- u.firstname,
- u.lastname,
+ u.idnumber, ' . $allnames . ',
u.picture,
u.imagealt,
u.institution,
get_string('showdetailedmarks', 'quiz_overview'));
} else {
$mform->addElement('hidden', 'slotmarks', 0);
+ $mform->setType('slotmarks', PARAM_INT);
}
}
}
$record->reference = $scorm->packageurl;
} else if ($record->scormtype === SCORM_TYPE_AICCURL) {
$record->reference = $scorm->packageurl;
+ $record->hidetoc = SCORM_TOC_DISABLED; // TOC is useless for direct AICCURL so disable it.
} else {
return false;
}
$scorm->reference = $scorm->packageurl;
} else if ($scorm->scormtype === SCORM_TYPE_AICCURL) {
$scorm->reference = $scorm->packageurl;
+ $scorm->hidetoc = SCORM_TOC_DISABLED; // TOC is useless for direct AICCURL so disable it.
} else {
return false;
}
$mform->addHelpButton('hidetoc', 'hidetoc', 'scorm');
$mform->setDefault('hidetoc', $cfg_scorm->hidetoc);
$mform->setAdvanced('hidetoc', $cfg_scorm->hidetoc_adv);
+ $mform->disabledIf('hidetoc', 'scormtype', 'eq', SCORM_TYPE_AICCURL);
// Hide Navigation panel.
$mform->addElement('selectyesno', 'hidenav', get_string('hidenav', 'scorm'));
// Construct the SQL
$select = 'SELECT DISTINCT '.$DB->sql_concat('u.id', '\'#\'', 'COALESCE(st.attempt, 0)').' AS uniqueid, ';
$select .= 'st.scormid AS scormid, st.attempt AS attempt, ' .
- 'u.id AS userid, u.idnumber, u.firstname, u.lastname, u.picture, u.imagealt, u.email' .
+ user_picture::fields('u', array('idnumber'), 'userid') .
get_extra_user_fields_sql($coursecontext, 'u', '', array('email', 'idnumber')) . ' ';
// This part is the same for all cases - join users and scorm_scoes_track tables
'id'=>$scouser->userid,
'picture'=>$scouser->picture,
'imagealt'=>$scouser->imagealt,
- 'email'=>$scouser->email,
- 'firstname'=>$scouser->firstname,
- 'lastname'=>$scouser->lastname);
+ 'email'=>$scouser->email);
+ foreach (get_all_user_name_fields() as $addname) {
+ $user->$addname = $scouser->$addname;
+ }
$row[] = $OUTPUT->user_picture($user, array('courseid'=>$course->id));
}
if (!$download) {
$params = array();
list($usql, $params) = $DB->get_in_or_equal($allowedlist, SQL_PARAMS_NAMED);
- // Construct the SQL
+ // Construct the SQL
$select = 'SELECT DISTINCT '.$DB->sql_concat('u.id', '\'#\'', 'COALESCE(st.attempt, 0)').' AS uniqueid, ';
$select .= 'st.scormid AS scormid, st.attempt AS attempt, ' .
- 'u.id AS userid, u.idnumber, u.firstname, u.lastname, u.picture, u.imagealt, u.email'.
+ user_picture::fields('u', array('idnumber'), 'userid') .
get_extra_user_fields_sql($coursecontext, 'u', '', array('email', 'idnumber')) . ' ';
// This part is the same for all cases - join users and scorm_scoes_track tables
'id'=>$scouser->userid,
'picture'=>$scouser->picture,
'imagealt'=>$scouser->imagealt,
- 'email'=>$scouser->email,
- 'firstname'=>$scouser->firstname,
- 'lastname'=>$scouser->lastname);
+ 'email'=>$scouser->email);
+ foreach (get_all_user_name_fields() as $addname) {
+ $user->$addname = $scouser->$addname;
+ }
$row[] = $OUTPUT->user_picture($user, array('courseid'=>$course->id));
}
if (!$download) {
// load the participants' submissions
$submissions = $this->workshop->get_submissions(array_keys($participants));
+ $allnames = get_all_user_name_fields();
foreach ($submissions as $submission) {
if (!isset($userinfo[$submission->authorid])) {
$userinfo[$submission->authorid] = new stdclass();
$userinfo[$submission->authorid]->id = $submission->authorid;
- $userinfo[$submission->authorid]->firstname = $submission->authorfirstname;
- $userinfo[$submission->authorid]->lastname = $submission->authorlastname;
$userinfo[$submission->authorid]->picture = $submission->authorpicture;
$userinfo[$submission->authorid]->imagealt = $submission->authorimagealt;
$userinfo[$submission->authorid]->email = $submission->authoremail;
+ foreach ($allnames as $addname) {
+ $temp = 'author' . $addname;
+ $userinfo[$submission->authorid]->$addname = $submission->$temp;
+ }
}
}
$reviewers = array();
if ($submissions) {
list($submissionids, $params) = $DB->get_in_or_equal(array_keys($submissions), SQL_PARAMS_NAMED);
- $sql = "SELECT a.id AS assessmentid, a.submissionid,
- r.id AS reviewerid, r.lastname, r.firstname, r.picture, r.imagealt, r.email,
+ $picturefields = user_picture::fields('r', array(), 'reviewerid')
+ $sql = "SELECT a.id AS assessmentid, a.submissionid, $picturefields,
s.id AS submissionid, s.authorid
FROM {workshop_assessments} a
JOIN {user} r ON (a.reviewerid = r.id)
if (!isset($userinfo[$reviewer->reviewerid])) {
$userinfo[$reviewer->reviewerid] = new stdclass();
$userinfo[$reviewer->reviewerid]->id = $reviewer->reviewerid;
- $userinfo[$reviewer->reviewerid]->firstname = $reviewer->firstname;
- $userinfo[$reviewer->reviewerid]->lastname = $reviewer->lastname;
$userinfo[$reviewer->reviewerid]->picture = $reviewer->picture;
$userinfo[$reviewer->reviewerid]->imagealt = $reviewer->imagealt;
$userinfo[$reviewer->reviewerid]->email = $reviewer->email;
+ foreach ($allnames as $addname) {
+ $userinfo[$reviewer->reviewerid]->$addname = $reviewer->$addname;
+ }
}
}
}
$reviewees = array();
if ($participants) {
list($participantids, $params) = $DB->get_in_or_equal(array_keys($participants), SQL_PARAMS_NAMED);
+ $namefields = get_all_user_name_fields(true, 'e');
$params['workshopid'] = $this->workshop->id;
$sql = "SELECT a.id AS assessmentid, a.submissionid,
u.id AS reviewerid,
s.id AS submissionid,
- e.id AS revieweeid, e.lastname, e.firstname, e.picture, e.imagealt, e.email
+ e.id AS revieweeid, e.lastname, e.firstname, $namefields, e.picture, e.imagealt, e.email
FROM {user} u
JOIN {workshop_assessments} a ON (a.reviewerid = u.id)
JOIN {workshop_submissions} s ON (a.submissionid = s.id)
$userinfo[$reviewee->revieweeid]->picture = $reviewee->picture;
$userinfo[$reviewee->revieweeid]->imagealt = $reviewee->imagealt;
$userinfo[$reviewee->revieweeid]->email = $reviewee->email;
+ foreach ($allnames as $addname) {
+ $userinfo[$reviewee->revieweeid]->$addname = $reviewee->$addname;
+ }
}
}
}
$sqlsort[] = $sqlsortfieldname . ' ' . $sqlsortfieldhow;
}
$sqlsort = implode(',', $sqlsort);
- $sql = "SELECT u.id AS userid,u.firstname,u.lastname,u.picture,u.imagealt,u.email,
- s.title AS submissiontitle, s.grade AS submissiongrade, ag.gradinggrade
+ $picturefields = user_picture::fields('u', array(), 'userid');
+ $sql = "SELECT $picturefields, s.title AS submissiontitle, s.grade AS submissiongrade, ag.gradinggrade
FROM {user} u
LEFT JOIN {workshop_submissions} s ON (s.authorid = u.id AND s.workshopid = :workshopid1 AND s.example = 0)
LEFT JOIN {workshop_aggregations} ag ON (ag.userid = u.id AND ag.workshopid = :workshopid2)
$userinfo = array();
// get the user details for all participants to display
+ $additionalnames = get_all_user_name_fields();
foreach ($participants as $participant) {
if (!isset($userinfo[$participant->userid])) {
$userinfo[$participant->userid] = new stdclass();
$userinfo[$participant->userid]->id = $participant->userid;
- $userinfo[$participant->userid]->firstname = $participant->firstname;
- $userinfo[$participant->userid]->lastname = $participant->lastname;
$userinfo[$participant->userid]->picture = $participant->picture;
$userinfo[$participant->userid]->imagealt = $participant->imagealt;
$userinfo[$participant->userid]->email = $participant->email;
+ foreach ($additionalnames as $addname) {
+ $userinfo[$participant->userid]->$addname = $participant->$addname;
+ }
}
}
if (!isset($userinfo[$submission->gradeoverby])) {
$userinfo[$submission->gradeoverby] = new stdclass();
$userinfo[$submission->gradeoverby]->id = $submission->gradeoverby;
- $userinfo[$submission->gradeoverby]->firstname = $submission->overfirstname;
- $userinfo[$submission->gradeoverby]->lastname = $submission->overlastname;
$userinfo[$submission->gradeoverby]->picture = $submission->overpicture;
$userinfo[$submission->gradeoverby]->imagealt = $submission->overimagealt;
$userinfo[$submission->gradeoverby]->email = $submission->overemail;
+ foreach ($additionalnames as $addname) {
+ $temp = 'over' . $addname;
+ $userinfo[$submission->gradeoverby]->$addname = $submission->$temp;
+ }
}
}
// get the user details for all reviewers of the displayed participants
$reviewers = array();
+
if ($submissions) {
list($submissionids, $params) = $DB->get_in_or_equal(array_keys($submissions), SQL_PARAMS_NAMED);
list($sort, $sortparams) = users_order_by_sql('r');
+ $picturefields = user_picture::fields('r', array(), 'reviewerid');
$sql = "SELECT a.id AS assessmentid, a.submissionid, a.grade, a.gradinggrade, a.gradinggradeover, a.weight,
- r.id AS reviewerid, r.lastname, r.firstname, r.picture, r.imagealt, r.email,
- s.id AS submissionid, s.authorid
+ $picturefields, s.id AS submissionid, s.authorid
FROM {workshop_assessments} a
JOIN {user} r ON (a.reviewerid = r.id)
JOIN {workshop_submissions} s ON (a.submissionid = s.id AND s.example = 0)
if (!isset($userinfo[$reviewer->reviewerid])) {
$userinfo[$reviewer->reviewerid] = new stdclass();
$userinfo[$reviewer->reviewerid]->id = $reviewer->reviewerid;
- $userinfo[$reviewer->reviewerid]->firstname = $reviewer->firstname;
- $userinfo[$reviewer->reviewerid]->lastname = $reviewer->lastname;
$userinfo[$reviewer->reviewerid]->picture = $reviewer->picture;
$userinfo[$reviewer->reviewerid]->imagealt = $reviewer->imagealt;
$userinfo[$reviewer->reviewerid]->email = $reviewer->email;
+ foreach ($additionalnames as $addname) {
+ $userinfo[$reviewer->reviewerid]->$addname = $reviewer->$addname;
+ }
}
}
}
list($participantids, $params) = $DB->get_in_or_equal(array_keys($participants), SQL_PARAMS_NAMED);
list($sort, $sortparams) = users_order_by_sql('e');
$params['workshopid'] = $this->id;
+ $picturefields = user_picture::fields('e', array(), 'authorid');
$sql = "SELECT a.id AS assessmentid, a.submissionid, a.grade, a.gradinggrade, a.gradinggradeover, a.reviewerid, a.weight,
- s.id AS submissionid,
- e.id AS authorid, e.lastname, e.firstname, e.picture, e.imagealt, e.email
+ s.id AS submissionid, $picturefields
FROM {user} u
JOIN {workshop_assessments} a ON (a.reviewerid = u.id)
JOIN {workshop_submissions} s ON (a.submissionid = s.id AND s.example = 0)
if (!isset($userinfo[$reviewee->authorid])) {
$userinfo[$reviewee->authorid] = new stdclass();
$userinfo[$reviewee->authorid]->id = $reviewee->authorid;
- $userinfo[$reviewee->authorid]->firstname = $reviewee->firstname;
- $userinfo[$reviewee->authorid]->lastname = $reviewee->lastname;
$userinfo[$reviewee->authorid]->picture = $reviewee->picture;
$userinfo[$reviewee->authorid]->imagealt = $reviewee->imagealt;
$userinfo[$reviewee->authorid]->email = $reviewee->email;
+ foreach ($additionalnames as $addname) {
+ $userinfo[$reviewee->authorid]->$addname = $reviewee->$addname;
+ }
}
}
}
$callerformats = optional_param('callerformats', null, PARAM_TAGLIST); // Comma separated list of formats the specific place exporting content supports.
require_login(); // this is selectively called again with $course later when we know for sure which one we're in.
-$PAGE->set_context(get_system_context());
+$PAGE->set_context(context_system::instance());
$PAGE->set_url('/portfolio/add.php', array('id' => $dataid, 'sesskey' => sesskey()));
$PAGE->set_pagelayout('standard');
$exporter = null;
* this question type.
*/
abstract public function get_test_questions();
+
+ /**
+ * Set up a form to create a question in $cat. This method also sets cat and contextid on $questiondata object.
+ * @param object $cat the category
+ * @param object $questiondata form initialisation requires question data.
+ * @return moodleform
+ */
+ public static function get_question_editing_form($cat, $questiondata) {
+ $catcontext = context::instance_by_id($cat->contextid, MUST_EXIST);
+ $contexts = new question_edit_contexts($catcontext);
+ $dataforformconstructor = new stdClass();
+ $dataforformconstructor->qtype = $questiondata->qtype;
+ $dataforformconstructor->contextid = $questiondata->contextid = $catcontext->id;
+ $dataforformconstructor->category = $questiondata->category = $cat->id;
+ $dataforformconstructor->formoptions = new stdClass();
+ $dataforformconstructor->formoptions->canmove = true;
+ $dataforformconstructor->formoptions->cansaveasnew = true;
+ $dataforformconstructor->formoptions->movecontext = false;
+ $dataforformconstructor->formoptions->canedit = true;
+ $dataforformconstructor->formoptions->repeatelements = true;
+ $qtype = question_bank::get_qtype($questiondata->qtype);
+ return $qtype->create_editing_form('question.php', $dataforformconstructor, $cat, $contexts, true);
+ }
}
$qdata->hints = array();
}
- public static function initialise_question_form_data($qdata) {
- $formdata = new stdClass();
- $formdata->id = 0;
- $formdata->category = '0,0';
- $formdata->usecurrentcat = 1;
- $formdata->categorymoveto = '0,0';
- $formdata->tags = array();
- $formdata->penalty = 0.3333333;
- $formdata->questiontextformat = FORMAT_HTML;
- $formdata->generalfeedbackformat = FORMAT_HTML;
- }
-
/**
* Get the test helper class for a particular question type.
* @param $qtype the question type name, e.g. 'multichoice'.
$q->incorrectfeedback = self::STANDARD_OVERALL_INCORRECT_FEEDBACK;
$q->incorrectfeedbackformat = FORMAT_HTML;
}
+
+ /**
+ * Add some standard overall feedback to a question's form data.
+ */
+ public static function set_standard_combined_feedback_form_data($form) {
+ $form->correctfeedback = array('text' => self::STANDARD_OVERALL_CORRECT_FEEDBACK,
+ 'format' => FORMAT_HTML);
+ $form->partiallycorrectfeedback = array('text' => self::STANDARD_OVERALL_PARTIALLYCORRECT_FEEDBACK,
+ 'format' => FORMAT_HTML);
+ $form->shownumcorrect = true;
+ $form->incorrectfeedback = array('text' => self::STANDARD_OVERALL_INCORRECT_FEEDBACK,
+ 'format' => FORMAT_HTML);
+ }
}
qtype_calculatedmulti_calculate_helper::calculate_all_expressions($this);
}
-
public function get_num_variants() {
return $this->datasetloader->get_number_of_items();
}
public function calculate_all_expressions() {
qtype_calculatedmulti_calculate_helper::calculate_all_expressions($this);
}
+
+ public function get_num_variants() {
+ return $this->datasetloader->get_number_of_items();
+ }
+
+ public function get_variants_selection_seed() {
+ if (!empty($this->synchronised) &&
+ $this->datasetloader->datasets_are_synchronised($this->category)) {
+ return 'category' . $this->category;
+ } else {
+ return parent::get_variants_selection_seed();
+ }
+ }
}
*/
class qtype_calculatedsimple_test_helper extends question_test_helper {
public function get_test_questions() {
- return array('sum');
+ return array('sum', 'sumwithvariants');
}
/**
return $q;
}
+
+
+ public function get_calculatedsimple_question_form_data_sumwithvariants() {
+ $form = new stdClass();
+
+ $form->name = 'Calculated simple';
+
+ $form->qtype = 'calculatedsimple';
+
+ $form->questiontext = array();
+ $form->questiontext['text'] = '<p>This is a simple sum of two variables.</p>';
+ $form->questiontext['format'] = '1';
+
+ $form->defaultmark = 1;
+ $form->generalfeedback = array();
+ $form->generalfeedback['text'] = '<p>The answer isĀ {a} + {b}</p>';
+ $form->generalfeedback['format'] = '1';
+
+ $form->synchronize = 0;
+ $form->initialcategory = 1;
+ $form->reload = 1;
+ $form->mform_isexpanded_id_answerhdr = 1;
+ $form->noanswers = 1;
+ $form->answer = array('{a} + {b}');
+
+ $form->fraction = array('1.0');
+
+ $form->tolerance = array(0.01);
+ $form->tolerancetype = array('1');
+
+ $form->correctanswerlength = array('2');
+ $form->correctanswerformat = array('1');
+
+ $form->feedback = array();
+ $form->feedback[0] = array();
+ $form->feedback[0]['text'] = '';
+ $form->feedback[0]['format'] = '1';
+
+ $form->unitrole = '3';
+ $form->unitpenalty = 0.1;
+ $form->unitgradingtypes = '1';
+ $form->unitsleft = '0';
+ $form->nounits = 1;
+ $form->multiplier = array('1.0');
+
+ $form->penalty = '0.3333333';
+ $form->numhints = 2;
+ $form->hint = array();
+ $form->hint[0] = array();
+ $form->hint[0]['text'] = '';
+ $form->hint[0]['format'] = '1';
+
+ $form->hint[1] = array();
+ $form->hint[1]['text'] = '';
+ $form->hint[1]['format'] = '1';
+
+ $form->calcmin = array();
+ $form->calcmin[1] = 1;
+ $form->calcmin[2] = 1;
+
+ $form->calcmax = array();
+ $form->calcmax[1] = 10;
+ $form->calcmax[2] = 10;
+
+ $form->calclength = array();
+ $form->calclength[1] = '1';
+ $form->calclength[2] = '1';
+
+ $form->calcdistribution = array();
+ $form->calcdistribution[1] = 0;
+ $form->calcdistribution[2] = 0;
+
+ $form->datasetdef = array();
+ $form->datasetdef[1] = '1-0-a';
+ $form->datasetdef[2] = '1-0-b';
+
+ $form->defoptions = array();
+ $form->defoptions[1] = '';
+ $form->defoptions[2] = '';
+
+ $form->selectadd = '10';
+ $form->selectshow = '10';
+ $form->number = array();
+ $form->number[1] = '2.3';
+ $form->number[2] = '7.6';
+ $form->number[3] = '2.1';
+ $form->number[4] = '6.4';
+ $form->number[5] = '1.4';
+ $form->number[6] = '1.9';
+ $form->number[7] = '9.9';
+ $form->number[8] = '9.5';
+ $form->number[9] = '9.0';
+ $form->number[10] = '5.2';
+ $form->number[11] = '2.1';
+ $form->number[12] = '7.3';
+ $form->number[13] = '7.9';
+ $form->number[14] = '1.2';
+ $form->number[15] = '2.3';
+ $form->number[16] = '3.4';
+ $form->number[17] = '1.9';
+ $form->number[18] = '5.2';
+ $form->number[19] = '3.4';
+ $form->number[20] = '3.4';
+
+ $form->itemid = array_fill(1, 20, 0);
+
+ $form->definition = array();
+ $form->definition[1] = '1-0-b';
+ $form->definition[2] = '1-0-a';
+ $form->definition[3] = '1-0-b';
+ $form->definition[4] = '1-0-a';
+ $form->definition[5] = '1-0-b';
+ $form->definition[6] = '1-0-a';
+ $form->definition[7] = '1-0-b';
+ $form->definition[8] = '1-0-a';
+ $form->definition[9] = '1-0-b';
+ $form->definition[10] = '1-0-a';
+ $form->definition[11] = '1-0-b';
+ $form->definition[12] = '1-0-a';
+ $form->definition[13] = '1-0-b';
+ $form->definition[14] = '1-0-a';
+ $form->definition[15] = '1-0-b';
+ $form->definition[16] = '1-0-a';
+ $form->definition[17] = '1-0-b';
+ $form->definition[18] = '1-0-a';
+ $form->definition[19] = '1-0-b';
+ $form->definition[20] = '1-0-a';
+
+ return $form;
+ }
+
+ public function get_calculatedsimple_question_data_sumwithvariants() {
+ $q = new stdClass();
+
+ $q->name = 'Calculated simple';
+ $q->questiontext = '<p>This is a simple sum of two variables.</p>';
+ $q->questiontextformat = '1';
+ $q->generalfeedback = '<p>The answer isĀ {a} + {b}</p>';
+ $q->generalfeedbackformat = '1';
+ $q->defaultmark = 1;
+ $q->penalty = 0.3333333;
+ $q->qtype = 'calculatedsimple';
+ $q->length = '1';
+ $q->hidden = '0';
+ $q->options = new stdClass();
+ $q->options->synchronize = 0;
+ $q->options->single = 0;
+ $q->options->answernumbering = 'abc';
+ $q->options->shuffleanswers = 0;
+ $q->options->correctfeedback = '';
+ $q->options->partiallycorrectfeedback = '';
+ $q->options->incorrectfeedback = '';
+ $q->options->correctfeedbackformat = 0;
+ $q->options->partiallycorrectfeedbackformat = 0;
+ $q->options->incorrectfeedbackformat = 0;
+ $q->options->answers = array();
+ $q->options->answers[0] = new stdClass();
+ $q->options->answers[0]->id = '6977';
+ $q->options->answers[0]->question = '3379';
+ $q->options->answers[0]->answer = '{a} + {b}';
+ $q->options->answers[0]->answerformat = '0';
+ $q->options->answers[0]->fraction = '1.0000000';
+ $q->options->answers[0]->feedback = '';
+ $q->options->answers[0]->feedbackformat = '1';
+ $q->options->answers[0]->tolerance = '0.01';
+ $q->options->answers[0]->tolerancetype = '1';
+ $q->options->answers[0]->correctanswerlength = '2';
+ $q->options->answers[0]->correctanswerformat = '1';
+
+ $q->options->units = array();
+
+ $q->options->unitgradingtype = '0';
+ $q->options->unitpenalty = '0.1000000';
+ $q->options->showunits = '3';
+ $q->options->unitsleft = '0';
+
+ $q->hints = array();
+
+ return $q;
+ }
}
--- /dev/null
+<?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/>.
+
+/**
+ * Unit tests for the calculatedsimple question type class.
+ *
+ * @package qtype_calculatedsimple
+ * @copyright 2013 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->dirroot . '/question/type/calculatedsimple/questiontype.php');
+require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
+require_once($CFG->dirroot . '/question/type/edit_question_form.php');
+require_once($CFG->dirroot . '/question/type/calculatedsimple/edit_calculatedsimple_form.php');
+
+
+/**
+ * Unit tests for the calculatedsimple question type class.
+ *
+ * @copyright 2007 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class qtype_calculatedsimple_test extends advanced_testcase {
+ public static $includecoverage = array(
+ 'question/type/questiontypebase.php',
+ 'question/type/calculatedsimple/questiontype.php',
+ 'question/type/edit_question_form.php',
+ 'question/type/calculatedsimple/edit_calculatedsimple_form.php'
+ );
+
+ protected $qtype;
+
+ protected function setUp() {
+ $this->qtype = new qtype_calculatedsimple();
+ }
+
+ protected function tearDown() {
+ $this->qtype = null;
+ }
+
+ public function test_name() {
+ $this->assertEquals($this->qtype->name(), 'calculatedsimple');
+ }
+
+ public function test_can_analyse_responses() {
+ $this->assertTrue($this->qtype->can_analyse_responses());
+ }
+
+
+ public function test_question_saving_sumwithvariants() {
+ $this->resetAfterTest(true);
+ $this->setAdminUser();
+
+ $questiondata = test_question_maker::get_question_data('calculatedsimple', 'sumwithvariants');
+ $formdata = test_question_maker::get_question_form_data('calculatedsimple', 'sumwithvariants');
+
+ $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
+ $cat = $generator->create_question_category(array());
+
+ $formdata->category = "{$cat->id},{$cat->contextid}";
+ qtype_calculatedsimple_edit_form::mock_submit((array)$formdata);
+
+ $form = qtype_calculatedsimple_test_helper::get_question_editing_form($cat, $questiondata);
+
+ $this->assertTrue($form->is_validated());
+
+ $fromform = $form->get_data();
+
+ $returnedfromsave = $this->qtype->save_question($questiondata, $fromform);
+ $actualquestionsdata = question_load_questions(array($returnedfromsave->id));
+ $actualquestiondata = end($actualquestionsdata);
+
+ foreach ($questiondata as $property => $value) {
+ if (!in_array($property, array('id', 'version', 'timemodified', 'timecreated', 'options'))) {
+ $this->assertAttributeEquals($value, $property, $actualquestiondata);
+ }
+ }
+
+ foreach ($questiondata->options as $optionname => $value) {
+ if ($optionname != 'answers') {
+ $this->assertAttributeEquals($value, $optionname, $actualquestiondata->options);
+ }
+ }
+
+ foreach ($questiondata->options->answers as $answer) {
+ $actualanswer = array_shift($actualquestiondata->options->answers);
+ foreach ($answer as $ansproperty => $ansvalue) {
+ if (!in_array($ansproperty, array('id', 'question', 'answerformat'))) {
+ $this->assertAttributeEquals($ansvalue, $ansproperty, $actualanswer);
+ }
+ }
+ }
+
+ $datasetloader = new qtype_calculated_dataset_loader($actualquestiondata->id);
+
+ $this->assertEquals(10, $datasetloader->get_number_of_items());
+
+ for ($itemno = 1; $itemno <= 10; $itemno++) {
+ $item = $datasetloader->get_values($itemno);
+ $this->assertEquals($formdata->number[($itemno -1)*2 + 2], $item['a']);
+ $this->assertEquals($formdata->number[($itemno -1)*2 + 1], $item['b']);
+ }
+ }
+}
/**
* Test helper code for the description question type.
*
- * @package qtype
- * @subpackage description
- * @copyright 2010 The Open University
+ * @package qtype_description
+ * @copyright 2013 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Test helper class for the description question type.
*
- * @copyright 2010 The Open University
+ * @copyright 2013 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_description_test_helper extends question_test_helper {
}
/**
- * Get the question data, as it would be loaded by get_question_options, for
- * the question returned by {@link make_an_oumultiresponse_two_of_four()}.
+ * Get the question data, as it would be loaded by get_question_options.
* @return object
*/
- public static function get_question_data() {
+ public static function get_description_question_data_info() {
global $USER;
$qdata = new stdClass();
$qdata->length = 0;
$qdata->penalty = 0;
$qdata->hidden = 0;
+ $qdata->hints = array();
+ $qdata->options = new stdClass();
+ $qdata->options->answers = array();
return $qdata;
}
+
+
+ /**
+ * Get the question form data.
+ * @return object
+ */
+ public static function get_description_question_form_data_info() {
+ $form = new stdClass();
+
+ $form->name = 'Description';
+ $form->questiontext = array('text' => 'Here is some information about the questions you are about to attempt.',
+ 'format' => FORMAT_HTML);
+ $form->generalfeedback = array('text' => 'And here is some more text shown only on the review page.',
+ 'format' => FORMAT_HTML);
+
+ return $form;
+ }
+
}
/**
* Unit tests for the description question type class.
*
- * @package qtype
- * @subpackage description
- * @copyright 2010 The Open University
+ * @package qtype_description
+ * @copyright 2013 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
global $CFG;
require_once($CFG->dirroot . '/question/type/description/questiontype.php');
+require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
+require_once($CFG->dirroot . '/question/type/edit_question_form.php');
+require_once($CFG->dirroot . '/question/type/description/edit_description_form.php');
/**
* Unit tests for the description question type class.
*
- * @copyright 2010 The Open University
+ * @copyright 2013 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_description_test extends advanced_testcase {
public function test_get_possible_responses() {
$this->assertEquals(array(), $this->qtype->get_possible_responses(null));
}
+
+
+ public function test_question_saving() {
+ $this->resetAfterTest(true);
+ $this->setAdminUser();
+
+ $questiondata = test_question_maker::get_question_data('description');
+ $formdata = test_question_maker::get_question_form_data('description');
+
+ $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
+ $cat = $generator->create_question_category(array());
+
+ $formdata->category = "{$cat->id},{$cat->contextid}";
+ qtype_description_edit_form::mock_submit((array)$formdata);
+
+ $form = qtype_description_test_helper::get_question_editing_form($cat, $questiondata);
+
+ $this->assertTrue($form->is_validated());
+
+ $fromform = $form->get_data();
+
+ $returnedfromsave = $this->qtype->save_question($questiondata, $fromform);
+ $actualquestionsdata = question_load_questions(array($returnedfromsave->id));
+ $actualquestiondata = end($actualquestionsdata);
+
+ foreach ($questiondata as $property => $value) {
+ if (!in_array($property, array('id', 'version', 'timemodified', 'timecreated'))) {
+ $this->assertAttributeEquals($value, $property, $actualquestiondata);
+ }
+ }
+ }
}
--- /dev/null
+<?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/>.
+
+/**
+ * Test helpers for the match question type.
+ *
+ * @package qtype_match
+ * @copyright 2013 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->dirroot . '/question/type/match/question.php');
+
+
+/**
+ * Test helper class for the match question type.
+ *
+ * @copyright 2013 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class qtype_match_test_helper extends question_test_helper {
+ public function get_test_questions() {
+ return array('foursubq');
+ }
+
+
+ /**
+ * Makes a match question about completing two blanks in some text.
+ * @return object the question definition data, as it might be returned from
+ * get_question_options.
+ */
+ public function get_match_question_data_foursubq() {
+ global $USER;
+ $q = new stdClass();
+ test_question_maker::initialise_question_data($q);
+ $q->name = 'Matching question';
+ $q->qtype = 'match';
+ $q->parent = 0;
+ $q->questiontext = 'Classify the animals.';
+ $q->questiontextformat = FORMAT_HTML;
+ $q->generalfeedback = 'General feedback.';
+ $q->generalfeedbackformat = FORMAT_HTML;
+ $q->defaultmark = 1;
+ $q->penalty = 0.3333333;
+ $q->length = 1;
+ $q->hidden = 0;
+ $q->createdby = $USER->id;
+ $q->modifiedby = $USER->id;
+
+ $q->options = new stdClass();
+ $q->options->shuffleanswers = 0;
+ test_question_maker::set_standard_combined_feedback_fields($q->options);
+
+ $q->options->subquestions = array(
+ 14 => (object) array(
+ 'id' => 14,
+ 'questiontext' => 'frog',
+ 'questiontextformat' => FORMAT_HTML,
+ 'answertext' => 'amphibian'),
+ 15 => (object) array(
+ 'id' => 15,
+ 'questiontext' => 'cat',
+ 'questiontextformat' => FORMAT_HTML,
+ 'answertext' => 'mammal'),
+ 16 => (object) array(
+ 'id' => 16,
+ 'questiontext' => 'newt',
+ 'questiontextformat' => FORMAT_HTML,
+ 'answertext' => 'amphibian'),
+ 17 => (object) array(
+ 'id' => 17,
+ 'questiontext' => '',
+ 'questiontextformat' => FORMAT_HTML,
+ 'answertext' => 'insect'),
+ );
+
+ return $q;
+ }
+
+ /**
+ * Makes a match question about completing two blanks in some text.
+ * @return object the question definition data, as it might be returned from
+ * the question editing form.
+ */
+ public function get_match_question_form_data_foursubq() {
+ $q = new stdClass();
+ $q->name = 'Matching question';
+ $q->questiontext = array('text' => 'Classify the animals.', 'format' => FORMAT_HTML);
+ $q->generalfeedback = array('text' => 'General feedback.', 'format' => FORMAT_HTML);
+ $q->defaultmark = 1;
+ $q->penalty = 0.3333333;
+
+ $q->shuffleanswers = 0;
+ test_question_maker::set_standard_combined_feedback_form_data($q);
+
+ $q->subquestions = array(
+ 0 => array('text' => 'frog', 'format' => FORMAT_HTML),
+ 1 => array('text' => 'cat', 'format' => FORMAT_HTML),
+ 2 => array('text' => 'newt', 'format' => FORMAT_HTML),
+ 3 => array('text' => '', 'format' => FORMAT_HTML));
+
+ $q->subanswers = array(
+ 0 => 'amphibian',
+ 1 => 'mammal',
+ 2 => 'amphibian',
+ 3 => 'insect'
+ );
+
+ $q->noanswers = 4;
+
+ return $q;
+ }
+
+}
global $CFG;
require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
require_once($CFG->dirroot . '/question/type/match/questiontype.php');
+require_once($CFG->dirroot . '/question/type/edit_question_form.php');
+require_once($CFG->dirroot . '/question/type/match/edit_match_form.php');
/**
null => question_possible_response::no_response()),
), $this->qtype->get_possible_responses($q));
}
+
+
+ public&nbs