var expected = semver.validRange(grunt.file.readJSON('package.json').engines.node);
var actual = semver.valid(process.version);
if (!semver.satisfies(actual, expected)) {
- grunt.fail.fatal('Node version too old. Require ' + expected + ', version installed: ' + actual);
+ grunt.fail.fatal('Node version not satisfied. Require ' + expected + ', version installed: ' + actual);
}
// Windows users can't run grunt in a subdirectory, so allow them to set
$table->set_attribute('class', 'admintable generaltable');
$table->setup();
+ $pluginmanager = core_plugin_manager::instance();
+
foreach ($modules as $module) {
+ $plugininfo = $pluginmanager->get_plugin_info('mod_'.$module->name);
+ $status = $plugininfo->get_status();
- if (!file_exists("$CFG->dirroot/mod/$module->name/lib.php")) {
+ if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
$strmodulename = '<span class="notifyproblem">'.$module->name.' ('.get_string('missingfromdisk').')</span>';
$missing = true;
} else {
if ($siteunregistrationform->is_cancelled()) {
redirect(new moodle_url('/admin/registration/index.php'));
} else if ($data = $siteunregistrationform->get_data()) {
- if (\core\hub\registration::unregister($data->unpublishalladvertisedcourses,
- $data->unpublishalluploadedcourses)) {
+ \core\hub\registration::unregister($data->unpublishalladvertisedcourses,
+ $data->unpublishalluploadedcourses);
+ if (!\core\hub\registration::is_registered()) {
redirect(new moodle_url('/admin/registration/index.php'));
}
}
if ($contextcourse = $context->get_course_context(false)) {
// Below course level we look at module or block level roles + course-assigned roles.
- $courseroles = get_roles_with_assignment_on_context($contextcourse);
- $roles = $courseroles + get_roles_with_assignment_on_context($context);
+ $courseroles = get_roles_used_in_context($contextcourse, false);
+ $roles = $courseroles + get_roles_used_in_context($context, false);
} else {
// We list category + system for others (we don't work with user instances so no need to work about them).
$roles = get_roles_used_in_context($context);
$internaldata['compliant'] = false;
}
// Check to see if we are an external plugin.
- $componentshortname = explode('_', $component);
+ // Plugin names can contain _ characters, limit to 2 to just remove initial plugintype.
+ $componentshortname = explode('_', $component, 2);
$shortname = array_pop($componentshortname);
if (isset($contributedplugins[$plugintype][$shortname])) {
$internaldata['external'] = 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/>.
+
+/**
+ * tool_dataprivacy plugin upgrade code
+ *
+ * @package tool_dataprivacy
+ * @copyright 2018 Jun Pataleta
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Function to upgrade tool_dataprivacy.
+ *
+ * @param int $oldversion the version we are upgrading from
+ * @return bool result
+ */
+function xmldb_tool_dataprivacy_upgrade($oldversion) {
+ global $CFG, $DB;
+
+ $dbman = $DB->get_manager();
+
+ if ($oldversion < 2018051405) {
+ // Define table tool_dataprivacy_ctxexpired to be created.
+ $table = new xmldb_table('tool_dataprivacy_ctxexpired');
+
+ // Adding fields to table tool_dataprivacy_ctxexpired.
+ $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+ $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
+ $table->add_field('status', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0');
+ $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
+ $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
+ $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
+
+ // Adding keys to table tool_dataprivacy_ctxexpired.
+ $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+ $table->add_key('contextid', XMLDB_KEY_FOREIGN_UNIQUE, array('contextid'), 'context', array('id'));
+
+ // Conditionally launch create table for tool_dataprivacy_ctxexpired.
+ if (!$dbman->table_exists($table)) {
+ $dbman->create_table($table);
+ }
+
+ // Define table tool_dataprivacy_contextlist to be created.
+ $table = new xmldb_table('tool_dataprivacy_contextlist');
+
+ // Adding fields to table tool_dataprivacy_contextlist.
+ $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+ $table->add_field('component', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
+ $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
+ $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
+
+ // Adding keys to table tool_dataprivacy_contextlist.
+ $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+
+ // Conditionally launch create table for tool_dataprivacy_contextlist.
+ if (!$dbman->table_exists($table)) {
+ $dbman->create_table($table);
+ }
+
+ // Define table tool_dataprivacy_ctxlst_ctx to be created.
+ $table = new xmldb_table('tool_dataprivacy_ctxlst_ctx');
+
+ // Adding fields to table tool_dataprivacy_ctxlst_ctx.
+ $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+ $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
+ $table->add_field('contextlistid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
+ $table->add_field('status', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0');
+ $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
+ $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
+
+ // Adding keys to table tool_dataprivacy_ctxlst_ctx.
+ $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+ $table->add_key('contextlistid', XMLDB_KEY_FOREIGN, array('contextlistid'), 'tool_dataprivacy_contextlist', array('id'));
+
+ // Conditionally launch create table for tool_dataprivacy_ctxlst_ctx.
+ if (!$dbman->table_exists($table)) {
+ $dbman->create_table($table);
+ }
+
+ // Define table tool_dataprivacy_rqst_ctxlst to be created.
+ $table = new xmldb_table('tool_dataprivacy_rqst_ctxlst');
+
+ // Adding fields to table tool_dataprivacy_rqst_ctxlst.
+ $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+ $table->add_field('requestid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
+ $table->add_field('contextlistid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
+
+ // Adding keys to table tool_dataprivacy_rqst_ctxlst.
+ $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+ $table->add_key('requestid', XMLDB_KEY_FOREIGN, array('requestid'), 'tool_dataprivacy_request', array('id'));
+ $table->add_key('contextlistid', XMLDB_KEY_FOREIGN, array('contextlistid'), 'tool_dataprivacy_contextlist', array('id'));
+ $table->add_key('request_contextlist', XMLDB_KEY_UNIQUE, array('requestid', 'contextlistid'));
+
+ // Conditionally launch create table for tool_dataprivacy_rqst_ctxlst.
+ if (!$dbman->table_exists($table)) {
+ $dbman->create_table($table);
+ }
+
+ // Define field lawfulbases to be added to tool_dataprivacy_purpose.
+ $table = new xmldb_table('tool_dataprivacy_purpose');
+
+ // It is a required field. We initially define and add it as null and later update it to XMLDB_NOTNULL.
+ $field = new xmldb_field('lawfulbases', XMLDB_TYPE_TEXT, null, null, null, null, null, 'descriptionformat');
+
+ // Conditionally launch add field lawfulbases.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+
+ // Set a kind-of-random value to lawfulbasis field.
+ $DB->set_field('tool_dataprivacy_purpose', 'lawfulbases', 'gdpr_art_6_1_a');
+
+ // We redefine it now as not null.
+ $field = new xmldb_field('lawfulbases', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null, 'descriptionformat');
+
+ // Launch change of nullability for field lawfulbases.
+ $dbman->change_field_notnull($table, $field);
+ }
+
+ // Define field sensitivedatareasons to be added to tool_dataprivacy_purpose.
+ $table = new xmldb_table('tool_dataprivacy_purpose');
+ $field = new xmldb_field('sensitivedatareasons', XMLDB_TYPE_TEXT, null, null, null, null, null, 'lawfulbases');
+
+ // Conditionally launch add field sensitivedatareasons.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+
+ // Dataprivacy savepoint reached.
+ upgrade_plugin_savepoint(true, 2018051405, 'tool', 'dataprivacy');
+ }
+
+ return true;
+}
defined('MOODLE_INTERNAL') || die;
-$plugin->version = 2018051403;
+$plugin->version = 2018051405;
$plugin->requires = 2018050800; // Moodle 3.5dev (Build 2018031600) and upwards.
$plugin->component = 'tool_dataprivacy';
$courseid = required_param('id', PARAM_INT);
$sectionid = optional_param('section', null, PARAM_INT);
$cmid = optional_param('cm', null, PARAM_INT);
+$cancel = optional_param('cancel', '', PARAM_ALPHA);
/**
* Part of the forms in stages after initial, is POST never GET
*/
$PAGE->set_heading($heading);
$renderer = $PAGE->get_renderer('core','backup');
-echo $OUTPUT->header();
+if (empty($cancel)) {
+ // Do not print the header if user cancelled the process, as we are going to redirect the user.
+ echo $OUTPUT->header();
+}
// Prepare a progress bar which can display optionally during long-running
// operations while setting up the UI.
$config->title = get_string('confirmcancel', 'backup');
}
$config->question = get_string('confirmcancelquestion', 'backup');
- $config->yesLabel = get_string('confirmcancelyes', 'backup');
+ $config->yesLabel = $config->title;
$config->noLabel = get_string('confirmcancelno', 'backup');
$config->closeButtonTitle = get_string('close', 'editor');
$PAGE->requires->yui_module(
$url = $component->get_url();
$output = html_writer::start_tag('div', array('class' => 'restore-course-search form-inline m-b-1'));
- $output .= html_writer::start_tag('div', array('class' => 'rcs-results'));
+ $output .= html_writer::start_tag('div', array('class' => 'rcs-results w-75'));
$table = new html_table();
$table->head = array('', get_string('shortnamecourse'), get_string('fullnamecourse'));
$url = $component->get_url();
$output = html_writer::start_tag('div', array('class' => 'restore-course-search form-inline m-b-1'));
- $output .= html_writer::start_tag('div', array('class' => 'rcs-results w-100'));
+ $output .= html_writer::start_tag('div', array('class' => 'rcs-results w-75'));
$table = new html_table();
$table->head = array('', get_string('name'), get_string('description'));
// Detach the listeners for the confirm box so they don't fire again.
new Y.EventHandle(M.core_backup.confirmcancel.listeners).detach();
+ // The currentTarget is a div surrounding the form elements. Simulating a click on the div is
+ // not going to submit a form so we need to find the form element to click.
+ var element = e.currentTarget.one('input, select, button');
+
// Simulate the original cancel button click.
- e.currentTarget.simulate('click');
+ if (element) {
+ element.simulate('click');
+ } else {
+ // Backwards compatibility only.
+ e.currentTarget.simulate('click');
+ }
}, this);
if (!hasLoadedAll(root)) {
// Only enable the button if we've got more events to load.
viewMoreButton.prop('disabled', false);
+ } else {
+ viewMoreButton.addClass('hidden');
}
};
// If there was only one hidden block then we have no more to show now
// so we can disable the button.
if (blocks && blocks.length == 1) {
- button.prop('disabled', true);
+ button.addClass('hidden');
}
if (data) {
if ($DB->record_exists('blog_external', ['userid' => $userid])) {
$sql = "
SELECT ctx.id
- FROM {context}
+ FROM {context} ctx
WHERE ctx.contextlevel = :ctxlevel
AND ctx.instanceid = :ctxuserid";
$params = [
* calendar_set_filters() function now has optional $user parameter.
* The core_calendar\local\event\container class now provides two new helper methods for getting and setting the requesting user:
set_requesting_user() and get_requesting_user().
+* The following functions have been finally deprecated and can not be used anymore:
+ * calendar_preferences_button()
=== 3.5 ===
* core_calendar_external::get_calendar_events now returns the categoryid for category events.
// profilingallowme, profilingallowall, profilinglifetime
// $CFG->earlyprofilingenabled = true;
//
+// Disable database storage for profile data.
+// When using an exernal plugin to store profiling data it is often
+// desirable to not store the data in the database.
+//
+// $CFG->disableprofilingtodatabase = true;
+//
// Force displayed usernames
// A little hack to anonymise user names for all students. If you set these
// then all non-teachers will always see these for every person.
public function get_component_name() {
return 'course';
}
+
+ /**
+ * Returns an icon instance for the document.
+ *
+ * @param \core_search\document $doc
+ * @return \core_search\document_icon
+ */
+ public function get_doc_icon(\core_search\document $doc) : \core_search\document_icon {
+ return new \core_search\document_icon('i/course');
+ }
}
public function get_component_name() {
return 'course';
}
+
+ /**
+ * Returns an icon instance for the document.
+ *
+ * @param \core_search\document $doc
+ * @return \core_search\document_icon
+ */
+ public function get_doc_icon(\core_search\document $doc) : \core_search\document_icon {
+ return new \core_search\document_icon('i/section');
+ }
}
Note that validate_format_options() is now always called when somebody creates or edits course or section and also
during restore and course upload. Default implementation validates against the definition of the form elements for
format options.
+* The final deprecation of xxx_delete_course callback means that this function will no longer be called.
+ Please use the observer for event \core\event\course_content_deleted instead.
=== 3.5 ===
* Course formats should overwrite get_config_for_external function to return the course format settings viewable by the
}
/**
- * Adds the item in course settings navigation to toggle modchooser
- *
- * Theme can overwrite as an empty function to exclude it (for example if theme does not
- * use modchooser at all)
- *
* @deprecated since 3.2
*/
protected function add_modchoosertoggle() {
- debugging('core_course_renderer::add_modchoosertoggle() is deprecated.', DEBUG_DEVELOPER);
-
- global $CFG;
-
- // Only needs to be done once per page.
- if (!$this->page->requires->should_create_one_time_item_now('core_course_modchoosertoggle')) {
- return;
- }
-
- if ($this->page->state > moodle_page::STATE_PRINTING_HEADER ||
- $this->page->course->id == SITEID ||
- !$this->page->user_is_editing() ||
- !($context = context_course::instance($this->page->course->id)) ||
- !has_capability('moodle/course:manageactivities', $context) ||
- !course_ajax_enabled($this->page->course) ||
- !($coursenode = $this->page->settingsnav->find('courseadmin', navigation_node::TYPE_COURSE)) ||
- !($turneditingnode = $coursenode->get('turneditingonoff'))) {
- // Too late, or we are on site page, or we could not find the
- // adjacent nodes in course settings menu, or we are not allowed to edit.
- return;
- }
-
- if ($this->page->url->compare(new moodle_url('/course/view.php'), URL_MATCH_BASE)) {
- // We are on the course page, retain the current page params e.g. section.
- $modchoosertoggleurl = clone($this->page->url);
- } else {
- // Edit on the main course page.
- $modchoosertoggleurl = new moodle_url('/course/view.php', array('id' => $this->page->course->id,
- 'return' => $this->page->url->out_as_local_url(false)));
- }
- $modchoosertoggleurl->param('sesskey', sesskey());
- if ($usemodchooser = get_user_preferences('usemodchooser', $CFG->modchooserdefault)) {
- $modchoosertogglestring = get_string('modchooserdisable', 'moodle');
- $modchoosertoggleurl->param('modchooser', 'off');
- } else {
- $modchoosertogglestring = get_string('modchooserenable', 'moodle');
- $modchoosertoggleurl->param('modchooser', 'on');
- }
- $modchoosertoggle = navigation_node::create($modchoosertogglestring, $modchoosertoggleurl, navigation_node::TYPE_SETTING, null, 'modchoosertoggle');
-
- // Insert the modchoosertoggle after the settings node 'turneditingonoff' (navigation_node only has function to insert before, so we insert before and then swap).
- $coursenode->add_node($modchoosertoggle, 'turneditingonoff');
- $turneditingnode->remove();
- $coursenode->add_node($turneditingnode, 'modchoosertoggle');
-
- $modchoosertoggle->add_class('modchoosertoggle');
- $modchoosertoggle->add_class('visibleifjs');
- user_preference_allow_ajax_update('usemodchooser', PARAM_BOOL);
+ throw new coding_exception('core_course_renderer::add_modchoosertoggle() can not be used anymore.');
}
/**
$this->assertEquals(\core_search\manager::ACCESS_DELETED,
$searcharea->check_access($documents[1]->get('itemid')));
}
+
+ /**
+ * Test document icon for mycourse area.
+ */
+ public function test_get_doc_icon_for_mycourse_area() {
+ $searcharea = \core_search\manager::get_search_area($this->mycoursesareaid);
+
+ $document = $this->getMockBuilder('\core_search\document')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $result = $searcharea->get_doc_icon($document);
+
+ $this->assertEquals('i/course', $result->get_name());
+ $this->assertEquals('moodle', $result->get_component());
+ }
+
+ /**
+ * Test document icon for section area.
+ */
+ public function test_get_doc_icon_for_section_area() {
+ $searcharea = \core_search\manager::get_search_area($this->sectionareaid);
+
+ $document = $this->getMockBuilder('\core_search\document')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $result = $searcharea->get_doc_icon($document);
+
+ $this->assertEquals('i/section', $result->get_name());
+ $this->assertEquals('moodle', $result->get_component());
+ }
}
information provided here is intended especially for developers.
=== 3.5 ===
- * There is a new capability 'moodle/course:forcelanguage' to control which users can force the course
+ * There is a new capability 'moodle/course:setforcedlanguage' to control which users can force the course
language; create_course and update_course functions delegate access control to the caller code; if you
- are calling those functions you may be interested in checking if the logged in user has 'moodle/course:forcelanguage' capability.
+ are calling those functions you may be interested in checking if the logged in user has 'moodle/course:setforcedlanguage' capability.
=== 3.3 ===
defined('MOODLE_INTERNAL') || die();
use core_privacy\local\metadata\collection;
+use core_privacy\local\request\contextlist;
+use core_privacy\local\request\approved_contextlist;
/**
* Data provider class.
*/
class provider implements
\core_privacy\local\metadata\provider,
- \core_privacy\local\request\subsystem\plugin_provider {
+ \core_privacy\local\request\subsystem\plugin_provider,
+
+ // We store a userkey for token-based file access.
+ \core_privacy\local\request\subsystem\provider {
/**
* Returns metadata.
'timemodified' => 'privacy:metadata:files:timemodified',
], 'privacy:metadata:files');
+ $collection->add_subsystem_link('core_userkey', [], 'privacy:metadata:core_userkey');
+
return $collection;
}
+ /**
+ * Get the list of contexts that contain user information for the specified user.
+ *
+ * This is currently just the user context.
+ *
+ * @param int $userid The user to search.
+ * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
+ */
+ public static function get_contexts_for_userid(int $userid) : contextlist {
+ $sql = "SELECT ctx.id
+ FROM {user_private_key} k
+ JOIN {user} u ON k.userid = u.id
+ JOIN {context} ctx ON ctx.instanceid = u.id AND ctx.contextlevel = :contextlevel
+ WHERE k.userid = :userid AND k.script = :script";
+ $params = [
+ 'userid' => $userid,
+ 'contextlevel' => CONTEXT_USER,
+ 'script' => 'core_files',
+ ];
+ $contextlist = new contextlist();
+ $contextlist->add_from_sql($sql, $params);
+
+ return $contextlist;
+ }
+
+ /**
+ * Export all user data for the specified user, in the specified contexts.
+ *
+ * @param approved_contextlist $contextlist The approved contexts to export information for.
+ */
+ public static function export_user_data(approved_contextlist $contextlist) {
+ // If the user has data, then only the CONTEXT_USER should be present so get the first context.
+ $contexts = $contextlist->get_contexts();
+ if (count($contexts) == 0) {
+ return;
+ }
+
+ // Sanity check that context is at the user context level, then get the userid.
+ $context = reset($contexts);
+ if ($context->contextlevel !== CONTEXT_USER) {
+ return;
+ }
+
+ // Export associated userkeys.
+ $subcontext = [
+ get_string('files'),
+ ];
+ \core_userkey\privacy\provider::export_userkeys($context, $subcontext, 'core_files');
+ }
+
+ /**
+ * Delete all use data which matches the specified deletion_criteria.
+ *
+ * @param context $context A user context.
+ */
+ public static function delete_data_for_all_users_in_context(\context $context) {
+ // Sanity check that context is at the user context level, then get the userid.
+ if ($context->contextlevel !== CONTEXT_USER) {
+ return;
+ }
+
+ // Delete all the userkeys.
+ \core_userkey\privacy\provider::delete_userkeys('core_files', $context->instanceid);
+ }
+
+ /**
+ * Delete all user data for the specified user, in the specified contexts.
+ *
+ * @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
+ */
+ public static function delete_data_for_user(approved_contextlist $contextlist) {
+ // If the user has data, then only the user context should be present so get the first context.
+ $contexts = $contextlist->get_contexts();
+ if (count($contexts) == 0) {
+ return;
+ }
+
+ // Sanity check that context is at the user context level, then get the userid.
+ $context = reset($contexts);
+ if ($context->contextlevel !== CONTEXT_USER) {
+ return;
+ }
+
+ // Delete all the userkeys for core_files..
+ \core_userkey\privacy\provider::delete_userkeys('core_files', $context->instanceid);
+ }
}
$string['confirmcancelimport'] = 'Cancel import';
$string['confirmcancelquestion'] = 'Are you sure you wish to cancel?
Any information you have entered will be lost.';
-$string['confirmcancelyes'] = 'Cancel';
-$string['confirmcancelno'] = 'Stay';
+$string['confirmcancelyes'] = 'Cancel backup';
+$string['confirmcancelno'] = 'Do not cancel';
$string['confirmnewcoursecontinue'] = 'New course warning';
$string['confirmnewcoursecontinuequestion'] = 'A temporary (hidden) course will be created by the course restoration process. To abort restoration click cancel. Do not close the browser while restoring.';
$string['coursecategory'] = 'Category the course will be restored into';
extendenrol,core
groupextendenrol,core
virusfounduser,core_antivirus
+formattexttype,core
+currentlyselectedusers,core
+emailuserhasnone,core
+emaildisplayhidden,core
+sitemessage,core
+coursemessage,core
+addedrecip,core
+addedrecips,core
+messagingdisabled,core_message
+messagedselectedcountusersfailed,core
+backtoparticipants,core
+keepsearching,core
+allfieldsrequired,core
+previewhtml,core
+messagedselecteduserfailed,core
$string['privacy:metadata:files:timecreated'] = 'The time when the file was created';
$string['privacy:metadata:files:timemodified'] = 'The time when the file was last modified';
$string['privacy:metadata:files:userid'] = 'The user who created the file';
+$string['privacy:metadata:core_userkey'] = 'A private token is generated and stored. This token can be used to access Moodle files without requiring you to log in.';
$string['errorregistration'] = 'An error occurred during registration, please try again later. ({$a})';
$string['errorunpublishcourses'] = 'Due to an unexpected error, the courses could not be deleted from Moodle.net. Try again later (recommended) or contact Moodle.net administrator.';
$string['errorws'] = '{$a}';
+$string['errorwstokenreset'] = '{$a}. Registration token on this site has been reset. You can now register your site again.';
$string['existingscreenshotnumber'] = '{$a} existing screenshots. You will be able to see these screenshots on this page, only once the Moodle.net administrator enables your course.';
$string['errorregistrationupdate'] = 'An error occurred during registration update ({$a})';
$string['existingscreenshots'] = 'Existing screenshots';
$string['updatesite'] = 'Update registration on {$a}';
$string['updatestatus'] = 'Check it now.';
$string['usedifferentemail'] = 'Use different email';
+$string['unregisterexplained'] = 'If the site with URL {$a} is registered on Moodle.net its registration will be removed.';
$string['urlalreadyregistered'] = 'Your site seems to be already registered on Moodle.net, which means something has gone wrong. Please contact the Moodle.net administrator to reset your registration so you can try again.';
$string['usersnumber'] = 'Number of users ({$a})';
$string['wrongtoken'] = 'The registration failed for some unknown reason (network?). Please try again.';
$string['messagepreferences'] = 'Message preferences';
$string['messages'] = 'Messages';
$string['messagingdatahasnotbeenmigrated'] = 'Your messages are temporarily unavailable due to upgrades in the messaging infrastructure. Please wait for them to be migrated.';
-$string['messagingdisabled'] = 'Messaging is disabled on this site, emails will be sent instead';
$string['newonlymsg'] = 'Show only new';
$string['newmessage'] = 'New message';
$string['newmessagesearch'] = 'Select or search for a contact to send a new message.';
$string['viewunreadmessageswith'] = 'View unread messages with {$a}';
$string['writeamessage'] = 'Write a message...';
$string['you'] = 'You:';
+
+// Deprecated since Moodle 3.6.
+$string['messagingdisabled'] = 'Messaging is disabled on this site, emails will be sent instead';
$string['addcreator'] = 'Add course creator';
$string['adddots'] = 'Add...';
$string['added'] = 'Added {$a}';
-$string['addedrecip'] = 'Added {$a} new recipient';
-$string['addedrecips'] = 'Added {$a} new recipients';
$string['addedtogroup'] = 'Added to group "{$a}"';
$string['addedtogroupnot'] = 'Not added to group "{$a}"';
$string['addedtogroupnotenrolled'] = 'Not added to group "{$a}", because not enrolled in course';
$string['allactivities'] = 'All activities';
$string['allcategories'] = 'All categories';
$string['alldays'] = 'All days';
-$string['allfieldsrequired'] = 'All fields are required';
$string['allfiles'] = 'All files';
$string['allgroups'] = 'All groups';
$string['allchanges'] = 'All changes';
$string['backtocourselisting'] = 'Back to course listing';
$string['backtohome'] = 'Back to the site home';
$string['backtopageyouwereon'] = 'Back to the page you were on';
-$string['backtoparticipants'] = 'Back to participants list';
$string['backup'] = 'Backup';
$string['backupactivehelp'] = 'Choose whether or not to do automated backups.';
$string['backupcancelled'] = 'Backup cancelled';
$string['courseoverviewfileslimit'] = 'Course summary files limit';
$string['courseoverviewfiles_help'] = 'Course summary files, such as images, are displayed in the list of courses together with the summary.';
$string['courseinfo'] = 'Course info';
-$string['coursemessage'] = 'Message course users';
$string['coursenotaccessible'] = 'This course does not allow public access';
$string['courselegacyfiles'] = 'Legacy course files';
$string['courselegacyfiles_help'] = 'The course files area provides some backward compatibility with Moodle 1.9 and earlier. All files in this area are always accessible to all participants in the course (whether you link to them or not) and there is no way to know where any of these files are being used in Moodle.
$string['currentcoursedeleting'] = 'Current course, deleting it first';
$string['currentlanguage'] = 'Current language';
$string['currentlocaltime'] = 'your current local time';
-$string['currentlyselectedusers'] = 'Currently selected users';
$string['currentpicture'] = 'Current picture';
$string['currentrelease'] = 'Current release information';
$string['currentversion'] = 'Current version';
$string['emaildisplay'] = 'Email display';
$string['emaildisplay_help'] = 'Privileged users (such as teachers and managers) will always be able to see your email address.';
$string['emaildisplaycourse'] = 'Allow only other course members to see my email address';
-$string['emaildisplayhidden'] = 'Email hidden';
$string['emaildisplayno'] = 'Hide my email address from non-privileged users';
$string['emaildisplayyes'] = 'Allow everyone to see my email address';
$string['emailenable'] = 'This email address is enabled';
If you continue to have difficulty, contact the site administrator.';
$string['emailtoprivatefiles'] = 'You can also e-mail files as attachments straight to your private files space. Simply attach your files to an e-mail and send it to {$a}';
$string['emailtoprivatefilesdenied'] = 'Your administrator has disabled the option to upload your own private files.';
-$string['emailuserhasnone'] = 'There is no email address for the user.';
$string['emailvia'] = '{$a->name} (via {$a->siteshortname})';
$string['emptydragdropregion'] = 'empty region';
$string['enable'] = 'Enable';
$string['formatmarkdown'] = 'Markdown format';
$string['formatplain'] = 'Plain text format';
$string['formattext'] = 'Moodle auto-format';
-$string['formattexttype'] = 'Formatting';
$string['forumpreferences'] = 'Forum preferences';
$string['framesetinfo'] = 'This frameset document contains:';
$string['from'] = 'From';
$string['jump'] = 'Jump';
$string['jumpto'] = 'Jump to...';
$string['keep'] = 'Keep';
-$string['keepsearching'] = 'Keep searching';
$string['langltr'] = 'Language direction left-to-right';
$string['langrtl'] = 'Language direction right-to-left';
$string['language'] = 'Language';
$string['memberincourse'] = 'People in the course';
$string['messagebody'] = 'Message body';
$string['messagedselectedusers'] = 'Selected users have been messaged and the recipient list has been reset.';
-$string['messagedselecteduserfailed'] = 'The message was not sent to user {$a->fullname}.';
$string['messagedselectedusersfailed'] = 'Something went wrong while messaging selected users. Some may have received the email.';
-$string['messagedselectedcountusersfailed'] = 'A problem occurred and {$a} messages have not been sent.';
$string['messageprovider:availableupdate'] = 'Available update notifications';
$string['messageprovider:backup'] = 'Backup notifications';
$string['messageprovider:badgecreatornotice'] = 'Badge creator notifications';
$string['preprocessingbackupfile'] = 'Preprocessing backup file';
$string['prev'] = 'Prev';
$string['preview'] = 'Preview';
-$string['previewhtml'] = 'HTML format preview';
$string['previeworchoose'] = 'Preview or choose a theme';
$string['previous'] = 'Previous';
$string['previouslyselectedusers'] = 'Previously selected users not matching \'{$a}\'';
$string['sitehome'] = 'Site home';
$string['sitelegacyfiles'] = 'Legacy site files';
$string['sitelogs'] = 'Site logs';
-$string['sitemessage'] = 'Message users';
$string['sitenews'] = 'Site announcements';
$string['sitepages'] = 'Site pages';
$string['sitepartlist'] = 'You do not have the required permissions to view the participants list';
$string['url'] = 'URL';
$string['used'] = 'Used';
$string['usedinnplaces'] = 'Used in {$a} places';
-$string['usemessageform'] = 'or use the form below to send a message to the selected students';
$string['user'] = 'User';
$string['useraccount'] = 'User account';
$string['userconfirmed'] = 'Confirmed {$a}';
$string['publish'] = 'Publish';
$string['extendenrol'] = 'Extend enrolment (individual)';
$string['groupextendenrol'] = 'Extend enrolment (common)';
+
+// Deprecated since Moodle 3.6.
+$string['addedrecip'] = 'Added {$a} new recipient';
+$string['addedrecips'] = 'Added {$a} new recipients';
+$string['allfieldsrequired'] = 'All fields are required';
+$string['backtoparticipants'] = 'Back to participants list';
+$string['currentlyselectedusers'] = 'Currently selected users';
+$string['coursemessage'] = 'Message course users';
+$string['emaildisplayhidden'] = 'Email hidden';
+$string['emailuserhasnone'] = 'There is no email address for the user.';
+$string['formattexttype'] = 'Formatting';
+$string['keepsearching'] = 'Keep searching';
+$string['messagedselectedcountusersfailed'] = 'A problem occurred and {$a} messages have not been sent.';
+$string['messagedselecteduserfailed'] = 'The message was not sent to user {$a->fullname}.';
+$string['previewhtml'] = 'HTML format preview';
+$string['sitemessage'] = 'Message users';
* Gets the list of roles assigned to this context and up (parents)
*
* @param context $context
+ * @param boolean $includeparents, false means without parents.
* @return array
*/
-function get_roles_used_in_context(context $context) {
+function get_roles_used_in_context(context $context, $includeparents = true) {
global $DB;
- list($contextlist, $params) = $DB->get_in_or_equal($context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'cl');
+ if ($includeparents === true) {
+ list($contextlist, $params) = $DB->get_in_or_equal($context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'cl');
+ } else {
+ list($contextlist, $params) = $DB->get_in_or_equal($context->id, SQL_PARAMS_NAMED, 'cl');
+ }
if ($coursecontext = $context->get_course_context(false)) {
$params['coursecontext'] = $coursecontext->id;
return empty($courses) ? false : $courses;
}
-/**
- * This function finds the roles assigned directly to this context only
- * i.e. no roles in parent contexts
- *
- * @param context $context
- * @return array
- */
-function get_roles_on_exact_context(context $context) {
- global $DB;
-
- return $DB->get_records_sql("SELECT r.*
- FROM {role_assignments} ra, {role} r
- WHERE ra.roleid = r.id AND ra.contextid = ?",
- array($context->id));
-}
-
/**
* Switches the current user to another role for the current session and only
* in the given context.
array($context->id, $role->id));
}
-/**
- * Find out which roles has assignment on this context
- *
- * @param context $context
- * @return array
- *
- */
-function get_roles_with_assignment_on_context(context $context) {
- global $DB;
-
- return $DB->get_records_sql("SELECT r.*
- FROM {role_assignments} ra, {role} r
- WHERE ra.roleid = r.id AND ra.contextid = ?",
- array($context->id));
-}
-
/**
* Find all user assignment of users for this role, on this context
*
class message_sent extends base {
/**
* Create event using ids.
- * @todo MDL-55449 Make $courseid mandatory in Moodle 3.6
* @param int $userfromid
* @param int $usertoid
* @param int $messageid
- * @param int|null $courseid course id the event is related with. Use SITEID if no relation exists.
+ * @param int $courseid course id the event is related with.
* @return message_sent
*/
- public static function create_from_ids($userfromid, $usertoid, $messageid, $courseid = null) {
+ public static function create_from_ids(int $userfromid, int $usertoid, int $messageid, int $courseid) {
// We may be sending a message from the 'noreply' address, which means we are not actually sending a
// message from a valid user. In this case, we will set the userid to 0.
// Check if the userid is valid.
$userfromid = 0;
}
- // TODO: MDL-55449 Make $courseid mandatory in Moodle 3.6.
- if (is_null($courseid)) {
- // Arrived here with not defined $courseid to associate the event with.
- // Let's default to SITEID and perform debugging so devs are aware. MDL-47162.
- $courseid = SITEID;
- debugging('message_sent::create_from_ids() needs a $courseid to be passed, nothing was detected. Please, change ' .
- 'the call to include it, using SITEID if the message is unrelated to any real course.', DEBUG_DEVELOPER);
- }
-
$event = self::create(array(
'objectid' => $messageid,
'userid' => $userfromid,
$curloutput = @json_decode($curl->get($serverurl, $params), true);
$info = $curl->get_info();
if ($curl->get_errno()) {
+ // Connection error.
throw new moodle_exception('errorconnect', 'hub', '', $curl->error);
} else if (isset($curloutput['exception'])) {
- // Error message returned by web service.
- throw new moodle_exception('errorws', 'hub', '', $curloutput['message']);
+ // Exception occurred on moodle.net .
+ self::process_curl_exception($token, $curloutput);
} else if ($info['http_code'] != 200) {
throw new moodle_exception('errorconnect', 'hub', '', $info['http_code']);
} else {
}
}
+ /**
+ * Analyses exception received from moodle.net
+ *
+ * @param string $token token used for CURL request
+ * @param array $curloutput output from CURL request
+ * @throws moodle_exception
+ */
+ protected static function process_curl_exception($token, $curloutput) {
+ if (!isset($curloutput['exception'])) {
+ return;
+ }
+ if ($token === registration::get_token()) {
+ // Check if registration token was rejected or there are other problems with registration.
+ if (($curloutput['exception'] === 'moodle_exception' && $curloutput['errorcode'] === 'invalidtoken')
+ || $curloutput['exception'] === 'registration_exception') {
+ // Force admin to repeat site registration process.
+ registration::reset_token();
+ throw new moodle_exception('errorwstokenreset', 'hub', '', $curloutput['message']);
+ }
+ }
+ throw new moodle_exception('errorws', 'hub', '', $curloutput['message']);
+ }
+
/**
* Update site registration on moodle.net
*
* @throws moodle_exception
*/
public static function update_registration(array $siteinfo) {
- $params = array('siteinfo' => $siteinfo);
+ $params = array('siteinfo' => $siteinfo, 'validateurl' => 1);
self::call('hub_update_site_info', $params);
}
* @throws moodle_exception
*/
public static function unregister_site() {
- self::call('hub_unregister_site');
+ global $CFG;
+ self::call('hub_unregister_site', ['url' => [$CFG->wwwroot]]);
}
/**
try {
api::update_registration($siteinfo);
} catch (moodle_exception $e) {
+ if (!self::is_registered()) {
+ // Token was rejected during registration update and site and locally stored token was reset,
+ // proceed to site registration. This method will redirect away.
+ self::register('');
+ }
\core\notification::add(get_string('errorregistrationupdate', 'hub', $e->getMessage()),
\core\output\notification::NOTIFY_ERROR);
return false;
return true;
}
+ /**
+ * Resets the registration token without changing site identifier so site can be re-registered
+ *
+ * @return bool
+ */
+ public static function reset_token() {
+ global $DB;
+ if (!$hub = self::get_registration()) {
+ return true;
+ }
+ $DB->delete_records('registration_hubs', array('id' => $hub->id));
+ self::$registration = null;
+ }
+
/**
* Generate a new token for the site that is not registered
*
* Form definition
*/
public function definition() {
+ global $CFG;
$mform = & $this->_form;
$mform->addElement('header', 'site', get_string('unregister', 'hub'));
$mform->addElement('hidden', 'unregistration', 1);
$mform->setType('unregistration', PARAM_INT);
+ $mform->addElement('static', 'explanation', '', get_string('unregisterexplained', 'hub', $CFG->wwwroot));
+
$this->add_action_buttons(true, $unregisterlabel);
}
}
*
* NOTE: to be used from message_send() only.
*
- * @todo MDL-55449 Drop support for stdClass in Moodle 3.6
* @param \core\message\message $eventdata fully prepared event data for processors
* @param \stdClass $savemessage the message saved in 'message' table
* @param array $processorlist list of processors for target user
* @return int $messageid the id from 'messages' (false is not returned)
*/
- public static function send_message($eventdata, \stdClass $savemessage, array $processorlist) {
+ public static function send_message(message $eventdata, \stdClass $savemessage, array $processorlist) {
global $CFG;
- // TODO MDL-55449 Drop support for stdClass in Moodle 3.6.
- if (!($eventdata instanceof \stdClass) && !($eventdata instanceof message)) {
- // Not a valid object.
- throw new \coding_exception('Message should be of type stdClass or \core\message\message');
- }
-
- // TODO MDL-55449 Drop support for stdClass in Moodle 3.6.
- if ($eventdata instanceof \stdClass) {
- if (!isset($eventdata->courseid)) {
- $eventdata->courseid = null;
- }
-
- debugging('eventdata as \stdClass is deprecated. Please use \core\message\message instead.', DEBUG_DEVELOPER);
- }
-
require_once($CFG->dirroot.'/message/lib.php'); // This is most probably already included from messagelib.php file.
if (empty($processorlist)) {
/**
* Prints a basic textarea field.
*
- * @deprecated since Moodle 2.0
+ * This was 'deprecated' in 2.0, but not properly (there was no alternative) so the
+ * debugging message was commented out.
+ *
+ * @deprecated since Moodle 3.6
*
* When using this function, you should
*
/// However, you can set them to zero to override the mincols and minrows values below.
// Disabling because there is not yet a viable $OUTPUT option for cases when mforms can't be used
- // debugging('print_textarea() has been deprecated. You should be using mforms and the editor element.');
+ debugging('print_textarea() is deprecated. Please use $OUTPUT->print_textarea() instead.', DEBUG_DEVELOPER);
- global $CFG;
+ global $OUTPUT;
$mincols = 65;
$minrows = 10;
- $str = '';
if ($id === '') {
$id = 'edit-'.$name;
$cols = $mincols;
}
- editors_head_setup();
- $editor = editors_get_preferred_editor(FORMAT_HTML);
- $editor->set_text($value);
- $editor->use_editor($id, array('legacy'=>true));
-
- $str .= "\n".'<textarea class="form-textarea" id="'. $id .'" name="'. $name .'" rows="'. $rows .'" cols="'. $cols .'" spellcheck="true">'."\n";
- $str .= htmlspecialchars($value); // needed for editing of cleaned text!
- $str .= '</textarea>'."\n";
-
+ $textarea = $OUTPUT->print_textarea($name, $id, $value, $rows, $cols);
if ($return) {
- return $str;
+ return $textarea;
}
- echo $str;
+
+ echo $textarea;
}
/**
}
/**
- * Prints the 'update this xxx' button that appears on module pages.
- *
* @deprecated since Moodle 3.2
- *
- * @param string $cmid the course_module id.
- * @param string $ignored not used any more. (Used to be courseid.)
- * @param string $string the module name - get_string('modulename', 'xxx')
- * @return string the HTML for the button, if this user has permission to edit it, else an empty string.
*/
-function update_module_button($cmid, $ignored, $string) {
- global $CFG, $OUTPUT;
-
- debugging('update_module_button() has been deprecated and should not be used anymore. Activity modules should not add the ' .
- 'edit module button, the link is already available in the Administration block. Themes can choose to display the link ' .
- 'in the buttons row consistently for all module types.', DEBUG_DEVELOPER);
-
- if (has_capability('moodle/course:manageactivities', context_module::instance($cmid))) {
- $string = get_string('updatethis', '', $string);
-
- $url = new moodle_url("$CFG->wwwroot/course/mod.php", array('update' => $cmid, 'return' => true, 'sesskey' => sesskey()));
- return $OUTPUT->single_button($url, $string);
- } else {
- return '';
- }
+function update_module_button() {
+ throw new coding_exception('update_module_button() can not be used anymore. Activity modules should ' .
+ 'not add the edit module button, the link is already available in the Administration block. Themes ' .
+ 'can choose to display the link in the buttons row consistently for all module types.');
}
/**
}
/**
- * Retrieves an array of records from a CSV file and places
- * them into a given table structure
- * This function is deprecated. Please use csv_import_reader() instead.
- *
- * @deprecated since Moodle 3.2 MDL-55126
- * @todo MDL-55195 for final deprecation in Moodle 3.6
+ * @deprecated since Moodle 3.2
* @see csv_import_reader::load_csv_content()
- * @global stdClass $CFG
- * @global moodle_database $DB
- * @param string $file The path to a CSV file
- * @param string $table The table to retrieve columns from
- * @return bool|array Returns an array of CSV records or false
*/
-function get_records_csv($file, $table) {
- global $CFG, $DB;
-
- debugging('get_records_csv() is deprecated. Please use lib/csvlib.class.php csv_import_reader() instead.');
-
- if (!$metacolumns = $DB->get_columns($table)) {
- return false;
- }
-
- if(!($handle = @fopen($file, 'r'))) {
- print_error('get_records_csv failed to open '.$file);
- }
-
- $fieldnames = fgetcsv($handle, 4096);
- if(empty($fieldnames)) {
- fclose($handle);
- return false;
- }
-
- $columns = array();
-
- foreach($metacolumns as $metacolumn) {
- $ord = array_search($metacolumn->name, $fieldnames);
- if(is_int($ord)) {
- $columns[$metacolumn->name] = $ord;
- }
- }
-
- $rows = array();
-
- while (($data = fgetcsv($handle, 4096)) !== false) {
- $item = new stdClass;
- foreach($columns as $name => $ord) {
- $item->$name = $data[$ord];
- }
- $rows[] = $item;
- }
-
- fclose($handle);
- return $rows;
-}
-
-/**
- * Create a file with CSV contents
- * This function is deprecated. Please use download_as_dataformat() instead.
- *
- * @deprecated since Moodle 3.2 MDL-55126
- * @todo MDL-55195 for final deprecation in Moodle 3.6
- * @see download_as_dataformat (lib/dataformatlib.php)
- * @global stdClass $CFG
- * @global moodle_database $DB
- * @param string $file The file to put the CSV content into
- * @param array $records An array of records to write to a CSV file
- * @param string $table The table to get columns from
- * @return bool success
- */
-function put_records_csv($file, $records, $table = NULL) {
- global $CFG, $DB;
-
- debugging('put_records_csv() is deprecated. Please use lib/dataformatlib.php download_as_dataformat()');
-
- if (empty($records)) {
- return true;
- }
-
- $metacolumns = NULL;
- if ($table !== NULL && !$metacolumns = $DB->get_columns($table)) {
- return false;
- }
-
- echo "x";
-
- if(!($fp = @fopen($CFG->tempdir.'/'.$file, 'w'))) {
- print_error('put_records_csv failed to open '.$file);
- }
-
- $proto = reset($records);
- if(is_object($proto)) {
- $fields_records = array_keys(get_object_vars($proto));
- }
- else if(is_array($proto)) {
- $fields_records = array_keys($proto);
- }
- else {
- return false;
- }
- echo "x";
-
- if(!empty($metacolumns)) {
- $fields_table = array_map(create_function('$a', 'return $a->name;'), $metacolumns);
- $fields = array_intersect($fields_records, $fields_table);
- }
- else {
- $fields = $fields_records;
- }
-
- fwrite($fp, implode(',', $fields));
- fwrite($fp, "\r\n");
-
- foreach($records as $record) {
- $array = (array)$record;
- $values = array();
- foreach($fields as $field) {
- if(strpos($array[$field], ',')) {
- $values[] = '"'.str_replace('"', '\"', $array[$field]).'"';
- }
- else {
- $values[] = $array[$field];
- }
- }
- fwrite($fp, implode(',', $values)."\r\n");
- }
-
- fclose($fp);
- @chmod($CFG->tempdir.'/'.$file, $CFG->filepermissions);
- return true;
+function get_records_csv() {
+ throw new coding_exception('get_records_csv() can not be used anymore. Please use ' .
+ 'lib/csvlib.class.php csv_import_reader() instead.');
}
/**
- * Determines if the given value is a valid CSS colour.
- *
- * A CSS colour can be one of the following:
- * - Hex colour: #AA66BB
- * - RGB colour: rgb(0-255, 0-255, 0-255)
- * - RGBA colour: rgba(0-255, 0-255, 0-255, 0-1)
- * - HSL colour: hsl(0-360, 0-100%, 0-100%)
- * - HSLA colour: hsla(0-360, 0-100%, 0-100%, 0-1)
- *
- * Or a recognised browser colour mapping {@link css_optimiser::$htmlcolours}
- *
* @deprecated since Moodle 3.2
- * @todo MDL-56173 for final deprecation in Moodle 3.6
- * @param string $value The colour value to check
- * @return bool
+ * @see download_as_dataformat (lib/dataformatlib.php)
*/
-function css_is_colour($value) {
- debugging('css_is_colour() is deprecated without a replacement. Please copy the implementation '.
- 'into your plugin if you need this functionality.', DEBUG_DEVELOPER);
-
- $value = trim($value);
-
- $hex = '/^#([a-fA-F0-9]{1,3}|[a-fA-F0-9]{6})$/';
- $rgb = '#^rgb\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$#i';
- $rgba = '#^rgba\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1}(\.\d+)?)\s*\)$#i';
- $hsl = '#^hsl\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\%\s*,\s*(\d{1,3})\%\s*\)$#i';
- $hsla = '#^hsla\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\%\s*,\s*(\d{1,3})\%\s*,\s*(\d{1}(\.\d+)?)\s*\)$#i';
-
- if (in_array(strtolower($value), array('inherit'))) {
- return true;
- } else if (preg_match($hex, $value)) {
- return true;
- } else if (in_array(strtolower($value), array_keys(css_optimiser::$htmlcolours))) {
- return true;
- } else if (preg_match($rgb, $value, $m) && $m[1] < 256 && $m[2] < 256 && $m[3] < 256) {
- // It is an RGB colour.
- return true;
- } else if (preg_match($rgba, $value, $m) && $m[1] < 256 && $m[2] < 256 && $m[3] < 256) {
- // It is an RGBA colour.
- return true;
- } else if (preg_match($hsl, $value, $m) && $m[1] <= 360 && $m[2] <= 100 && $m[3] <= 100) {
- // It is an HSL colour.
- return true;
- } else if (preg_match($hsla, $value, $m) && $m[1] <= 360 && $m[2] <= 100 && $m[3] <= 100) {
- // It is an HSLA colour.
- return true;
- }
- // Doesn't look like a colour.
- return false;
+function put_records_csv() {
+ throw new coding_exception('put_records_csv() can not be used anymore. Please use ' .
+ 'lib/dataformatlib.php download_as_dataformat() instead.');
}
/**
- * Returns true is the passed value looks like a CSS width.
- * In order to pass this test the value must be purely numerical or end with a
- * valid CSS unit term.
- *
- * @param string|int $value
- * @return boolean
* @deprecated since Moodle 3.2
- * @todo MDL-56173 for final deprecation in Moodle 3.6
*/
-function css_is_width($value) {
- debugging('css_is_width() is deprecated without a replacement. Please copy the implementation '.
- 'into your plugin if you need this functionality.', DEBUG_DEVELOPER);
-
- $value = trim($value);
- if (in_array(strtolower($value), array('auto', 'inherit'))) {
- return true;
- }
- if ((string)$value === '0' || preg_match('#^(\-\s*)?(\d*\.)?(\d+)\s*(em|px|pt|\%|in|cm|mm|ex|pc)$#i', $value)) {
- return true;
- }
- return false;
+function css_is_colour() {
+ throw new coding_exception('css_is_colour() can not be used anymore.');
}
/**
- * A simple sorting function to sort two array values on the number of items they contain
- *
- * @param array $a
- * @param array $b
- * @return int
* @deprecated since Moodle 3.2
- * @todo MDL-56173 for final deprecation in Moodle 3.6
*/
-function css_sort_by_count(array $a, array $b) {
- debugging('css_sort_by_count() is deprecated without a replacement. Please copy the implementation '.
- 'into your plugin if you need this functionality.', DEBUG_DEVELOPER);
-
- $a = count($a);
- $b = count($b);
- if ($a == $b) {
- return 0;
- }
- return ($a > $b) ? -1 : 1;
+function css_is_width() {
+ throw new coding_exception('css_is_width() can not be used anymore.');
}
/**
- * A basic CSS optimiser that strips out unwanted things and then processes CSS organising and cleaning styles.
* @deprecated since Moodle 3.2
- * @todo MDL-56173 for final deprecation in Moodle 3.6
- */
-class css_optimiser {
- /**
- * An array of the common HTML colours that are supported by most browsers.
- *
- * This reference table is used to allow us to unify colours, and will aid
- * us in identifying buggy CSS using unsupported colours.
- *
- * @var string[]
- * @deprecated since Moodle 3.2
- * @todo MDL-56173 for final deprecation in Moodle 3.6
- */
- public static $htmlcolours = array(
- 'aliceblue' => '#F0F8FF',
- 'antiquewhite' => '#FAEBD7',
- 'aqua' => '#00FFFF',
- 'aquamarine' => '#7FFFD4',
- 'azure' => '#F0FFFF',
- 'beige' => '#F5F5DC',
- 'bisque' => '#FFE4C4',
- 'black' => '#000000',
- 'blanchedalmond' => '#FFEBCD',
- 'blue' => '#0000FF',
- 'blueviolet' => '#8A2BE2',
- 'brown' => '#A52A2A',
- 'burlywood' => '#DEB887',
- 'cadetblue' => '#5F9EA0',
- 'chartreuse' => '#7FFF00',
- 'chocolate' => '#D2691E',
- 'coral' => '#FF7F50',
- 'cornflowerblue' => '#6495ED',
- 'cornsilk' => '#FFF8DC',
- 'crimson' => '#DC143C',
- 'cyan' => '#00FFFF',
- 'darkblue' => '#00008B',
- 'darkcyan' => '#008B8B',
- 'darkgoldenrod' => '#B8860B',
- 'darkgray' => '#A9A9A9',
- 'darkgrey' => '#A9A9A9',
- 'darkgreen' => '#006400',
- 'darkKhaki' => '#BDB76B',
- 'darkmagenta' => '#8B008B',
- 'darkolivegreen' => '#556B2F',
- 'arkorange' => '#FF8C00',
- 'darkorchid' => '#9932CC',
- 'darkred' => '#8B0000',
- 'darksalmon' => '#E9967A',
- 'darkseagreen' => '#8FBC8F',
- 'darkslateblue' => '#483D8B',
- 'darkslategray' => '#2F4F4F',
- 'darkslategrey' => '#2F4F4F',
- 'darkturquoise' => '#00CED1',
- 'darkviolet' => '#9400D3',
- 'deeppink' => '#FF1493',
- 'deepskyblue' => '#00BFFF',
- 'dimgray' => '#696969',
- 'dimgrey' => '#696969',
- 'dodgerblue' => '#1E90FF',
- 'firebrick' => '#B22222',
- 'floralwhite' => '#FFFAF0',
- 'forestgreen' => '#228B22',
- 'fuchsia' => '#FF00FF',
- 'gainsboro' => '#DCDCDC',
- 'ghostwhite' => '#F8F8FF',
- 'gold' => '#FFD700',
- 'goldenrod' => '#DAA520',
- 'gray' => '#808080',
- 'grey' => '#808080',
- 'green' => '#008000',
- 'greenyellow' => '#ADFF2F',
- 'honeydew' => '#F0FFF0',
- 'hotpink' => '#FF69B4',
- 'indianred ' => '#CD5C5C',
- 'indigo ' => '#4B0082',
- 'ivory' => '#FFFFF0',
- 'khaki' => '#F0E68C',
- 'lavender' => '#E6E6FA',
- 'lavenderblush' => '#FFF0F5',
- 'lawngreen' => '#7CFC00',
- 'lemonchiffon' => '#FFFACD',
- 'lightblue' => '#ADD8E6',
- 'lightcoral' => '#F08080',
- 'lightcyan' => '#E0FFFF',
- 'lightgoldenrodyellow' => '#FAFAD2',
- 'lightgray' => '#D3D3D3',
- 'lightgrey' => '#D3D3D3',
- 'lightgreen' => '#90EE90',
- 'lightpink' => '#FFB6C1',
- 'lightsalmon' => '#FFA07A',
- 'lightseagreen' => '#20B2AA',
- 'lightskyblue' => '#87CEFA',
- 'lightslategray' => '#778899',
- 'lightslategrey' => '#778899',
- 'lightsteelblue' => '#B0C4DE',
- 'lightyellow' => '#FFFFE0',
- 'lime' => '#00FF00',
- 'limegreen' => '#32CD32',
- 'linen' => '#FAF0E6',
- 'magenta' => '#FF00FF',
- 'maroon' => '#800000',
- 'mediumaquamarine' => '#66CDAA',
- 'mediumblue' => '#0000CD',
- 'mediumorchid' => '#BA55D3',
- 'mediumpurple' => '#9370D8',
- 'mediumseagreen' => '#3CB371',
- 'mediumslateblue' => '#7B68EE',
- 'mediumspringgreen' => '#00FA9A',
- 'mediumturquoise' => '#48D1CC',
- 'mediumvioletred' => '#C71585',
- 'midnightblue' => '#191970',
- 'mintcream' => '#F5FFFA',
- 'mistyrose' => '#FFE4E1',
- 'moccasin' => '#FFE4B5',
- 'navajowhite' => '#FFDEAD',
- 'navy' => '#000080',
- 'oldlace' => '#FDF5E6',
- 'olive' => '#808000',
- 'olivedrab' => '#6B8E23',
- 'orange' => '#FFA500',
- 'orangered' => '#FF4500',
- 'orchid' => '#DA70D6',
- 'palegoldenrod' => '#EEE8AA',
- 'palegreen' => '#98FB98',
- 'paleturquoise' => '#AFEEEE',
- 'palevioletred' => '#D87093',
- 'papayawhip' => '#FFEFD5',
- 'peachpuff' => '#FFDAB9',
- 'peru' => '#CD853F',
- 'pink' => '#FFC0CB',
- 'plum' => '#DDA0DD',
- 'powderblue' => '#B0E0E6',
- 'purple' => '#800080',
- 'red' => '#FF0000',
- 'rosybrown' => '#BC8F8F',
- 'royalblue' => '#4169E1',
- 'saddlebrown' => '#8B4513',
- 'salmon' => '#FA8072',
- 'sandybrown' => '#F4A460',
- 'seagreen' => '#2E8B57',
- 'seashell' => '#FFF5EE',
- 'sienna' => '#A0522D',
- 'silver' => '#C0C0C0',
- 'skyblue' => '#87CEEB',
- 'slateblue' => '#6A5ACD',
- 'slategray' => '#708090',
- 'slategrey' => '#708090',
- 'snow' => '#FFFAFA',
- 'springgreen' => '#00FF7F',
- 'steelblue' => '#4682B4',
- 'tan' => '#D2B48C',
- 'teal' => '#008080',
- 'thistle' => '#D8BFD8',
- 'tomato' => '#FF6347',
- 'transparent' => 'transparent',
- 'turquoise' => '#40E0D0',
- 'violet' => '#EE82EE',
- 'wheat' => '#F5DEB3',
- 'white' => '#FFFFFF',
- 'whitesmoke' => '#F5F5F5',
- 'yellow' => '#FFFF00',
- 'yellowgreen' => '#9ACD32'
- );
-
- /**
- * Used to orocesses incoming CSS optimising it and then returning it. Now just returns
- * what is sent to it. Do not use.
- *
- * @param string $css The raw CSS to optimise
- * @return string The optimised CSS
- * @deprecated since Moodle 3.2
- * @todo MDL-56173 for final deprecation in Moodle 3.6
- */
- public function process($css) {
- debugging('class css_optimiser is deprecated and no longer does anything, '.
- 'please consider using stylelint to optimise your css.', DEBUG_DEVELOPER);
-
- return $css;
- }
+ */
+function css_sort_by_count() {
+ throw new coding_exception('css_sort_by_count() can not be used anymore.');
}
/**
- * Load the course contexts for all of the users courses
- *
* @deprecated since Moodle 3.2
- * @param array $courses array of course objects. The courses the user is enrolled in.
- * @return array of course contexts
*/
-function message_get_course_contexts($courses) {
- debugging('message_get_course_contexts() is deprecated and is no longer used.', DEBUG_DEVELOPER);
-
- $coursecontexts = array();
-
- foreach($courses as $course) {
- $coursecontexts[$course->id] = context_course::instance($course->id);
- }
-
- return $coursecontexts;
+function message_get_course_contexts() {
+ throw new coding_exception('message_get_course_contexts() can not be used anymore.');
}
/**
- * strip off action parameters like 'removecontact'
- *
* @deprecated since Moodle 3.2
- * @param moodle_url/string $moodleurl a URL. Typically the current page URL.
- * @return string the URL minus parameters that perform actions (like adding/removing/blocking a contact).
*/
-function message_remove_url_params($moodleurl) {
- debugging('message_remove_url_params() is deprecated and is no longer used.', DEBUG_DEVELOPER);
-
- $newurl = new moodle_url($moodleurl);
- $newurl->remove_params('addcontact','removecontact','blockcontact','unblockcontact');
- return $newurl->out();
+function message_remove_url_params() {
+ throw new coding_exception('message_remove_url_params() can not be used anymore.');
}
/**
- * Count the number of messages with a field having a specified value.
- * if $field is empty then return count of the whole array
- * if $field is non-existent then return 0
- *
* @deprecated since Moodle 3.2
- * @param array $messagearray array of message objects
- * @param string $field the field to inspect on the message objects
- * @param string $value the value to test the field against
*/
-function message_count_messages($messagearray, $field='', $value='') {
- debugging('message_count_messages() is deprecated and is no longer used.', DEBUG_DEVELOPER);
-
- if (!is_array($messagearray)) return 0;
- if ($field == '' or empty($messagearray)) return count($messagearray);
-
- $count = 0;
- foreach ($messagearray as $message) {
- $count += ($message->$field == $value) ? 1 : 0;
- }
- return $count;
+function message_count_messages() {
+ throw new coding_exception('message_count_messages() can not be used anymore.');
}
/**
- * Count the number of users blocked by $user1
- *
* @deprecated since Moodle 3.2
- * @param object $user1 user object
- * @return int the number of blocked users
*/
-function message_count_blocked_users($user1=null) {
- debugging('message_count_blocked_users() is deprecated, please use \core_message\api::count_blocked_users() instead.',
- DEBUG_DEVELOPER);
-
- return \core_message\api::count_blocked_users($user1);
+function message_count_blocked_users() {
+ throw new coding_exception('message_count_blocked_users() can not be used anymore. Please use ' .
+ '\core_message\api::count_blocked_users() instead.');
}
/**
- * Print a message contact link
- *
* @deprecated since Moodle 3.2
- * @param int $userid the ID of the user to apply to action to
- * @param string $linktype can be add, remove, block or unblock
- * @param bool $return if true return the link as a string. If false echo the link.
- * @param string $script the URL to send the user to when the link is clicked. If null, the current page.
- * @param bool $text include text next to the icons?
- * @param bool $icon include a graphical icon?
- * @return string if $return is true otherwise bool
*/
-function message_contact_link($userid, $linktype='add', $return=false, $script=null, $text=false, $icon=true) {
- debugging('message_contact_link() is deprecated and is no longer used.', DEBUG_DEVELOPER);
-
- global $OUTPUT, $PAGE;
-
- //hold onto the strings as we're probably creating a bunch of links
- static $str;
-
- if (empty($script)) {
- //strip off previous action params like 'removecontact'
- $script = message_remove_url_params($PAGE->url);
- }
-
- if (empty($str->blockcontact)) {
- $str = new stdClass();
- $str->blockcontact = get_string('blockcontact', 'message');
- $str->unblockcontact = get_string('unblockcontact', 'message');
- $str->removecontact = get_string('removecontact', 'message');
- $str->addcontact = get_string('addcontact', 'message');
- }
-
- $command = $linktype.'contact';
- $string = $str->{$command};
-
- $safealttext = s($string);
-
- $safestring = '';
- if (!empty($text)) {
- $safestring = $safealttext;
- }
-
- $img = '';
- if ($icon) {
- $iconpath = null;
- switch ($linktype) {
- case 'block':
- $iconpath = 't/block';
- break;
- case 'unblock':
- $iconpath = 't/unblock';
- break;
- case 'remove':
- $iconpath = 't/removecontact';
- break;
- case 'add':
- default:
- $iconpath = 't/addcontact';
- }
-
- $img = $OUTPUT->pix_icon($iconpath, $safealttext);
- }
-
- $output = '<span class="'.$linktype.'contact">'.
- '<a href="'.$script.'&'.$command.'='.$userid.
- '&sesskey='.sesskey().'" title="'.$safealttext.'">'.
- $img.
- $safestring.'</a></span>';
-
- if ($return) {
- return $output;
- } else {
- echo $output;
- return true;
- }
+function message_contact_link() {
+ throw new coding_exception('message_contact_link() can not be used anymore.');
}
/**
* @deprecated since Moodle 3.2
*/
-function message_get_recent_notifications($user, $limitfrom=0, $limitto=100) {
- throw new coding_exception('message_get_recent_notifications() can not be used any more.', DEBUG_DEVELOPER);
+function message_get_recent_notifications() {
+ throw new coding_exception('message_get_recent_notifications() can not be used anymore.');
}
/**
- * echo or return a link to take the user to the full message history between themselves and another user
- *
* @deprecated since Moodle 3.2
- * @param int $userid1 the ID of the user displayed on the left (usually the current user)
- * @param int $userid2 the ID of the other user
- * @param bool $return true to return the link as a string. False to echo the link.
- * @param string $keywords any keywords to highlight in the message history
- * @param string $position anchor name to jump to within the message history
- * @param string $linktext optionally specify the link text
- * @return string|bool. Returns a string if $return is true. Otherwise returns a boolean.
- */
-function message_history_link($userid1, $userid2, $return=false, $keywords='', $position='', $linktext='') {
- debugging('message_history_link() is deprecated and is no longer used.', DEBUG_DEVELOPER);
-
- global $OUTPUT, $PAGE;
- static $strmessagehistory;
-
- if (empty($strmessagehistory)) {
- $strmessagehistory = get_string('messagehistory', 'message');
- }
-
- if ($position) {
- $position = "#$position";
- }
- if ($keywords) {
- $keywords = "&search=".urlencode($keywords);
- }
-
- if ($linktext == 'icon') { // Icon only
- $fulllink = $OUTPUT->pix_icon('t/messages', $strmessagehistory);
- } else if ($linktext == 'both') { // Icon and standard name
- $fulllink = $OUTPUT->pix_icon('t/messages', '');
- $fulllink .= ' '.$strmessagehistory;
- } else if ($linktext) { // Custom name
- $fulllink = $linktext;
- } else { // Standard name only
- $fulllink = $strmessagehistory;
- }
-
- $popupoptions = array(
- 'height' => 500,
- 'width' => 500,
- 'menubar' => false,
- 'location' => false,
- 'status' => true,
- 'scrollbars' => true,
- 'resizable' => true);
-
- $link = new moodle_url('/message/index.php?history='.MESSAGE_HISTORY_ALL."&user1=$userid1&user2=$userid2$keywords$position");
- if ($PAGE->url && $PAGE->url->get_param('viewing')) {
- $link->param('viewing', $PAGE->url->get_param('viewing'));
- }
- $action = null;
- $str = $OUTPUT->action_link($link, $fulllink, $action, array('title' => $strmessagehistory));
-
- $str = '<span class="history">'.$str.'</span>';
-
- if ($return) {
- return $str;
- } else {
- echo $str;
- return true;
- }
+ */
+function message_history_link() {
+ throw new coding_exception('message_history_link() can not be used anymore.');
}
/**
* @deprecated since Moodle 3.2
*/
-function message_search($searchterms, $fromme=true, $tome=true, $courseid='none', $userid=0) {
- throw new coding_exception('message_search() can not be used any more.', DEBUG_DEVELOPER);
+function message_search() {
+ throw new coding_exception('message_search() can not be used anymore.');
}
/**
- * Given a message object that we already know has a long message
- * this function truncates the message nicely to the first
- * sane place between $CFG->forum_longpost and $CFG->forum_shortpost
- *
* @deprecated since Moodle 3.2
- * @param string $message the message
- * @param int $minlength the minimum length to trim the message to
- * @return string the shortened message
*/
-function message_shorten_message($message, $minlength = 0) {
- debugging('message_shorten_message() is deprecated and is no longer used.', DEBUG_DEVELOPER);
-
- $i = 0;
- $tag = false;
- $length = strlen($message);
- $count = 0;
- $stopzone = false;
- $truncate = 0;
- if ($minlength == 0) $minlength = MESSAGE_SHORTLENGTH;
-
-
- for ($i=0; $i<$length; $i++) {
- $char = $message[$i];
-
- switch ($char) {
- case "<":
- $tag = true;
- break;
- case ">":
- $tag = false;
- break;
- default:
- if (!$tag) {
- if ($stopzone) {
- if ($char == '.' or $char == ' ') {
- $truncate = $i+1;
- break 2;
- }
- }
- $count++;
- }
- break;
- }
- if (!$stopzone) {
- if ($count > $minlength) {
- $stopzone = true;
- }
- }
- }
-
- if (!$truncate) {
- $truncate = $i;
- }
-
- return substr($message, 0, $truncate);
+function message_shorten_message() {
+ throw new coding_exception('message_shorten_message() can not be used anymore.');
}
/**
- * Given a string and an array of keywords, this function looks
- * for the first keyword in the string, and then chops out a
- * small section from the text that shows that word in context.
- *
* @deprecated since Moodle 3.2
- * @param string $message the text to search
- * @param array $keywords array of keywords to find
*/
-function message_get_fragment($message, $keywords) {
- debugging('message_get_fragment() is deprecated and is no longer used.', DEBUG_DEVELOPER);
-
- $fullsize = 160;
- $halfsize = (int)($fullsize/2);
-
- $message = strip_tags($message);
-
- foreach ($keywords as $keyword) { // Just get the first one
- if ($keyword !== '') {
- break;
- }
- }
- if (empty($keyword)) { // None found, so just return start of message
- return message_shorten_message($message, 30);
- }
-
- $leadin = $leadout = '';
-
-/// Find the start of the fragment
- $start = 0;
- $length = strlen($message);
-
- $pos = strpos($message, $keyword);
- if ($pos > $halfsize) {
- $start = $pos - $halfsize;
- $leadin = '...';
- }
-/// Find the end of the fragment
- $end = $start + $fullsize;
- if ($end > $length) {
- $end = $length;
- } else {
- $leadout = '...';
- }
-
-/// Pull out the fragment and format it
-
- $fragment = substr($message, $start, $end - $start);
- $fragment = $leadin.highlight(implode(' ',$keywords), $fragment).$leadout;
- return $fragment;
+function message_get_fragment() {
+ throw new coding_exception('message_get_fragment() can not be used anymore.');
}
/**
* @deprecated since Moodle 3.2
*/
-function message_get_history($user1, $user2, $limitnum=0, $viewingnewmessages=false) {
- throw new coding_exception('message_get_history() can not be used any more.', DEBUG_DEVELOPER);
+function message_get_history() {
+ throw new coding_exception('message_get_history() can not be used anymore.');
}
/**
- * Constructs the add/remove contact link to display next to other users
- *
* @deprecated since Moodle 3.2
- * @param bool $incontactlist is the user a contact
- * @param bool $isblocked is the user blocked
- * @param stdClass $contact contact object
- * @param string $script the URL to send the user to when the link is clicked. If null, the current page.
- * @param bool $text include text next to the icons?
- * @param bool $icon include a graphical icon?
- * @return string
- */
-function message_get_contact_add_remove_link($incontactlist, $isblocked, $contact, $script=null, $text=false, $icon=true) {
- debugging('message_get_contact_add_remove_link() is deprecated and is no longer used.', DEBUG_DEVELOPER);
-
- $strcontact = '';
-
- if($incontactlist){
- $strcontact = message_contact_link($contact->id, 'remove', true, $script, $text, $icon);
- } else if ($isblocked) {
- $strcontact = message_contact_link($contact->id, 'add', true, $script, $text, $icon);
- } else{
- $strcontact = message_contact_link($contact->id, 'add', true, $script, $text, $icon);
- }
-
- return $strcontact;
+ */
+function message_get_contact_add_remove_link() {
+ throw new coding_exception('message_get_contact_add_remove_link() can not be used anymore.');
}
/**
- * Constructs the block contact link to display next to other users
- *
* @deprecated since Moodle 3.2
- * @param bool $incontactlist is the user a contact?
- * @param bool $isblocked is the user blocked?
- * @param stdClass $contact contact object
- * @param string $script the URL to send the user to when the link is clicked. If null, the current page.
- * @param bool $text include text next to the icons?
- * @param bool $icon include a graphical icon?
- * @return string
- */
-function message_get_contact_block_link($incontactlist, $isblocked, $contact, $script=null, $text=false, $icon=true) {
- debugging('message_get_contact_block_link() is deprecated and is no longer used.', DEBUG_DEVELOPER);
-
- $strblock = '';
-
- //commented out to allow the user to block a contact without having to remove them first
- /*if ($incontactlist) {
- //$strblock = '';
- } else*/
- if ($isblocked) {
- $strblock = message_contact_link($contact->id, 'unblock', true, $script, $text, $icon);
- } else{
- $strblock = message_contact_link($contact->id, 'block', true, $script, $text, $icon);
- }
-
- return $strblock;
+ */
+function message_get_contact_block_link() {
+ throw new coding_exception('message_get_contact_block_link() can not be used anymore.');
}
/**
- * marks ALL messages being sent from $fromuserid to $touserid as read
- *
* @deprecated since Moodle 3.2
- * @param int $touserid the id of the message recipient
- * @param int $fromuserid the id of the message sender
- * @return void
*/
-function message_mark_messages_read($touserid, $fromuserid) {
- debugging('message_mark_messages_read() is deprecated and is no longer used, please use
- \core_message\api::mark_all_messages_as_read() instead.', DEBUG_DEVELOPER);
-
- \core_message\api::mark_all_messages_as_read($touserid, $fromuserid);
+function message_mark_messages_read() {
+ throw new coding_exception('message_mark_messages_read() can not be used anymore. Please use ' .
+ '\core_message\api::mark_all_messages_as_read() instead.');
}
/**
- * Return a list of page types
- *
* @deprecated since Moodle 3.2
- * @param string $pagetype current page type
- * @param stdClass $parentcontext Block's parent context
- * @param stdClass $currentcontext Current context of block
*/
-function message_page_type_list($pagetype, $parentcontext, $currentcontext) {
- debugging('message_page_type_list() is deprecated and is no longer used.', DEBUG_DEVELOPER);
-
- return array('messages-*'=>get_string('page-message-x', 'message'));
+function message_page_type_list() {
+ throw new coding_exception('message_page_type_list() can not be used anymore.');
}
/**
- * Determines if a user is permitted to send another user a private message.
- * If no sender is provided then it defaults to the logged in user.
- *
* @deprecated since Moodle 3.2
- * @param object $recipient User object.
- * @param object $sender User object.
- * @return bool true if user is permitted, false otherwise.
*/
-function message_can_post_message($recipient, $sender = null) {
- debugging('message_can_post_message() is deprecated and is no longer used, please use
- \core_message\api::can_post_message() instead.', DEBUG_DEVELOPER);
-
- return \core_message\api::can_post_message($recipient, $sender);
+function message_can_post_message() {
+ throw new coding_exception('message_can_post_message() can not be used anymore. Please use ' .
+ '\core_message\api::can_post_message() instead.');
}
/**
- * Checks if the recipient is allowing messages from users that aren't a
- * contact. If not then it checks to make sure the sender is in the
- * recipient's contacts.
- *
* @deprecated since Moodle 3.2
- * @param object $recipient User object.
- * @param object $sender User object.
- * @return bool true if $sender is blocked, false otherwise.
*/
-function message_is_user_non_contact_blocked($recipient, $sender = null) {
- debugging('message_is_user_non_contact_blocked() is deprecated and is no longer used, please use
- \core_message\api::is_user_non_contact_blocked() instead.', DEBUG_DEVELOPER);
-
- return \core_message\api::is_user_non_contact_blocked($recipient, $sender);
+function message_is_user_non_contact_blocked() {
+ throw new coding_exception('message_is_user_non_contact_blocked() can not be used anymore. Please use ' .
+ '\core_message\api::is_user_non_contact_blocked() instead.');
}
/**
- * Checks if the recipient has specifically blocked the sending user.
- *
- * Note: This function will always return false if the sender has the
- * readallmessages capability at the system context level.
- *
* @deprecated since Moodle 3.2
- * @param object $recipient User object.
- * @param object $sender User object.
- * @return bool true if $sender is blocked, false otherwise.
*/
-function message_is_user_blocked($recipient, $sender = null) {
- debugging('message_is_user_blocked() is deprecated and is no longer used, please use
- \core_message\api::is_user_blocked() instead.', DEBUG_DEVELOPER);
-
- $senderid = null;
- if ($sender !== null && isset($sender->id)) {
- $senderid = $sender->id;
- }
- return \core_message\api::is_user_blocked($recipient->id, $senderid);
+function message_is_user_blocked() {
+ throw new coding_exception('message_is_user_blocked() can not be used anymore. Please use ' .
+ '\core_message\api::is_user_blocked() instead.');
}
/**
- * Display logs.
- *
- * @deprecated since 3.2
+ * @deprecated since Moodle 3.2
*/
-function print_log($course, $user=0, $date=0, $order="l.time ASC", $page=0, $perpage=100,
- $url="", $modname="", $modid=0, $modaction="", $groupid=0) {
- debugging(__FUNCTION__ . '() is deprecated. Please use the report_log framework instead.', DEBUG_DEVELOPER);
-
- global $CFG, $DB, $OUTPUT;
-
- if (!$logs = build_logs_array($course, $user, $date, $order, $page*$perpage, $perpage,
- $modname, $modid, $modaction, $groupid)) {
- echo $OUTPUT->notification("No logs found!");
- echo $OUTPUT->footer();
- exit;
- }
-
- $courses = array();
-
- if ($course->id == SITEID) {
- $courses[0] = '';
- if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname')) {
- foreach ($ccc as $cc) {
- $courses[$cc->id] = $cc->shortname;
- }
- }
- } else {
- $courses[$course->id] = $course->shortname;
- }
-
- $totalcount = $logs['totalcount'];
- $ldcache = array();
-
- $strftimedatetime = get_string("strftimedatetime");
-
- echo "<div class=\"info\">\n";
- print_string("displayingrecords", "", $totalcount);
- echo "</div>\n";
-
- echo $OUTPUT->paging_bar($totalcount, $page, $perpage, "$url&perpage=$perpage");
-
- $table = new html_table();
- $table->classes = array('logtable','generaltable');
- $table->align = array('right', 'left', 'left');
- $table->head = array(
- get_string('time'),
- get_string('ip_address'),
- get_string('fullnameuser'),
- get_string('action'),
- get_string('info')
- );
- $table->data = array();
-
- if ($course->id == SITEID) {
- array_unshift($table->align, 'left');
- array_unshift($table->head, get_string('course'));
- }
-
- // Make sure that the logs array is an array, even it is empty, to avoid warnings from the foreach.
- if (empty($logs['logs'])) {
- $logs['logs'] = array();
- }
-
- foreach ($logs['logs'] as $log) {
-
- if (isset($ldcache[$log->module][$log->action])) {
- $ld = $ldcache[$log->module][$log->action];
- } else {
- $ld = $DB->get_record('log_display', array('module'=>$log->module, 'action'=>$log->action));
- $ldcache[$log->module][$log->action] = $ld;
- }
- if ($ld && is_numeric($log->info)) {
- // ugly hack to make sure fullname is shown correctly
- if ($ld->mtable == 'user' && $ld->field == $DB->sql_concat('firstname', "' '" , 'lastname')) {
- $log->info = fullname($DB->get_record($ld->mtable, array('id'=>$log->info)), true);
- } else {
- $log->info = $DB->get_field($ld->mtable, $ld->field, array('id'=>$log->info));
- }
- }
-
- //Filter log->info
- $log->info = format_string($log->info);
-
- // If $log->url has been trimmed short by the db size restriction
- // code in add_to_log, keep a note so we don't add a link to a broken url
- $brokenurl=(core_text::strlen($log->url)==100 && core_text::substr($log->url,97)=='...');
-
- $row = array();
- if ($course->id == SITEID) {
- if (empty($log->course)) {
- $row[] = get_string('site');
- } else {
- $row[] = "<a href=\"{$CFG->wwwroot}/course/view.php?id={$log->course}\">". format_string($courses[$log->course])."</a>";
- }
- }
-
- $row[] = userdate($log->time, '%a').' '.userdate($log->time, $strftimedatetime);
-
- $link = new moodle_url("/iplookup/index.php?ip=$log->ip&user=$log->userid");
- $row[] = $OUTPUT->action_link($link, $log->ip, new popup_action('click', $link, 'iplookup', array('height' => 440, 'width' => 700)));
-
- $row[] = html_writer::link(new moodle_url("/user/view.php?id={$log->userid}&course={$log->course}"), fullname($log, has_capability('moodle/site:viewfullnames', context_course::instance($course->id))));
-
- $displayaction="$log->module $log->action";
- if ($brokenurl) {
- $row[] = $displayaction;
- } else {
- $link = make_log_url($log->module,$log->url);
- $row[] = $OUTPUT->action_link($link, $displayaction, new popup_action('click', $link, 'fromloglive'), array('height' => 440, 'width' => 700));
- }
- $row[] = $log->info;
- $table->data[] = $row;
- }
-
- echo html_writer::table($table);
- echo $OUTPUT->paging_bar($totalcount, $page, $perpage, "$url&perpage=$perpage");
+function print_log() {
+ throw new coding_exception('print_log() can not be used anymore. Please use the ' .
+ 'report_log framework instead.');
}
/**
- * Display MNET logs.
- *
- * @deprecated since 3.2
+ * @deprecated since Moodle 3.2
*/
-function print_mnet_log($hostid, $course, $user=0, $date=0, $order="l.time ASC", $page=0, $perpage=100,
- $url="", $modname="", $modid=0, $modaction="", $groupid=0) {
- debugging(__FUNCTION__ . '() is deprecated. Please use the report_log framework instead.', DEBUG_DEVELOPER);
-
- global $CFG, $DB, $OUTPUT;
-
- if (!$logs = build_mnet_logs_array($hostid, $course, $user, $date, $order, $page*$perpage, $perpage,
- $modname, $modid, $modaction, $groupid)) {
- echo $OUTPUT->notification("No logs found!");
- echo $OUTPUT->footer();
- exit;
- }
-
- if ($course->id == SITEID) {
- $courses[0] = '';
- if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname,c.visible')) {
- foreach ($ccc as $cc) {
- $courses[$cc->id] = $cc->shortname;
- }
- }
- }
-
- $totalcount = $logs['totalcount'];
- $ldcache = array();
-
- $strftimedatetime = get_string("strftimedatetime");
-
- echo "<div class=\"info\">\n";
- print_string("displayingrecords", "", $totalcount);
- echo "</div>\n";
-
- echo $OUTPUT->paging_bar($totalcount, $page, $perpage, "$url&perpage=$perpage");
-
- echo "<table class=\"logtable\" cellpadding=\"3\" cellspacing=\"0\">\n";
- echo "<tr>";
- if ($course->id == SITEID) {
- echo "<th class=\"c0 header\">".get_string('course')."</th>\n";
- }
- echo "<th class=\"c1 header\">".get_string('time')."</th>\n";
- echo "<th class=\"c2 header\">".get_string('ip_address')."</th>\n";
- echo "<th class=\"c3 header\">".get_string('fullnameuser')."</th>\n";
- echo "<th class=\"c4 header\">".get_string('action')."</th>\n";
- echo "<th class=\"c5 header\">".get_string('info')."</th>\n";
- echo "</tr>\n";
-
- if (empty($logs['logs'])) {
- echo "</table>\n";
- return;
- }
-
- $row = 1;
- foreach ($logs['logs'] as $log) {
-
- $log->info = $log->coursename;
- $row = ($row + 1) % 2;
-
- if (isset($ldcache[$log->module][$log->action])) {
- $ld = $ldcache[$log->module][$log->action];
- } else {
- $ld = $DB->get_record('log_display', array('module'=>$log->module, 'action'=>$log->action));
- $ldcache[$log->module][$log->action] = $ld;
- }
- if (0 && $ld && !empty($log->info)) {
- // ugly hack to make sure fullname is shown correctly
- if (($ld->mtable == 'user') and ($ld->field == $DB->sql_concat('firstname', "' '" , 'lastname'))) {
- $log->info = fullname($DB->get_record($ld->mtable, array('id'=>$log->info)), true);
- } else {
- $log->info = $DB->get_field($ld->mtable, $ld->field, array('id'=>$log->info));
- }
- }
-
- //Filter log->info
- $log->info = format_string($log->info);
-
- echo '<tr class="r'.$row.'">';
- if ($course->id == SITEID) {
- $courseshortname = format_string($courses[$log->course], true, array('context' => context_course::instance(SITEID)));
- echo "<td class=\"r$row c0\" >\n";
- echo " <a href=\"{$CFG->wwwroot}/course/view.php?id={$log->course}\">".$courseshortname."</a>\n";
- echo "</td>\n";
- }
- echo "<td class=\"r$row c1\" align=\"right\">".userdate($log->time, '%a').
- ' '.userdate($log->time, $strftimedatetime)."</td>\n";
- echo "<td class=\"r$row c2\" >\n";
- $link = new moodle_url("/iplookup/index.php?ip=$log->ip&user=$log->userid");
- echo $OUTPUT->action_link($link, $log->ip, new popup_action('click', $link, 'iplookup', array('height' => 400, 'width' => 700)));
- echo "</td>\n";
- $fullname = fullname($log, has_capability('moodle/site:viewfullnames', context_course::instance($course->id)));
- echo "<td class=\"r$row c3\" >\n";
- echo " <a href=\"$CFG->wwwroot/user/view.php?id={$log->userid}\">$fullname</a>\n";
- echo "</td>\n";
- echo "<td class=\"r$row c4\">\n";
- echo $log->action .': '.$log->module;
- echo "</td>\n";
- echo "<td class=\"r$row c5\">{$log->info}</td>\n";
- echo "</tr>\n";
- }
- echo "</table>\n";
-
- echo $OUTPUT->paging_bar($totalcount, $page, $perpage, "$url&perpage=$perpage");
+function print_mnet_log() {
+ throw new coding_exception('print_mnet_log() can not be used anymore. Please use the ' .
+ 'report_log framework instead.');
}
/**
- * Display logs in CSV format.
- *
- * @deprecated since 3.2
+ * @deprecated since Moodle 3.2
*/
-function print_log_csv($course, $user, $date, $order='l.time DESC', $modname,
- $modid, $modaction, $groupid) {
- debugging(__FUNCTION__ . '() is deprecated. Please use the report_log framework instead.', DEBUG_DEVELOPER);
-
- global $DB, $CFG;
-
- require_once($CFG->libdir . '/csvlib.class.php');
-
- $csvexporter = new csv_export_writer('tab');
-
- $header = array();
- $header[] = get_string('course');
- $header[] = get_string('time');
- $header[] = get_string('ip_address');
- $header[] = get_string('fullnameuser');
- $header[] = get_string('action');
- $header[] = get_string('info');
-
- if (!$logs = build_logs_array($course, $user, $date, $order, '', '',
- $modname, $modid, $modaction, $groupid)) {
- return false;
- }
-
- $courses = array();
-
- if ($course->id == SITEID) {
- $courses[0] = '';
- if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname')) {
- foreach ($ccc as $cc) {
- $courses[$cc->id] = $cc->shortname;
- }
- }
- } else {
- $courses[$course->id] = $course->shortname;
- }
-
- $count=0;
- $ldcache = array();
- $tt = getdate(time());
- $today = mktime (0, 0, 0, $tt["mon"], $tt["mday"], $tt["year"]);
-
- $strftimedatetime = get_string("strftimedatetime");
-
- $csvexporter->set_filename('logs', '.txt');
- $title = array(get_string('savedat').userdate(time(), $strftimedatetime));
- $csvexporter->add_data($title);
- $csvexporter->add_data($header);
-
- if (empty($logs['logs'])) {
- return true;
- }
-
- foreach ($logs['logs'] as $log) {
- if (isset($ldcache[$log->module][$log->action])) {
- $ld = $ldcache[$log->module][$log->action];
- } else {
- $ld = $DB->get_record('log_display', array('module'=>$log->module, 'action'=>$log->action));
- $ldcache[$log->module][$log->action] = $ld;
- }
- if ($ld && is_numeric($log->info)) {
- // ugly hack to make sure fullname is shown correctly
- if (($ld->mtable == 'user') and ($ld->field == $DB->sql_concat('firstname', "' '" , 'lastname'))) {
- $log->info = fullname($DB->get_record($ld->mtable, array('id'=>$log->info)), true);
- } else {
- $log->info = $DB->get_field($ld->mtable, $ld->field, array('id'=>$log->info));
- }
- }
-
- //Filter log->info
- $log->info = format_string($log->info);
- $log->info = strip_tags(urldecode($log->info)); // Some XSS protection
-
- $coursecontext = context_course::instance($course->id);
- $firstField = format_string($courses[$log->course], true, array('context' => $coursecontext));
- $fullname = fullname($log, has_capability('moodle/site:viewfullnames', $coursecontext));
- $actionurl = $CFG->wwwroot. make_log_url($log->module,$log->url);
- $row = array($firstField, userdate($log->time, $strftimedatetime), $log->ip, $fullname, $log->module.' '.$log->action.' ('.$actionurl.')', $log->info);
- $csvexporter->add_data($row);
- }
- $csvexporter->download_file();
- return true;
+function print_log_csv() {
+ throw new coding_exception('print_log_csv() can not be used anymore. Please use the ' .
+ 'report_log framework instead.');
}
/**
- * Display logs in XLS format.
- *
- * @deprecated since 3.2
+ * @deprecated since Moodle 3.2
*/
-function print_log_xls($course, $user, $date, $order='l.time DESC', $modname,
- $modid, $modaction, $groupid) {
- debugging(__FUNCTION__ . '() is deprecated. Please use the report_log framework instead.', DEBUG_DEVELOPER);
-
- global $CFG, $DB;
-
- require_once("$CFG->libdir/excellib.class.php");
-
- if (!$logs = build_logs_array($course, $user, $date, $order, '', '',
- $modname, $modid, $modaction, $groupid)) {
- return false;
- }
-
- $courses = array();
-
- if ($course->id == SITEID) {
- $courses[0] = '';
- if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname')) {
- foreach ($ccc as $cc) {
- $courses[$cc->id] = $cc->shortname;
- }
- }
- } else {
- $courses[$course->id] = $course->shortname;
- }
-
- $count=0;
- $ldcache = array();
- $tt = getdate(time());
- $today = mktime (0, 0, 0, $tt["mon"], $tt["mday"], $tt["year"]);
-
- $strftimedatetime = get_string("strftimedatetime");
-
- $nroPages = ceil(count($logs)/(EXCELROWS-FIRSTUSEDEXCELROW+1));
- $filename = 'logs_'.userdate(time(),get_string('backupnameformat', 'langconfig'),99,false);
- $filename .= '.xls';
-
- $workbook = new MoodleExcelWorkbook('-');
- $workbook->send($filename);
-
- $worksheet = array();
- $headers = array(get_string('course'), get_string('time'), get_string('ip_address'),
- get_string('fullnameuser'), get_string('action'), get_string('info'));
-
- // Creating worksheets
- for ($wsnumber = 1; $wsnumber <= $nroPages; $wsnumber++) {
- $sheettitle = get_string('logs').' '.$wsnumber.'-'.$nroPages;
- $worksheet[$wsnumber] = $workbook->add_worksheet($sheettitle);
- $worksheet[$wsnumber]->set_column(1, 1, 30);
- $worksheet[$wsnumber]->write_string(0, 0, get_string('savedat').
- userdate(time(), $strftimedatetime));
- $col = 0;
- foreach ($headers as $item) {
- $worksheet[$wsnumber]->write(FIRSTUSEDEXCELROW-1,$col,$item,'');
- $col++;
- }
- }
-
- if (empty($logs['logs'])) {
- $workbook->close();
- return true;
- }
-
- $formatDate =& $workbook->add_format();
- $formatDate->set_num_format(get_string('log_excel_date_format'));
-
- $row = FIRSTUSEDEXCELROW;
- $wsnumber = 1;
- $myxls =& $worksheet[$wsnumber];
- foreach ($logs['logs'] as $log) {
- if (isset($ldcache[$log->module][$log->action])) {
- $ld = $ldcache[$log->module][$log->action];
- } else {
- $ld = $DB->get_record('log_display', array('module'=>$log->module, 'action'=>$log->action));
- $ldcache[$log->module][$log->action] = $ld;
- }
- if ($ld && is_numeric($log->info)) {
- // ugly hack to make sure fullname is shown correctly
- if (($ld->mtable == 'user') and ($ld->field == $DB->sql_concat('firstname', "' '" , 'lastname'))) {
- $log->info = fullname($DB->get_record($ld->mtable, array('id'=>$log->info)), true);
- } else {
- $log->info = $DB->get_field($ld->mtable, $ld->field, array('id'=>$log->info));
- }
- }
-
- // Filter log->info
- $log->info = format_string($log->info);
- $log->info = strip_tags(urldecode($log->info)); // Some XSS protection
-
- if ($nroPages>1) {
- if ($row > EXCELROWS) {
- $wsnumber++;
- $myxls =& $worksheet[$wsnumber];
- $row = FIRSTUSEDEXCELROW;
- }
- }
-
- $coursecontext = context_course::instance($course->id);
-
- $myxls->write($row, 0, format_string($courses[$log->course], true, array('context' => $coursecontext)), '');
- $myxls->write_date($row, 1, $log->time, $formatDate); // write_date() does conversion/timezone support. MDL-14934
- $myxls->write($row, 2, $log->ip, '');
- $fullname = fullname($log, has_capability('moodle/site:viewfullnames', $coursecontext));
- $myxls->write($row, 3, $fullname, '');
- $actionurl = $CFG->wwwroot. make_log_url($log->module,$log->url);
- $myxls->write($row, 4, $log->module.' '.$log->action.' ('.$actionurl.')', '');
- $myxls->write($row, 5, $log->info, '');
-
- $row++;
- }
-
- $workbook->close();
- return true;
+function print_log_xls() {
+ throw new coding_exception('print_log_xls() can not be used anymore. Please use the ' .
+ 'report_log framework instead.');
}
/**
- * Display logs in ODS format.
- *
- * @deprecated since 3.2
+ * @deprecated since Moodle 3.2
*/
-function print_log_ods($course, $user, $date, $order='l.time DESC', $modname,
- $modid, $modaction, $groupid) {
- debugging(__FUNCTION__ . '() is deprecated. Please use the report_log framework instead.', DEBUG_DEVELOPER);
-
- global $CFG, $DB;
-
- require_once("$CFG->libdir/odslib.class.php");
-
- if (!$logs = build_logs_array($course, $user, $date, $order, '', '',
- $modname, $modid, $modaction, $groupid)) {
- return false;
- }
-
- $courses = array();
-
- if ($course->id == SITEID) {
- $courses[0] = '';
- if ($ccc = get_courses('all', 'c.id ASC', 'c.id,c.shortname')) {
- foreach ($ccc as $cc) {
- $courses[$cc->id] = $cc->shortname;
- }
- }
- } else {
- $courses[$course->id] = $course->shortname;
- }
-
- $ldcache = array();
-
- $strftimedatetime = get_string("strftimedatetime");
-
- $nroPages = ceil(count($logs)/(EXCELROWS-FIRSTUSEDEXCELROW+1));
- $filename = 'logs_'.userdate(time(),get_string('backupnameformat', 'langconfig'),99,false);
- $filename .= '.ods';
-
- $workbook = new MoodleODSWorkbook('-');
- $workbook->send($filename);
-
- $worksheet = array();
- $headers = array(get_string('course'), get_string('time'), get_string('ip_address'),
- get_string('fullnameuser'), get_string('action'), get_string('info'));
-
- // Creating worksheets
- for ($wsnumber = 1; $wsnumber <= $nroPages; $wsnumber++) {
- $sheettitle = get_string('logs').' '.$wsnumber.'-'.$nroPages;
- $worksheet[$wsnumber] = $workbook->add_worksheet($sheettitle);
- $worksheet[$wsnumber]->set_column(1, 1, 30);
- $worksheet[$wsnumber]->write_string(0, 0, get_string('savedat').
- userdate(time(), $strftimedatetime));
- $col = 0;
- foreach ($headers as $item) {
- $worksheet[$wsnumber]->write(FIRSTUSEDEXCELROW-1,$col,$item,'');
- $col++;
- }
- }
-
- if (empty($logs['logs'])) {
- $workbook->close();
- return true;
- }
-
- $formatDate =& $workbook->add_format();
- $formatDate->set_num_format(get_string('log_excel_date_format'));
-
- $row = FIRSTUSEDEXCELROW;
- $wsnumber = 1;
- $myxls =& $worksheet[$wsnumber];
- foreach ($logs['logs'] as $log) {
- if (isset($ldcache[$log->module][$log->action])) {
- $ld = $ldcache[$log->module][$log->action];
- } else {
- $ld = $DB->get_record('log_display', array('module'=>$log->module, 'action'=>$log->action));
- $ldcache[$log->module][$log->action] = $ld;
- }
- if ($ld && is_numeric($log->info)) {
- // ugly hack to make sure fullname is shown correctly
- if (($ld->mtable == 'user') and ($ld->field == $DB->sql_concat('firstname', "' '" , 'lastname'))) {
- $log->info = fullname($DB->get_record($ld->mtable, array('id'=>$log->info)), true);
- } else {
- $log->info = $DB->get_field($ld->mtable, $ld->field, array('id'=>$log->info));
- }
- }
-
- // Filter log->info
- $log->info = format_string($log->info);
- $log->info = strip_tags(urldecode($log->info)); // Some XSS protection
-
- if ($nroPages>1) {
- if ($row > EXCELROWS) {
- $wsnumber++;
- $myxls =& $worksheet[$wsnumber];
- $row = FIRSTUSEDEXCELROW;
- }
- }
-
- $coursecontext = context_course::instance($course->id);
-
- $myxls->write_string($row, 0, format_string($courses[$log->course], true, array('context' => $coursecontext)));
- $myxls->write_date($row, 1, $log->time);
- $myxls->write_string($row, 2, $log->ip);
- $fullname = fullname($log, has_capability('moodle/site:viewfullnames', $coursecontext));
- $myxls->write_string($row, 3, $fullname);
- $actionurl = $CFG->wwwroot. make_log_url($log->module,$log->url);
- $myxls->write_string($row, 4, $log->module.' '.$log->action.' ('.$actionurl.')');
- $myxls->write_string($row, 5, $log->info);
-
- $row++;
- }
-
- $workbook->close();
- return true;
+function print_log_ods() {
+ throw new coding_exception('print_log_ods() can not be used anymore. Please use the ' .
+ 'report_log framework instead.');
}
/**
- * Build an array of logs.
- *
- * @deprecated since 3.2
+ * @deprecated since Moodle 3.2
*/
-function build_logs_array($course, $user=0, $date=0, $order="l.time ASC", $limitfrom='', $limitnum='',
- $modname="", $modid=0, $modaction="", $groupid=0) {
- global $DB, $SESSION, $USER;
-
- debugging(__FUNCTION__ . '() is deprecated. Please use the report_log framework instead.', DEBUG_DEVELOPER);
- // It is assumed that $date is the GMT time of midnight for that day,
- // and so the next 86400 seconds worth of logs are printed.
-
- // Setup for group handling.
-
- // If the group mode is separate, and this user does not have editing privileges,
- // then only the user's group can be viewed.
- if ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/course:managegroups', context_course::instance($course->id))) {
- if (isset($SESSION->currentgroup[$course->id])) {
- $groupid = $SESSION->currentgroup[$course->id];
- } else {
- $groupid = groups_get_all_groups($course->id, $USER->id);
- if (is_array($groupid)) {
- $groupid = array_shift(array_keys($groupid));
- $SESSION->currentgroup[$course->id] = $groupid;
- } else {
- $groupid = 0;
- }
- }
- }
- // If this course doesn't have groups, no groupid can be specified.
- else if (!$course->groupmode) {
- $groupid = 0;
- }
-
- $joins = array();
- $params = array();
-
- if ($course->id != SITEID || $modid != 0) {
- $joins[] = "l.course = :courseid";
- $params['courseid'] = $course->id;
- }
-
- if ($modname) {
- $joins[] = "l.module = :modname";
- $params['modname'] = $modname;
- }
-
- if ('site_errors' === $modid) {
- $joins[] = "( l.action='error' OR l.action='infected' )";
- } else if ($modid) {
- $joins[] = "l.cmid = :modid";
- $params['modid'] = $modid;
- }
-
- if ($modaction) {
- $firstletter = substr($modaction, 0, 1);
- if ($firstletter == '-') {
- $joins[] = $DB->sql_like('l.action', ':modaction', false, true, true);
- $params['modaction'] = '%'.substr($modaction, 1).'%';
- } else {
- $joins[] = $DB->sql_like('l.action', ':modaction', false);
- $params['modaction'] = '%'.$modaction.'%';
- }
- }
-
-
- /// Getting all members of a group.
- if ($groupid and !$user) {
- if ($gusers = groups_get_members($groupid)) {
- $gusers = array_keys($gusers);
- $joins[] = 'l.userid IN (' . implode(',', $gusers) . ')';
- } else {
- $joins[] = 'l.userid = 0'; // No users in groups, so we want something that will always be false.
- }
- }
- else if ($user) {
- $joins[] = "l.userid = :userid";
- $params['userid'] = $user;
- }
-
- if ($date) {
- $enddate = $date + 86400;
- $joins[] = "l.time > :date AND l.time < :enddate";
- $params['date'] = $date;
- $params['enddate'] = $enddate;
- }
-
- $selector = implode(' AND ', $joins);
-
- $totalcount = 0; // Initialise
- $result = array();
- $result['logs'] = get_logs($selector, $params, $order, $limitfrom, $limitnum, $totalcount);
- $result['totalcount'] = $totalcount;
- return $result;
+function build_logs_array() {
+ throw new coding_exception('build_logs_array() can not be used anymore. Please use the ' .
+ 'report_log framework instead.');
}
/**
- * Select all log records for a given course and user.
- *
- * @deprecated since 3.2
- * @param int $userid The id of the user as found in the 'user' table.
- * @param int $courseid The id of the course as found in the 'course' table.
- * @param string $coursestart unix timestamp representing course start date and time.
- * @return array
+ * @deprecated since Moodle 3.2
*/
-function get_logs_usercourse($userid, $courseid, $coursestart) {
- global $DB;
-
- debugging(__FUNCTION__ . '() is deprecated. Please use the report_log framework instead.', DEBUG_DEVELOPER);
-
- $params = array();
-
- $courseselect = '';
- if ($courseid) {
- $courseselect = "AND course = :courseid";
- $params['courseid'] = $courseid;
- }
- $params['userid'] = $userid;
- // We have to sanitize this param ourselves here instead of relying on DB.
- // Postgres complains if you use name parameter or column alias in GROUP BY.
- // See MDL-27696 and 51c3e85 for details.
- $coursestart = (int)$coursestart;
-
- return $DB->get_records_sql("SELECT FLOOR((time - $coursestart)/". DAYSECS .") AS day, COUNT(*) AS num
- FROM {log}
- WHERE userid = :userid
- AND time > $coursestart $courseselect
- GROUP BY FLOOR((time - $coursestart)/". DAYSECS .")", $params);
+function get_logs_usercourse() {
+ throw new coding_exception('get_logs_usercourse() can not be used anymore. Please use the ' .
+ 'report_log framework instead.');
}
/**
- * Select all log records for a given course, user, and day.
- *
- * @deprecated since 3.2
- * @param int $userid The id of the user as found in the 'user' table.
- * @param int $courseid The id of the course as found in the 'course' table.
- * @param string $daystart unix timestamp of the start of the day for which the logs needs to be retrived
- * @return array
+ * @deprecated since Moodle 3.2
*/
-function get_logs_userday($userid, $courseid, $daystart) {
- global $DB;
-
- debugging(__FUNCTION__ . '() is deprecated. Please use the report_log framework instead.', DEBUG_DEVELOPER);
-
- $params = array('userid'=>$userid);
-
- $courseselect = '';
- if ($courseid) {
- $courseselect = "AND course = :courseid";
- $params['courseid'] = $courseid;
- }
- // Note: unfortunately pg complains if you use name parameter or column alias in GROUP BY.
- $daystart = (int) $daystart;
-
- return $DB->get_records_sql("SELECT FLOOR((time - $daystart)/". HOURSECS .") AS hour, COUNT(*) AS num
- FROM {log}
- WHERE userid = :userid
- AND time > $daystart $courseselect
- GROUP BY FLOOR((time - $daystart)/". HOURSECS .") ", $params);
+function get_logs_userday() {
+ throw new coding_exception('get_logs_userday() can not be used anymore. Please use the ' .
+ 'report_log framework instead.');
}
/**
- * Select all log records based on SQL criteria.
- *
- * @deprecated since 3.2
- * @param string $select SQL select criteria
- * @param array $params named sql type params
- * @param string $order SQL order by clause to sort the records returned
- * @param string $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set)
- * @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set)
- * @param int $totalcount Passed in by reference.
- * @return array
+ * @deprecated since Moodle 3.2
*/
-function get_logs($select, array $params=null, $order='l.time DESC', $limitfrom='', $limitnum='', &$totalcount) {
- global $DB;
-
- debugging(__FUNCTION__ . '() is deprecated. Please use the report_log framework instead.', DEBUG_DEVELOPER);
-
- if ($order) {
- $order = "ORDER BY $order";
- }
-
- if ($select) {
- $select = "WHERE $select";
- }
-
- $sql = "SELECT COUNT(*)
- FROM {log} l
- $select";
-
- $totalcount = $DB->count_records_sql($sql, $params);
- $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
- $order";
-
- return $DB->get_records_sql($sql, $params, $limitfrom, $limitnum);
+function get_logs() {
+ throw new coding_exception('get_logs() can not be used anymore. Please use the ' .
+ 'report_log framework instead.');
}
/**
- * Renders a hidden password field so that browsers won't incorrectly autofill password fields with the user's password.
- *
- * @deprecated since Moodle 3.2 MDL-53048
+ * @deprecated since Moodle 3.2
*/
function prevent_form_autofill_password() {
- debugging('prevent_form_autofill_password has been deprecated and is no longer in use.', DEBUG_DEVELOPER);
- return '';
+ throw new coding_exception('prevent_form_autofill_password() can not be used anymore.');
}
/**
}
/**
- * Display calendar preference button.
- *
- * @param stdClass $course course object
* @deprecated since Moodle 3.2
- * @return string return preference button in html
*/
-function calendar_preferences_button(stdClass $course) {
- debugging('This should no longer be used, the calendar preferences are now linked to the user preferences page.');
-
- global $OUTPUT;
-
- // Guests have no preferences.
- if (!isloggedin() || isguestuser()) {
- return '';
- }
-
- return $OUTPUT->single_button(new moodle_url('/user/calendar.php'), get_string("preferences", "calendar"));
+function calendar_preferences_button() {
+ throw new coding_exception('calendar_preferences_button() can not be used anymore. The calendar ' .
+ 'preferences are now linked to the user preferences page.');
}
/**
return $handlers[$eventname];
}
+
+/**
+ * This function finds the roles assigned directly to this context only
+ * i.e. no roles in parent contexts
+ *
+ * @deprecated since Moodle 3.6. Please use the get_roles_used_in_context().
+ * @todo final deprecation. To be removed in Moodle 4.0
+ * @param context $context
+ * @return array
+ */
+function get_roles_on_exact_context(context $context) {
+ debugging('get_roles_on_exact_context() is deprecated, please use get_roles_used_in_context() instead.',
+ DEBUG_DEVELOPER);
+
+ return get_roles_used_in_context($context, false);
+}
+
+/**
+ * Find out which roles has assignment on this context
+ *
+ * @deprecated since Moodle 3.6. Please use the get_roles_used_in_context().
+ * @todo final deprecation. To be removed in Moodle 4.0
+ * @param context $context
+ * @return array
+ */
+function get_roles_with_assignment_on_context(context $context) {
+ debugging('get_roles_with_assignment_on_context() is deprecated, please use get_roles_used_in_context() instead.',
+ DEBUG_DEVELOPER);
+
+ return get_roles_used_in_context($context, false);
+}
}
}
$urlbase = $CFG->wwwroot.'/pluginfile.php';
- return new file_info_stored($this->browser, $this->context, $storedfile, $urlbase, $section->section, true, true, true, false);
+ require_once($CFG->dirroot.'/course/lib.php');
+ $sectionname = get_section_name($this->course, $section);
+ return new file_info_stored($this->browser, $this->context, $storedfile, $urlbase, $sectionname, true, true, true, false);
}
/**
* Passing a new option reverse = true in the $options var will make the function to convert actual URLs in $text to encoded URLs
* in the @@PLUGINFILE@@ form.
*
- * @category files
- * @global stdClass $CFG
- * @param string $text The content that may contain ULRs in need of rewriting.
- * @param string $file The script that should be used to serve these files. pluginfile.php, draftfile.php, etc.
- * @param int $contextid This parameter and the next two identify the file area to use.
- * @param string $component
- * @param string $filearea helps identify the file area.
- * @param int $itemid helps identify the file area.
- * @param array $options text and file options ('forcehttps'=>false), use reverse = true to reverse the behaviour of the function.
- * @return string the processed text.
+ * @param string $text The content that may contain ULRs in need of rewriting.
+ * @param string $file The script that should be used to serve these files. pluginfile.php, draftfile.php, etc.
+ * @param int $contextid This parameter and the next two identify the file area to use.
+ * @param string $component
+ * @param string $filearea helps identify the file area.
+ * @param int $itemid helps identify the file area.
+ * @param array $options
+ * bool $options.forcehttps Force the user of https
+ * bool $options.reverse Reverse the behaviour of the function
+ * bool $options.includetoken Use a token for authentication
+ * string The processed text.
*/
function file_rewrite_pluginfile_urls($text, $file, $contextid, $component, $filearea, $itemid, array $options=null) {
- global $CFG;
+ global $CFG, $USER;
$options = (array)$options;
if (!isset($options['forcehttps'])) {
$options['forcehttps'] = false;
}
- if (!$CFG->slasharguments) {
- $file = $file . '?file=';
+ $baseurl = "{$CFG->wwwroot}/{$file}";
+ if (!empty($options['includetoken'])) {
+ $token = get_user_key('core_files', $USER->id);
+ $finalfile = basename($file);
+ $tokenfile = "token{$finalfile}";
+ $file = substr($file, 0, strlen($file) - strlen($finalfile)) . $tokenfile;
+ $baseurl = "{$CFG->wwwroot}/{$file}";
+
+ if (!$CFG->slasharguments) {
+ $baseurl .= "?token={$token}&file=";
+ } else {
+ $baseurl .= "/{$token}";
+ }
}
- $baseurl = "$CFG->wwwroot/$file/$contextid/$component/$filearea/";
+ $baseurl .= "/{$contextid}/{$component}/{$filearea}/";
if ($itemid !== null) {
$baseurl .= "$itemid/";
}
}
+/**
+ * Finds all draft areas used in a textarea and copies the files into the primary textarea. If a user copies and pastes
+ * content from another draft area it's possible for a single textarea to reference multiple draft areas.
+ *
+ * @category files
+ * @param int $draftitemid the id of the primary draft area.
+ * @param int $usercontextid the user's context id.
+ * @param string $text some html content that needs to have files copied to the correct draft area.
+ * @param bool $forcehttps force https urls.
+ *
+ * @return string $text html content modified with new draft links
+ */
+function file_merge_draft_areas($draftitemid, $usercontextid, $text, $forcehttps = false) {
+ if (is_null($text)) {
+ return null;
+ }
+
+ $urls = extract_draft_file_urls_from_text($text, $forcehttps, $usercontextid, 'user', 'draft');
+
+ // No draft areas to rewrite.
+ if (empty($urls)) {
+ return $text;
+ }
+
+ foreach ($urls as $url) {
+ // Do not process the "home" draft area.
+ if ($url['itemid'] == $draftitemid) {
+ continue;
+ }
+
+ // Decode the filename.
+ $filename = urldecode($url['filename']);
+
+ // Copy the file.
+ file_copy_file_to_file_area($url, $filename, $draftitemid);
+
+ // Rewrite draft area.
+ $text = file_replace_file_area_in_text($url, $draftitemid, $text, $forcehttps);
+ }
+ return $text;
+}
+
+/**
+ * Rewrites a file area in arbitrary text.
+ *
+ * @param array $file General information about the file.
+ * @param int $newid The new file area itemid.
+ * @param string $text The text to rewrite.
+ * @param bool $forcehttps force https urls.
+ * @return string The rewritten text.
+ */
+function file_replace_file_area_in_text($file, $newid, $text, $forcehttps = false) {
+ global $CFG;
+
+ $wwwroot = $CFG->wwwroot;
+ if ($forcehttps) {
+ $wwwroot = str_replace('http://', 'https://', $wwwroot);
+ }
+
+ $search = [
+ $wwwroot,
+ $file['urlbase'],
+ $file['contextid'],
+ $file['component'],
+ $file['filearea'],
+ $file['itemid'],
+ $file['filename']
+ ];
+ $replace = [
+ $wwwroot,
+ $file['urlbase'],
+ $file['contextid'],
+ $file['component'],
+ $file['filearea'],
+ $newid,
+ $file['filename']
+ ];
+
+ $text = str_ireplace( implode('/', $search), implode('/', $replace), $text);
+ return $text;
+}
+
+/**
+ * Copies a file from one file area to another.
+ *
+ * @param array $file Information about the file to be copied.
+ * @param string $filename The filename.
+ * @param int $itemid The new file area.
+ */
+function file_copy_file_to_file_area($file, $filename, $itemid) {
+ $fs = get_file_storage();
+
+ // Load the current file in the old draft area.
+ $fileinfo = array(
+ 'component' => $file['component'],
+ 'filearea' => $file['filearea'],
+ 'itemid' => $file['itemid'],
+ 'contextid' => $file['contextid'],
+ 'filepath' => '/',
+ 'filename' => $filename
+ );
+ $oldfile = $fs->get_file($fileinfo['contextid'], $fileinfo['component'], $fileinfo['filearea'],
+ $fileinfo['itemid'], $fileinfo['filepath'], $fileinfo['filename']);
+ $newfileinfo = array(
+ 'component' => $file['component'],
+ 'filearea' => $file['filearea'],
+ 'itemid' => $itemid,
+ 'contextid' => $file['contextid'],
+ 'filepath' => '/',
+ 'filename' => $filename
+ );
+
+ $newcontextid = $newfileinfo['contextid'];
+ $newcomponent = $newfileinfo['component'];
+ $newfilearea = $newfileinfo['filearea'];
+ $newitemid = $newfileinfo['itemid'];
+ $newfilepath = $newfileinfo['filepath'];
+ $newfilename = $newfileinfo['filename'];
+
+ // Check if the file exists.
+ if (!$fs->file_exists($newcontextid, $newcomponent, $newfilearea, $newitemid, $newfilepath, $newfilename)) {
+ $fs->create_file_from_storedfile($newfileinfo, $oldfile);
+ }
+}
+
/**
* Saves files from a draft file area to a real one (merging the list of files).
* Can rewrite URLs in some content at the same time if desired.
$allowreferences = false;
}
+ // Check if the user has copy-pasted from other draft areas. Those files will be located in different draft
+ // areas and need to be copied into the current draft area.
+ $text = file_merge_draft_areas($draftitemid, $usercontext->id, $text, $forcehttps);
+
// Check if the draft area has exceeded the authorised limit. This should never happen as validation
// should have taken place before, unless the user is doing something nauthly. If so, let's just not save
// anything at all in the next area.
*
* Contains HTML class for htmleditor type element
*
+ * @deprecated since 3.6
* @package core_form
* @copyright 2006 Jamie Pratt <me@jamiep.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* or an associative array
*/
public function __construct($elementName=null, $elementLabel=null, $options=array(), $attributes=null){
+ debugging("The form element 'htmleditor' has been deprecated. Please use the 'editor' element instead.", DEBUG_DEVELOPER);
+
parent::__construct($elementName, $elementLabel, $attributes);
// set the options, do not bother setting bogus ones
if (is_array($options)) {
*
* @return string
*/
- function toHtml(){
+ public function toHtml() {
+ global $OUTPUT;
+
if ($this->_flagFrozen) {
return $this->getFrozenHtml();
} else {
+ $value = preg_replace("/(\r\n|\n|\r)/", '
', $this->getValue());
+
return $this->_getTabs() .
- print_textarea(true,
- $this->_options['rows'],
- $this->_options['cols'],
- $this->_options['width'],
- $this->_options['height'],
- $this->getName(),
- preg_replace("/(\r\n|\n|\r)/", '
',$this->getValue()),
- 0, // unused anymore
- true,
- $this->getAttribute('id'));
+ $OUTPUT->print_textarea($this->getName(), $this->getAttribute('id'), $value, $this->_options['rows'],
+ $this->_options['cols']);
}
}
* Note: processor failure is is not reported as false return value,
* earlier versions did not do it consistently either.
*
- * @todo MDL-55449 Drop support for stdClass in Moodle 3.6
* @category message
* @param \core\message\message $eventdata information about the message (component, userfrom, userto, ...)
* @return mixed the integer ID of the new message or false if there was a problem with submitted data
*/
-function message_send($eventdata) {
+function message_send(\core\message\message $eventdata) {
global $CFG, $DB;
- // TODO MDL-55449 Drop support for stdClass in Moodle 3.6.
- if ($eventdata instanceof \stdClass) {
- if (!isset($eventdata->courseid)) {
- $eventdata->courseid = null;
- }
-
- debugging('eventdata as \stdClass is deprecated. Please use core\message\message instead.', DEBUG_DEVELOPER);
- }
-
//new message ID to return
$messageid = false;
* @uses PARAM_ALPHANUM
* @param string $script unique script identifier
* @param int $instance optional instance id
+ * @param string $keyvalue The key. If not supplied, this will be fetched from the current session.
* @return int Instance ID
*/
-function require_user_key_login($script, $instance=null) {
+function require_user_key_login($script, $instance = null, $keyvalue = null) {
global $DB;
if (!NO_MOODLE_COOKIES) {
// Extra safety.
\core\session\manager::write_close();
- $keyvalue = required_param('key', PARAM_ALPHANUM);
+ if (null === $keyvalue) {
+ $keyvalue = required_param('key', PARAM_ALPHANUM);
+ }
$key = validate_user_key($keyvalue, $script, $instance);
include_once("$moddir/lib.php"); // Shows php warning only if plugin defective.
$moddelete = $modname .'_delete_instance'; // Delete everything connected to an instance.
- $moddeletecourse = $modname .'_delete_course'; // Delete other stray stuff (uncommon).
if ($instances) {
foreach ($instances as $cm) {
}
}
}
- if (function_exists($moddeletecourse)) {
- // Execute optional course cleanup callback. Deprecated since Moodle 3.2. TODO MDL-53297 remove in 3.6.
- debugging("Callback delete_course is deprecated. Function $moddeletecourse should be converted " .
- 'to observer of event \core\event\course_content_deleted', DEBUG_DEVELOPER);
- $moddeletecourse($course, $showfeedback);
- }
if ($instances and $showfeedback) {
echo $OUTPUT->notification($strdeleted.get_string('pluginname', $modname), 'notifysuccess');
}
echo $OUTPUT->notification($strdeleted.get_string('type_mod_plural', 'plugin'), 'notifysuccess');
}
- // Cleanup the rest of plugins. Deprecated since Moodle 3.2. TODO MDL-53297 remove in 3.6.
- $cleanuplugintypes = array('report', 'coursereport', 'format');
- $callbacks = get_plugins_with_function('delete_course', 'lib.php');
- foreach ($cleanuplugintypes as $type) {
- if (!empty($callbacks[$type])) {
- foreach ($callbacks[$type] as $pluginfunction) {
- debugging("Callback delete_course is deprecated. Function $pluginfunction should be converted " .
- 'to observer of event \core\event\course_content_deleted', DEBUG_DEVELOPER);
- $pluginfunction($course->id, $showfeedback);
- }
- if ($showfeedback) {
- echo $OUTPUT->notification($strdeleted.get_string('type_'.$type.'_plural', 'plugin'), 'notifysuccess');
- }
- }
- }
-
// Delete questions and question categories.
question_delete_course($course, $showfeedback);
if ($showfeedback) {
$translist = array();
} else {
$translist = explode(',', $CFG->langlist);
+ $translist = array_map('trim', $translist);
}
if (!empty($CFG->config_php_settings['customstringmanager'])) {
*/
public $includefullname = false;
+ /**
+ * @var bool Include user authentication token.
+ */
+ public $includetoken = false;
+
/**
* User picture constructor.
*
$path .= $page->theme->name.'/';
}
// Set the image URL to the URL for the uploaded file and return.
- $url = moodle_url::make_pluginfile_url($contextid, 'user', 'icon', NULL, $path, $filename);
+ $url = moodle_url::make_pluginfile_url(
+ $contextid, 'user', 'icon', null, $path, $filename, false, $this->includetoken);
$url->param('rev', $this->user->picture);
return $url;
}
return $this->render($menu);
}
+ /**
+ * Returns the HTML for a basic textarea field.
+ *
+ * @param string $name Name to use for the textarea element
+ * @param string $id The id to use fort he textarea element
+ * @param string $value Initial content to display in the textarea
+ * @param int $rows Number of rows to display
+ * @param int $cols Number of columns to display
+ * @return string the HTML to display
+ */
+ public function print_textarea($name, $id, $value, $rows, $cols) {
+ global $OUTPUT;
+
+ editors_head_setup();
+ $editor = editors_get_preferred_editor(FORMAT_HTML);
+ $editor->set_text($value);
+ $editor->use_editor($id, []);
+
+ $context = [
+ 'id' => $id,
+ 'name' => $name,
+ 'value' => $value,
+ 'rows' => $rows,
+ 'cols' => $cols
+ ];
+
+ return $OUTPUT->render_from_template('core_form/editor_textarea', $context);
+ }
+
/**
* Renders an action menu component.
*
* - class = image class attribute (default 'userpicture')
* - visibletoscreenreaders=true (whether to be visible to screen readers)
* - includefullname=false (whether to include the user's full name together with the user picture)
+ * - includetoken = false
* @return string HTML fragment
*/
public function user_picture(stdClass $user, array $options = null) {
class behat_transformations extends behat_base {
/**
- * Transformations for TableNode arguments.
- *
- * Transformations applicable to TableNode arguments should also
- * be applied, adding them in a different method for Behat API restrictions.
- *
- * @deprecated since Moodle 3.2 MDL-56335 - please do not use this function any more.
- * @param TableNode $tablenode
- * @return TableNode The transformed table
+ * @deprecated since Moodle 3.2
*/
- public function prefixed_tablenode_transformations(TableNode $tablenode) {
- debugging('prefixed_tablenode_transformations() is deprecated. Please use tablenode_transformations() instead.',
- DEBUG_DEVELOPER);
-
- return $this->tablenode_transformations($tablenode);
+ public function prefixed_tablenode_transformations() {
+ throw new coding_exception('prefixed_tablenode_transformations() can not be used anymore. ' .
+ 'Please use tablenode_transformations() instead.');
}
/**
*/
class core_csslib_testcase extends advanced_testcase {
- public function test_background() {
- $optimiser = new css_optimiser();
-
- $cssin = '.test {background-color: #123456;}';
- $this->assertSame($cssin, $optimiser->process($cssin));
- $this->assertDebuggingCalled('class css_optimiser is deprecated and no longer does anything, '
- . 'please consider using stylelint to optimise your css.');
- }
-
-
/**
- * Test CSS colour matching.
+ * Test that css_is_colour function throws an exception.
*/
public function test_css_is_colour() {
- $debugstr = 'css_is_colour() is deprecated without a replacement. Please copy the implementation '
- . 'into your plugin if you need this functionality.';
- // First lets test hex colours.
- $this->assertTrue(css_is_colour('#123456'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('#123'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('#ABCDEF'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('#ABC'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('#abcdef'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('#abc'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('#aBcDeF'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('#aBc'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('#1a2Bc3'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('#1Ac'));
- $this->assertDebuggingCalled($debugstr);
-
- // Note the following two colour's aren't really colours but browsers process
- // them still.
- $this->assertTrue(css_is_colour('#A'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('#12'));
- $this->assertDebuggingCalled($debugstr);
- // Having four or five characters however are not valid colours and
- // browsers don't parse them. They need to fail so that broken CSS
- // stays broken after optimisation.
- $this->assertFalse(css_is_colour('#1234'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_colour('#12345'));
- $this->assertDebuggingCalled($debugstr);
-
- $this->assertFalse(css_is_colour('#BCDEFG'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_colour('#'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_colour('#0000000'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_colour('#132-245'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_colour('#13 23 43'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_colour('123456'));
- $this->assertDebuggingCalled($debugstr);
-
- // Next lets test real browser mapped colours.
- $this->assertTrue(css_is_colour('black'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('blue'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('BLACK'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('Black'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('bLACK'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('mediumaquamarine'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('mediumAquamarine'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_colour('monkey'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_colour(''));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_colour('not a colour'));
- $this->assertDebuggingCalled($debugstr);
-
- // Next lets test rgb(a) colours.
- $this->assertTrue(css_is_colour('rgb(255,255,255)'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('rgb(0, 0, 0)'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('RGB (255, 255 , 255)'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('rgba(0,0,0,0)'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('RGBA(255,255,255,1)'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('rgbA(255,255,255,0.5)'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_colour('rgb(-255,-255,-255)'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_colour('rgb(256,-256,256)'));
- $this->assertDebuggingCalled($debugstr);
-
- // Now lets test HSL colours.
- $this->assertTrue(css_is_colour('hsl(0,0%,100%)'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('hsl(180, 0%, 10%)'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_colour('hsl (360, 100% , 95%)'));
- $this->assertDebuggingCalled($debugstr);
-
- // Finally test the special values.
- $this->assertTrue(css_is_colour('inherit'));
- $this->assertDebuggingCalled($debugstr);
+ $this->expectException('coding_exception');
+ $this->expectExceptionMessage('css_is_colour() can not be used anymore.');
+ css_is_colour();
}
/**
- * Test the css_is_width function.
+ * Test that css_is_width function throws an exception.
*/
public function test_css_is_width() {
- $debugstr = 'css_is_width() is deprecated without a replacement. Please copy the implementation '
- . 'into your plugin if you need this functionality.';
- $this->assertTrue(css_is_width('0'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_width('0px'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_width('0em'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_width('199px'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_width('199em'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_width('199%'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_width('-1px'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_width('auto'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertTrue(css_is_width('inherit'));
- $this->assertDebuggingCalled($debugstr);
-
- // Valid widths but missing their unit specifier.
- $this->assertFalse(css_is_width('0.75'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_width('3'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_width('-1'));
- $this->assertDebuggingCalled($debugstr);
-
- // Totally invalid widths.
- $this->assertFalse(css_is_width('-'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_width('bananas'));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_width(''));
- $this->assertDebuggingCalled($debugstr);
- $this->assertFalse(css_is_width('top'));
- $this->assertDebuggingCalled($debugstr);
+ $this->expectException('coding_exception');
+ $this->expectExceptionMessage('css_is_width() can not be used anymore.');
+ css_is_width();
}
}
$this->assertEquals($originaltext, $finaltext);
}
+ /**
+ * Test file_rewrite_pluginfile_urls with includetoken.
+ */
+ public function test_file_rewrite_pluginfile_urls_includetoken() {
+ global $USER, $CFG;
+
+ $CFG->slasharguments = true;
+
+ $this->resetAfterTest();
+
+ $syscontext = context_system::instance();
+ $originaltext = 'Fake test with an image <img src="@@PLUGINFILE@@/image.png">';
+ $options = ['includetoken' => true];
+
+ // Rewrite the content. This will generate a new token.
+ $finaltext = file_rewrite_pluginfile_urls(
+ $originaltext, 'pluginfile.php', $syscontext->id, 'user', 'private', 0, $options);
+
+ $token = get_user_key('core_files', $USER->id);
+ $expectedurl = new \moodle_url("/tokenpluginfile.php/{$token}/{$syscontext->id}/user/private/0/image.png");
+ $expectedtext = "Fake test with an image <img src=\"{$expectedurl}\">";
+ $this->assertEquals($expectedtext, $finaltext);
+
+ // Do it again - the second time will use an existing token.
+ $finaltext = file_rewrite_pluginfile_urls(
+ $originaltext, 'pluginfile.php', $syscontext->id, 'user', 'private', 0, $options);
+ $this->assertEquals($expectedtext, $finaltext);
+
+ // Now undo.
+ $options['reverse'] = true;
+ $finaltext = file_rewrite_pluginfile_urls($finaltext, 'pluginfile.php', $syscontext->id, 'user', 'private', 0, $options);
+
+ // Compare the final text is the same that the original.
+ $this->assertEquals($originaltext, $finaltext);
+ }
+
+ /**
+ * Test file_rewrite_pluginfile_urls with includetoken with slasharguments disabled..
+ */
+ public function test_file_rewrite_pluginfile_urls_includetoken_no_slashargs() {
+ global $USER, $CFG;
+
+ $CFG->slasharguments = false;
+
+ $this->resetAfterTest();
+
+ $syscontext = context_system::instance();
+ $originaltext = 'Fake test with an image <img src="@@PLUGINFILE@@/image.png">';
+ $options = ['includetoken' => true];
+
+ // Rewrite the content. This will generate a new token.
+ $finaltext = file_rewrite_pluginfile_urls(
+ $originaltext, 'pluginfile.php', $syscontext->id, 'user', 'private', 0, $options);
+
+ $token = get_user_key('core_files', $USER->id);
+ $expectedurl = new \moodle_url("/tokenpluginfile.php");
+ $expectedurl .= "?token={$token}&file=/{$syscontext->id}/user/private/0/image.png";
+ $expectedtext = "Fake test with an image <img src=\"{$expectedurl}\">";
+ $this->assertEquals($expectedtext, $finaltext);
+
+ // Do it again - the second time will use an existing token.
+ $finaltext = file_rewrite_pluginfile_urls(
+ $originaltext, 'pluginfile.php', $syscontext->id, 'user', 'private', 0, $options);
+ $this->assertEquals($expectedtext, $finaltext);
+
+ // Now undo.
+ $options['reverse'] = true;
+ $finaltext = file_rewrite_pluginfile_urls($finaltext, 'pluginfile.php', $syscontext->id, 'user', 'private', 0, $options);
+
+ // Compare the final text is the same that the original.
+ $this->assertEquals($originaltext, $finaltext);
+ }
+
/**
* Helpter function to create draft files
*
$this->assertEquals($fourthrecord['filename'], $allfiles[3]->filename);
$this->assertEquals($fifthrecord['filename'], $allfiles[4]->filename);
}
+
+ public function test_file_copy_file_to_file_area() {
+ // Create two files in different draft areas but owned by the same user.
+ global $USER;
+ $this->resetAfterTest(true);
+ $this->setAdminUser();
+
+ $filerecord = ['filename' => 'file1.png', 'itemid' => file_get_unused_draft_itemid()];
+ $file1 = self::create_draft_file($filerecord);
+ $filerecord = ['filename' => 'file2.png', 'itemid' => file_get_unused_draft_itemid()];
+ $file2 = self::create_draft_file($filerecord);
+
+ // Confirm one file in each draft area.
+ $fs = get_file_storage();
+ $usercontext = context_user::instance($USER->id);
+ $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $file1->get_itemid(), 'itemid', 0);
+ $this->assertCount(1, $draftfiles);
+ $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $file2->get_itemid(), 'itemid', 0);
+ $this->assertCount(1, $draftfiles);
+
+ // Create file record.
+ $filerecord = [
+ 'component' => $file2->get_component(),
+ 'filearea' => $file2->get_filearea(),
+ 'itemid' => $file2->get_itemid(),
+ 'contextid' => $file2->get_contextid(),
+ 'filepath' => '/',
+ 'filename' => $file2->get_filename()
+ ];
+
+ // Copy file2 into file1's draft area.
+ file_copy_file_to_file_area($filerecord, $file2->get_filename(), $file1->get_itemid());
+ $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $file1->get_itemid(), 'itemid', 0);
+ $this->assertCount(2, $draftfiles);
+ $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $file2->get_itemid(), 'itemid', 0);
+ $this->assertCount(1, $draftfiles);
+ }
}
/**
--- /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/>.
+
+/**
+ * Tests for moodle_url.
+ *
+ * @package core
+ * @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Tests for moodle_url.
+ *
+ * @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class core_moodle_url_testcase extends advanced_testcase {
+ /**
+ * Test basic moodle_url construction.
+ */
+ public function test_moodle_url_constructor() {
+ global $CFG;
+
+ $url = new moodle_url('/index.php');
+ $this->assertSame($CFG->wwwroot.'/index.php', $url->out());
+
+ $url = new moodle_url('/index.php', array());
+ $this->assertSame($CFG->wwwroot.'/index.php', $url->out());
+
+ $url = new moodle_url('/index.php', array('id' => 2));
+ $this->assertSame($CFG->wwwroot.'/index.php?id=2', $url->out());
+
+ $url = new moodle_url('/index.php', array('id' => 'two'));
+ $this->assertSame($CFG->wwwroot.'/index.php?id=two', $url->out());
+
+ $url = new moodle_url('/index.php', array('id' => 1, 'cid' => '2'));
+ $this->assertSame($CFG->wwwroot.'/index.php?id=1&cid=2', $url->out());
+ $this->assertSame($CFG->wwwroot.'/index.php?id=1&cid=2', $url->out(false));
+
+ $url = new moodle_url('/index.php', null, 'test');
+ $this->assertSame($CFG->wwwroot.'/index.php#test', $url->out());
+
+ $url = new moodle_url('/index.php', array('id' => 2), 'test');
+ $this->assertSame($CFG->wwwroot.'/index.php?id=2#test', $url->out());
+ }
+
+ /**
+ * Tests moodle_url::get_path().
+ */
+ public function test_moodle_url_get_path() {
+ $url = new moodle_url('http://www.example.org:447/my/file/is/here.txt?really=1');
+ $this->assertSame('/my/file/is/here.txt', $url->get_path());
+
+ $url = new moodle_url('http://www.example.org/');
+ $this->assertSame('/', $url->get_path());
+
+ $url = new moodle_url('http://www.example.org/pluginfile.php/slash/arguments');
+ $this->assertSame('/pluginfile.php/slash/arguments', $url->get_path());
+ $this->assertSame('/pluginfile.php', $url->get_path(false));
+ }
+
+ public function test_moodle_url_round_trip() {
+ $strurl = 'http://moodle.org/course/view.php?id=5';
+ $url = new moodle_url($strurl);
+ $this->assertSame($strurl, $url->out(false));
+
+ $strurl = 'http://moodle.org/user/index.php?contextid=53&sifirst=M&silast=D';
+ $url = new moodle_url($strurl);
+ $this->assertSame($strurl, $url->out(false));
+ }
+
+ /**
+ * Test Moodle URL objects created with a param with empty value.
+ */
+ public function test_moodle_url_empty_param_values() {
+ $strurl = 'http://moodle.org/course/view.php?id=0';
+ $url = new moodle_url($strurl, array('id' => 0));
+ $this->assertSame($strurl, $url->out(false));
+
+ $strurl = 'http://moodle.org/course/view.php?id';
+ $url = new moodle_url($strurl, array('id' => false));
+ $this->assertSame($strurl, $url->out(false));
+
+ $strurl = 'http://moodle.org/course/view.php?id';
+ $url = new moodle_url($strurl, array('id' => null));
+ $this->assertSame($strurl, $url->out(false));
+
+ $strurl = 'http://moodle.org/course/view.php?id';
+ $url = new moodle_url($strurl, array('id' => ''));
+ $this->assertSame($strurl, $url->out(false));
+
+ $strurl = 'http://moodle.org/course/view.php?id';
+ $url = new moodle_url($strurl);
+ $this->assertSame($strurl, $url->out(false));
+ }
+
+ /**
+ * Test set good scheme on Moodle URL objects.
+ */
+ public function test_moodle_url_set_good_scheme() {
+ $url = new moodle_url('http://moodle.org/foo/bar');
+ $url->set_scheme('myscheme');
+ $this->assertSame('myscheme://moodle.org/foo/bar', $url->out());
+ }
+
+ /**
+ * Test set bad scheme on Moodle URL objects.
+ *
+ * @expectedException coding_exception
+ */
+ public function test_moodle_url_set_bad_scheme() {
+ $url = new moodle_url('http://moodle.org/foo/bar');
+ $url->set_scheme('not a valid $ scheme');
+ }
+
+ public function test_moodle_url_round_trip_array_params() {
+ $strurl = 'http://example.com/?a%5B1%5D=1&a%5B2%5D=2';
+ $url = new moodle_url($strurl);
+ $this->assertSame($strurl, $url->out(false));
+
+ $url = new moodle_url('http://example.com/?a[1]=1&a[2]=2');
+ $this->assertSame($strurl, $url->out(false));
+
+ // For un-keyed array params, we expect 0..n keys to be returned.
+ $strurl = 'http://example.com/?a%5B0%5D=0&a%5B1%5D=1';
+ $url = new moodle_url('http://example.com/?a[]=0&a[]=1');
+ $this->assertSame($strurl, $url->out(false));
+ }
+
+ public function test_compare_url() {
+ $url1 = new moodle_url('index.php', array('var1' => 1, 'var2' => 2));
+ $url2 = new moodle_url('index2.php', array('var1' => 1, 'var2' => 2, 'var3' => 3));
+
+ $this->assertFalse($url1->compare($url2, URL_MATCH_BASE));
+ $this->assertFalse($url1->compare($url2, URL_MATCH_PARAMS));
+ $this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
+
+ $url2 = new moodle_url('index.php', array('var1' => 1, 'var3' => 3));
+
+ $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
+ $this->assertFalse($url1->compare($url2, URL_MATCH_PARAMS));
+ $this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
+
+ $url2 = new moodle_url('index.php', array('var1' => 1, 'var2' => 2, 'var3' => 3));
+
+ $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
+ $this->assertTrue($url1->compare($url2, URL_MATCH_PARAMS));
+ $this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
+
+ $url2 = new moodle_url('index.php', array('var2' => 2, 'var1' => 1));
+
+ $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
+ $this->assertTrue($url1->compare($url2, URL_MATCH_PARAMS));
+ $this->assertTrue($url1->compare($url2, URL_MATCH_EXACT));
+
+ $url1->set_anchor('test');
+ $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
+ $this->assertTrue($url1->compare($url2, URL_MATCH_PARAMS));
+ $this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
+
+ $url2->set_anchor('test');
+ $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
+ $this->assertTrue($url1->compare($url2, URL_MATCH_PARAMS));
+ $this->assertTrue($url1->compare($url2, URL_MATCH_EXACT));
+ }
+
+ public function test_out_as_local_url() {
+ global $CFG;
+ // Test http url.
+ $url1 = new moodle_url('/lib/tests/weblib_test.php');
+ $this->assertSame('/lib/tests/weblib_test.php', $url1->out_as_local_url());
+
+ // Test https url.
+ $httpswwwroot = str_replace("http://", "https://", $CFG->wwwroot);
+ $url2 = new moodle_url($httpswwwroot.'/login/profile.php');
+ $this->assertSame('/login/profile.php', $url2->out_as_local_url());
+
+ // Test http url matching wwwroot.
+ $url3 = new moodle_url($CFG->wwwroot);
+ $this->assertSame('', $url3->out_as_local_url());
+
+ // Test http url matching wwwroot ending with slash (/).
+ $url3 = new moodle_url($CFG->wwwroot.'/');
+ $this->assertSame('/', $url3->out_as_local_url());
+ }
+
+ /**
+ * @expectedException coding_exception
+ * @return void
+ */
+ public function test_out_as_local_url_error() {
+ $url2 = new moodle_url('http://www.google.com/lib/tests/weblib_test.php');
+ $url2->out_as_local_url();
+ }
+
+ /**
+ * You should get error with modified url
+ *
+ * @expectedException coding_exception
+ * @return void
+ */
+ public function test_modified_url_out_as_local_url_error() {
+ global $CFG;
+
+ $modifiedurl = $CFG->wwwroot.'1';
+ $url3 = new moodle_url($modifiedurl.'/login/profile.php');
+ $url3->out_as_local_url();
+ }
+
+ /**
+ * Try get local url from external https url and you should get error
+ *
+ * @expectedException coding_exception
+ */
+ public function test_https_out_as_local_url_error() {
+ $url4 = new moodle_url('https://www.google.com/lib/tests/weblib_test.php');
+ $url4->out_as_local_url();
+ }
+
+ public function test_moodle_url_get_scheme() {
+ // Should return the scheme only.
+ $url = new moodle_url('http://www.example.org:447/my/file/is/here.txt?really=1');
+ $this->assertSame('http', $url->get_scheme());
+
+ // Should work for secure URLs.
+ $url = new moodle_url('https://www.example.org:447/my/file/is/here.txt?really=1');
+ $this->assertSame('https', $url->get_scheme());
+
+ // Should return an empty string if no scheme is specified.
+ $url = new moodle_url('www.example.org:447/my/file/is/here.txt?really=1');
+ $this->assertSame('', $url->get_scheme());
+ }
+
+ public function test_moodle_url_get_host() {
+ // Should return the host part only.
+ $url = new moodle_url('http://www.example.org:447/my/file/is/here.txt?really=1');
+ $this->assertSame('www.example.org', $url->get_host());
+ }
+
+ public function test_moodle_url_get_port() {
+ // Should return the port if one provided.
+ $url = new moodle_url('http://www.example.org:447/my/file/is/here.txt?really=1');
+ $this->assertSame(447, $url->get_port());
+
+ // Should return an empty string if port not specified.
+ $url = new moodle_url('http://www.example.org/some/path/here.php');
+ $this->assertSame('', $url->get_port());
+ }
+
+ /**
+ * Test the make_pluginfile_url function.
+ *
+ * @dataProvider make_pluginfile_url_provider
+ * @param bool $slashargs
+ * @param array $args Args to be provided to make_pluginfile_url
+ * @param string $expected The expected result
+ */
+ public function test_make_pluginfile_url($slashargs, $args, $expected) {
+ global $CFG;
+
+ $this->resetAfterTest();
+
+ $CFG->slasharguments = $slashargs;
+ $url = call_user_func_array('moodle_url::make_pluginfile_url', $args);
+ $this->assertRegexp($expected, $url->out(true));
+ }
+
+ /**
+ * Data provider for make_pluginfile_url tests.
+ *
+ * @return array[]
+ */
+ public function make_pluginfile_url_provider() {
+ $baseurl = "https://www.example.com/moodle/pluginfile.php";
+ $tokenbaseurl = "https://www.example.com/moodle/tokenpluginfile.php";
+ return [
+ 'Standard with slashargs' => [
+ 'slashargs' => true,
+ 'args' => [
+ 1,
+ 'mod_forum',
+ 'posts',
+ 422,
+ '/my/location/',
+ 'file.png',
+ ],
+ 'expected' => "@{$baseurl}/1/mod_forum/posts/422/my/location/file.png@",
+ ],
+ 'Standard without slashargs' => [
+ 'slashargs' => false,
+ 'args' => [
+ 1,
+ 'mod_forum',
+ 'posts',
+ 422,
+ '/my/location/',
+ 'file.png',
+ ],
+ 'expected' => "@{$baseurl}\?file=%2F1%2Fmod_forum%2Fposts%2F422%2Fmy%2Flocation%2Ffile.png@",
+ ],
+ 'Token included with slashargs' => [
+ 'slashargs' => true,
+ 'args' => [
+ 1,
+ 'mod_forum',
+ 'posts',
+ 422,
+ '/my/location/',
+ 'file.png',
+ false,
+ true,
+ ],
+ 'expected' => "@{$tokenbaseurl}/[^/]*/1/mod_forum/posts/422/my/location/file.png@",
+ ],
+ 'Token included without slashargs' => [
+ 'slashargs' => false,
+ 'args' => [
+ 1,
+ 'mod_forum',
+ 'posts',
+ 422,
+ '/my/location/',
+ 'file.png',
+ false,
+ true,
+ ],
+ 'expected' => "@{$tokenbaseurl}\?file=%2F1%2Fmod_forum%2Fposts%2F422%2Fmy%2Flocation%2Ffile.png&token=[a-z0-9]*@",
+ ],
+ ];
+ }
+}
$this->assertSame('this is a link [ http://someaddress.com/query ]', wikify_links('this is a <a href="http://someaddress.com/query">link</a>'));
}
- /**
- * Test basic moodle_url construction.
- */
- public function test_moodle_url_constructor() {
- global $CFG;
-
- $url = new moodle_url('/index.php');
- $this->assertSame($CFG->wwwroot.'/index.php', $url->out());
-
- $url = new moodle_url('/index.php', array());
- $this->assertSame($CFG->wwwroot.'/index.php', $url->out());
-
- $url = new moodle_url('/index.php', array('id' => 2));
- $this->assertSame($CFG->wwwroot.'/index.php?id=2', $url->out());
-
- $url = new moodle_url('/index.php', array('id' => 'two'));
- $this->assertSame($CFG->wwwroot.'/index.php?id=two', $url->out());
-
- $url = new moodle_url('/index.php', array('id' => 1, 'cid' => '2'));
- $this->assertSame($CFG->wwwroot.'/index.php?id=1&cid=2', $url->out());
- $this->assertSame($CFG->wwwroot.'/index.php?id=1&cid=2', $url->out(false));
-
- $url = new moodle_url('/index.php', null, 'test');
- $this->assertSame($CFG->wwwroot.'/index.php#test', $url->out());
-
- $url = new moodle_url('/index.php', array('id' => 2), 'test');
- $this->assertSame($CFG->wwwroot.'/index.php?id=2#test', $url->out());
- }
-
- /**
- * Tests moodle_url::get_path().
- */
- public function test_moodle_url_get_path() {
- $url = new moodle_url('http://www.example.org:447/my/file/is/here.txt?really=1');
- $this->assertSame('/my/file/is/here.txt', $url->get_path());
-
- $url = new moodle_url('http://www.example.org/');
- $this->assertSame('/', $url->get_path());
-
- $url = new moodle_url('http://www.example.org/pluginfile.php/slash/arguments');
- $this->assertSame('/pluginfile.php/slash/arguments', $url->get_path());
- $this->assertSame('/pluginfile.php', $url->get_path(false));
- }
-
- public function test_moodle_url_round_trip() {
- $strurl = 'http://moodle.org/course/view.php?id=5';
- $url = new moodle_url($strurl);
- $this->assertSame($strurl, $url->out(false));
-
- $strurl = 'http://moodle.org/user/index.php?contextid=53&sifirst=M&silast=D';
- $url = new moodle_url($strurl);
- $this->assertSame($strurl, $url->out(false));
- }
-
- /**
- * Test Moodle URL objects created with a param with empty value.
- */
- public function test_moodle_url_empty_param_values() {
- $strurl = 'http://moodle.org/course/view.php?id=0';
- $url = new moodle_url($strurl, array('id' => 0));
- $this->assertSame($strurl, $url->out(false));
-
- $strurl = 'http://moodle.org/course/view.php?id';
- $url = new moodle_url($strurl, array('id' => false));
- $this->assertSame($strurl, $url->out(false));
-
- $strurl = 'http://moodle.org/course/view.php?id';
- $url = new moodle_url($strurl, array('id' => null));
- $this->assertSame($strurl, $url->out(false));
-
- $strurl = 'http://moodle.org/course/view.php?id';
- $url = new moodle_url($strurl, array('id' => ''));
- $this->assertSame($strurl, $url->out(false));
-
- $strurl = 'http://moodle.org/course/view.php?id';
- $url = new moodle_url($strurl);
- $this->assertSame($strurl, $url->out(false));
- }
-
- /**
- * Test set good scheme on Moodle URL objects.
- */
- public function test_moodle_url_set_good_scheme() {
- $url = new moodle_url('http://moodle.org/foo/bar');
- $url->set_scheme('myscheme');
- $this->assertSame('myscheme://moodle.org/foo/bar', $url->out());
- }
-
- /**
- * Test set bad scheme on Moodle URL objects.
- *
- * @expectedException coding_exception
- */
- public function test_moodle_url_set_bad_scheme() {
- $url = new moodle_url('http://moodle.org/foo/bar');
- $url->set_scheme('not a valid $ scheme');
- }
-
- public function test_moodle_url_round_trip_array_params() {
- $strurl = 'http://example.com/?a%5B1%5D=1&a%5B2%5D=2';
- $url = new moodle_url($strurl);
- $this->assertSame($strurl, $url->out(false));
-
- $url = new moodle_url('http://example.com/?a[1]=1&a[2]=2');
- $this->assertSame($strurl, $url->out(false));
-
- // For un-keyed array params, we expect 0..n keys to be returned.
- $strurl = 'http://example.com/?a%5B0%5D=0&a%5B1%5D=1';
- $url = new moodle_url('http://example.com/?a[]=0&a[]=1');
- $this->assertSame($strurl, $url->out(false));
- }
-
- public function test_compare_url() {
- $url1 = new moodle_url('index.php', array('var1' => 1, 'var2' => 2));
- $url2 = new moodle_url('index2.php', array('var1' => 1, 'var2' => 2, 'var3' => 3));
-
- $this->assertFalse($url1->compare($url2, URL_MATCH_BASE));
- $this->assertFalse($url1->compare($url2, URL_MATCH_PARAMS));
- $this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
-
- $url2 = new moodle_url('index.php', array('var1' => 1, 'var3' => 3));
-
- $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
- $this->assertFalse($url1->compare($url2, URL_MATCH_PARAMS));
- $this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
-
- $url2 = new moodle_url('index.php', array('var1' => 1, 'var2' => 2, 'var3' => 3));
-
- $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
- $this->assertTrue($url1->compare($url2, URL_MATCH_PARAMS));
- $this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
-
- $url2 = new moodle_url('index.php', array('var2' => 2, 'var1' => 1));
-
- $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
- $this->assertTrue($url1->compare($url2, URL_MATCH_PARAMS));
- $this->assertTrue($url1->compare($url2, URL_MATCH_EXACT));
-
- $url1->set_anchor('test');
- $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
- $this->assertTrue($url1->compare($url2, URL_MATCH_PARAMS));
- $this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
-
- $url2->set_anchor('test');
- $this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
- $this->assertTrue($url1->compare($url2, URL_MATCH_PARAMS));
- $this->assertTrue($url1->compare($url2, URL_MATCH_EXACT));
- }
-
- public function test_out_as_local_url() {
- global $CFG;
- // Test http url.
- $url1 = new moodle_url('/lib/tests/weblib_test.php');
- $this->assertSame('/lib/tests/weblib_test.php', $url1->out_as_local_url());
-
- // Test https url.
- $httpswwwroot = str_replace("http://", "https://", $CFG->wwwroot);
- $url2 = new moodle_url($httpswwwroot.'/login/profile.php');
- $this->assertSame('/login/profile.php', $url2->out_as_local_url());
-
- // Test http url matching wwwroot.
- $url3 = new moodle_url($CFG->wwwroot);
- $this->assertSame('', $url3->out_as_local_url());
-
- // Test http url matching wwwroot ending with slash (/).
- $url3 = new moodle_url($CFG->wwwroot.'/');
- $this->assertSame('/', $url3->out_as_local_url());
- }
-
- /**
- * @expectedException coding_exception
- * @return void
- */
- public function test_out_as_local_url_error() {
- $url2 = new moodle_url('http://www.google.com/lib/tests/weblib_test.php');
- $url2->out_as_local_url();
- }
-
- /**
- * You should get error with modified url
- *
- * @expectedException coding_exception
- * @return void
- */
- public function test_modified_url_out_as_local_url_error() {
- global $CFG;
-
- $modifiedurl = $CFG->wwwroot.'1';
- $url3 = new moodle_url($modifiedurl.'/login/profile.php');
- $url3->out_as_local_url();
- }
-
- /**
- * Try get local url from external https url and you should get error
- *
- * @expectedException coding_exception
- */
- public function test_https_out_as_local_url_error() {
- $url4 = new moodle_url('https://www.google.com/lib/tests/weblib_test.php');
- $url4->out_as_local_url();
- }
-
- public function test_moodle_url_get_scheme() {
- // Should return the scheme only.
- $url = new moodle_url('http://www.example.org:447/my/file/is/here.txt?really=1');
- $this->assertSame('http', $url->get_scheme());
-
- // Should work for secure URLs.
- $url = new moodle_url('https://www.example.org:447/my/file/is/here.txt?really=1');
- $this->assertSame('https', $url->get_scheme());
-
- // Should return an empty string if no scheme is specified.
- $url = new moodle_url('www.example.org:447/my/file/is/here.txt?really=1');
- $this->assertSame('', $url->get_scheme());
- }
-
- public function test_moodle_url_get_host() {
- // Should return the host part only.
- $url = new moodle_url('http://www.example.org:447/my/file/is/here.txt?really=1');
- $this->assertSame('www.example.org', $url->get_host());
- }
-
- public function test_moodle_url_get_port() {
- // Should return the port if one provided.
- $url = new moodle_url('http://www.example.org:447/my/file/is/here.txt?really=1');
- $this->assertSame(447, $url->get_port());
-
- // Should return an empty string if port not specified.
- $url = new moodle_url('http://www.example.org/some/path/here.php');
- $this->assertSame('', $url->get_port());
- }
-
public function test_clean_text() {
$text = "lala <applet>xx</applet>";
$this->assertSame($text, clean_text($text, FORMAT_PLAIN));
$_GET = $currentget;
}
}
+
+ /**
+ * Tests for extract_draft_file_urls_from_text() function.
+ */
+ public function test_extract_draft_file_urls_from_text() {
+ global $CFG;
+
+ $url1 = "{$CFG->wwwroot}/draftfile.php/5/user/draft/99999999/test1.jpg";
+ $url2 = "{$CFG->wwwroot}/draftfile.php/5/user/draft/99999998/test2.jpg";
+
+ $html = "<p>This is a test.</p><p><img src=\"${url1}\" alt=\"\" role=\"presentation\"></p>
+ <br>Test content.<p></p><p><img src=\"{$url2}\" alt=\"\" width=\"2048\" height=\"1536\"
+ role=\"presentation\" class=\"img-responsive atto_image_button_text-bottom\"><br></p>";
+ $draftareas = array(
+ array(
+ 'urlbase' => 'draftfile.php',
+ 'contextid' => '5',
+ 'component' => 'user',
+ 'filearea' => 'draft',
+ 'itemid' => '99999999',
+ 'filename' => 'test1.jpg',
+ 0 => "{$CFG->wwwroot}/draftfile.php/5/user/draft/99999999/test1.jpg",
+ 1 => 'draftfile.php',
+ 2 => '5',
+ 3 => 'user',
+ 4 => 'draft',
+ 5 => '99999999',
+ 6 => 'test1.jpg'
+ ),
+ array(
+ 'urlbase' => 'draftfile.php',
+ 'contextid' => '5',
+ 'component' => 'user',
+ 'filearea' => 'draft',
+ 'itemid' => '99999998',
+ 'filename' => 'test2.jpg',
+ 0 => "{$CFG->wwwroot}/draftfile.php/5/user/draft/99999998/test2.jpg",
+ 1 => 'draftfile.php',
+ 2 => '5',
+ 3 => 'user',
+ 4 => 'draft',
+ 5 => '99999998',
+ 6 => 'test2.jpg'
+ )
+ );
+ $extracteddraftareas = extract_draft_file_urls_from_text($html, false, 5, 'user', 'draft');
+ $this->assertEquals($draftareas, $extracteddraftareas);
+ }
}
=== 3.6 ===
+* A new token-based version of pluginfile.php has been added which can be used for out-of-session file serving by
+ setting the `$includetoken` parameter to true on the `moodle_url::make_pluginfile_url()`, and
+ `moodle_url::make_file_url()` functions.
+* The following picture functions have been updated to support use of the new token-based file serving:
+ - print_group_picture
+ - get_group_picture_url
+* The `user_picture` class has a new public `$includetoken` property which can be set to make use of the new token-based
+ file serving.
* Custom AJAX handlers for the form autocomplete fields can now optionally return string in their processResults()
callback. If a string is returned, it is displayed instead of the list of suggested items. This can be used, for
example, to inform the user that there are too many items matching the current search criteria.
+* The form element 'htmleditor' has been deprecated. Please use the 'editor' element instead.
+* The print_textarea() function has been deprecated. Please use $OUTPUT->print_textarea() instead.
* The following functions have been finally deprecated and can not be used any more:
- external_function_info()
- core_renderer::update_module_button()
- site_scale_used()
- clam_message_admins()
- get_clam_error_code()
-* The following classes have been finally deprecated and can not be used any more:
+ - get_records_csv()
+ - put_records_csv()
+ - print_log()
+ - print_mnet_log()
+ - print_log_csv()
+ - print_log_xls()
+ - print_log_ods()
+ - build_logs_array()
+ - get_logs_usercourse()
+ - get_logs_userday()
+ - get_logs()
+ - prevent_form_autofill_password()
+ - prefixed_tablenode_transformations()
- core_media_renderer
- core_media
* Following api's have been removed in behat_config_manager, please use behat_config_util instead.
policy and respect the privacy setting made by site administrators. The list of user identifiers should never be
hard-coded. Instead, the setting $CFG->showuseridentity should be always respected, which has always been the default
behaviour (MDL-59847).
+* The function message_send() in messagelib.php will now only take the object \core\message\message as a parameter.
+* The method message_sent::create_from_ids() parameter courseid is now required. A debugging
+ message was previously displayed, and the SITEID was used, when not provided.
+* The method \core\message\manager::send_message() now only takes the object \core\message\message as the first parameter.
+* Following functions have been deprecated, please use get_roles_used_in_context.
+ - get_roles_on_exact_context()
+ - get_roles_with_assignment_on_context()
+* New functions to support the merging of user draft areas from the interface; see MDL-45170 for details:
+ - file_copy_file_to_file_area()
+ - file_merge_draft_areas()
+ - file_replace_file_area_in_text()
+ - extract_draft_file_urls_from_text()
=== 3.5 ===
* @param string $pathname
* @param string $filename
* @param bool $forcedownload
+ * @param boolean $includetoken Whether to use a user token when displaying this group image.
+ * If the group picture is included in an e-mail or some other location where the audience is a specific
+ * user who will not be logged in when viewing, then we use a token to authenticate the user.
* @return moodle_url
*/
public static function make_pluginfile_url($contextid, $component, $area, $itemid, $pathname, $filename,
- $forcedownload = false) {
- global $CFG;
- $urlbase = "$CFG->wwwroot/pluginfile.php";
- if ($itemid === null) {
- return self::make_file_url($urlbase, "/$contextid/$component/$area".$pathname.$filename, $forcedownload);
+ $forcedownload = false, $includetoken = false) {
+ global $CFG, $USER;
+
+ $path = [];
+
+ if ($includetoken) {
+ $urlbase = "$CFG->wwwroot/tokenpluginfile.php";
+ $token = get_user_key('core_files', $USER->id);
+ if ($CFG->slasharguments) {
+ $path[] = $token;
+ }
} else {
- return self::make_file_url($urlbase, "/$contextid/$component/$area/$itemid".$pathname.$filename, $forcedownload);
+ $urlbase = "$CFG->wwwroot/pluginfile.php";
}
+ $path[] = $contextid;
+ $path[] = $component;
+ $path[] = $area;
+
+ if ($itemid !== null) {
+ $path[] = $itemid;
+ }
+
+ $path = "/" . implode('/', $path) . "{$pathname}{$filename}";
+
+ $url = self::make_file_url($urlbase, $path, $forcedownload, $includetoken);
+ if ($includetoken && empty($CFG->slasharguments)) {
+ $url->param('token', $token);
+ }
+ return $url;
}
/**
return trim($content, "\r\n ");
}
+/**
+ * Factory method for extracting draft file links from arbitrary text using regular expressions. Only text
+ * is required; other file fields may be passed to filter.
+ *
+ * @param string $text Some html content.
+ * @param bool $forcehttps force https urls.
+ * @param int $contextid This parameter and the next three identify the file area to save to.
+ * @param string $component The component name.
+ * @param string $filearea The filearea.
+ * @param int $itemid The item id for the filearea.
+ * @param string $filename The specific filename of the file.
+ * @return array
+ */
+function extract_draft_file_urls_from_text($text, $forcehttps = false, $contextid = null, $component = null,
+ $filearea = null, $itemid = null, $filename = null) {
+ global $CFG;
+
+ $wwwroot = $CFG->wwwroot;
+ if ($forcehttps) {
+ $wwwroot = str_replace('http://', 'https://', $wwwroot);
+ }
+ $urlstring = '/' . preg_quote($wwwroot, '/');
+
+ $urlbase = preg_quote('draftfile.php');
+ $urlstring .= "\/(?<urlbase>{$urlbase})";
+
+ if (is_null($contextid)) {
+ $contextid = '[0-9]+';
+ }
+ $urlstring .= "\/(?<contextid>{$contextid})";
+
+ if (is_null($component)) {
+ $component = '[a-z_]+';
+ }
+ $urlstring .= "\/(?<component>{$component})";
+
+ if (is_null($filearea)) {
+ $filearea = '[a-z_]+';
+ }
+ $urlstring .= "\/(?<filearea>{$filearea})";
+
+ if (is_null($itemid)) {
+ $itemid = '[0-9]+';
+ }
+ $urlstring .= "\/(?<itemid>{$itemid})";
+
+ // Filename matching magic based on file_rewrite_urls_to_pluginfile().
+ if (is_null($filename)) {
+ $filename = '[^\'\",&<>|`\s:\\\\]+';
+ }
+ $urlstring .= "\/(?<filename>{$filename})/";
+
+ // Regular expression which matches URLs and returns their components.
+ preg_match_all($urlstring, $text, $urls, PREG_SET_ORDER);
+ return $urls;
+}
+
/**
* This function will highlight search words in a given string
*
* @param boolean $large Default small picture, or large.
* @param boolean $return If false print picture, otherwise return the output as string
* @param boolean $link Enclose image in a link to view specified course?
+ * @param boolean $includetoken Whether to use a user token when displaying this group image.
+ * If the group picture is included in an e-mail or some other location where the audience is a specific
+ * user who will not be logged in when viewing, then we use a token to authenticate the user.
* @return string|void Depending on the setting of $return
*/
-function print_group_picture($group, $courseid, $large=false, $return=false, $link=true) {
+function print_group_picture($group, $courseid, $large = false, $return = false, $link = true, $includetoken = false) {
global $CFG;
if (is_array($group)) {
$output = '';
foreach ($group as $g) {
- $output .= print_group_picture($g, $courseid, $large, true, $link);
+ $output .= print_group_picture($g, $courseid, $large, true, $link, $includetoken);
}
if ($return) {
return $output;
}
}
- $pictureurl = get_group_picture_url($group, $courseid, $large);
+ $pictureurl = get_group_picture_url($group, $courseid, $large, $includetoken);
// If there is no picture, do nothing.
if (!isset($pictureurl)) {
* @param stdClass $group A group object.
* @param int $courseid The course ID for the group.
* @param bool $large A large or small group picture? Default is small.
+ * @param boolean $includetoken Whether to use a user token when displaying this group image.
+ * If the group picture is included in an e-mail or some other location where the audience is a specific
+ * user who will not be logged in when viewing, then we use a token to authenticate the user.
* @return moodle_url Returns the url for the group picture.
*/
-function get_group_picture_url($group, $courseid, $large = false) {
+function get_group_picture_url($group, $courseid, $large = false, $includetoken = false) {
global $CFG;
$context = context_course::instance($courseid);
$file = 'f2';
}
- $grouppictureurl = moodle_url::make_pluginfile_url($context->id, 'group', 'icon', $group->id, '/', $file);
+ $grouppictureurl = moodle_url::make_pluginfile_url(
+ $context->id, 'group', 'icon', $group->id, '/', $file, false, $includetoken);
$grouppictureurl->param('rev', $group->picture);
return $grouppictureurl;
}
$rec = new stdClass();
$rec->runid = $this->runid;
$rec->url = $this->url;
- $rec->data = base64_encode(gzcompress(serialize($xhprof_data), 9));
$rec->totalexecutiontime = $this->totalexecutiontime;
$rec->totalcputime = $this->totalcputime;
$rec->totalcalls = $this->totalcalls;
$rec->totalmemory = $this->totalmemory;
$rec->timecreated = $this->timecreated;
- $DB->insert_record('profiling', $rec);
+ // Send to database with compressed and endoded data.
+ if (empty($CFG->disableprofilingtodatabase)) {
+ $rec->data = base64_encode(gzcompress(serialize($xhprof_data), 9));
+ $DB->insert_record('profiling', $rec);
+ }
+
+ // Send raw data to plugins.
+ $rec->data = $xhprof_data;
+
+ // Allow a plugin to take the trace data and process it.
+ if ($pluginsfunction = get_plugins_with_function('store_profiling_data')) {
+ foreach ($pluginsfunction as $plugintype => $plugins) {
+ foreach ($plugins as $pluginfunction) {
+ $pluginfunction($rec);
+ }
+ }
+ }
if (PHPUNIT_TEST) {
// Calculate export variables.
ORDER BY m.timecreated ASC";
return $DB->get_recordset_sql($sql, $params);
}
+
+ /**
+ * Returns an icon instance for the document.
+ *
+ * @param \core_search\document $doc
+ *
+ * @return \core_search\document_icon
+ */
+ public function get_doc_icon(\core_search\document $doc) : \core_search\document_icon {
+ return new \core_search\document_icon('t/message');
+ }
}
$this->assertEquals(4, $event->other['courseid']);
}
- public function test_mesage_sent_via_create_from_ids_without_other_courseid() {
-
- // Creating a message_sent event without courseid leads to debugging + SITEID.
- // TODO: MDL-55449 Ensure this leads to exception instead of debugging in Moodle 3.6.
- $event = \core\event\message_sent::create_from_ids(1, 2, 3);
-
- // Trigger and capturing the event.
- $sink = $this->redirectEvents();
- $event->trigger();
- $events = $sink->get_events();
- $event = reset($events);
-
- $this->assertDebuggingCalled();
- $this->assertEquals(SITEID, $event->other['courseid']);
- }
-
/**
* Test the message viewed event.
*/
$this->assertFalse($doc);
}
+
+ /**
+ * Test document icon.
+ */
+ public function test_get_doc_icon() {
+ $searcharea = \core_search\manager::get_search_area($this->messagereceivedareaid);
+
+ $document = $this->getMockBuilder('\core_search\document')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $result = $searcharea->get_doc_icon($document);
+
+ $this->assertEquals('t/message', $result->get_name());
+ $this->assertEquals('moodle', $result->get_component());
+ }
}
$this->assertFalse($doc);
}
+
+ /**
+ * Test document icon.
+ */
+ public function test_get_doc_icon() {
+ $searcharea = \core_search\manager::get_search_area($this->messagesentareaid);
+
+ $document = $this->getMockBuilder('\core_search\document')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $result = $searcharea->get_doc_icon($document);
+
+ $this->assertEquals('t/message', $result->get_name());
+ $this->assertEquals('moodle', $result->get_component());
+ }
}
This files describes API changes in /message/ messaging system,
information provided here is intended especially for developers.
+=== 3.6 ===
+
+* The following functions have been finally deprecated and can not be used anymore:
+ * message_get_course_contexts()
+ * message_remove_url_params()
+ * message_count_messages()
+ * message_count_blocked_users()
+ * message_contact_link()
+ * message_history_link()
+ * message_shorten_message()
+ * message_get_fragment()
+ * message_get_contact_add_remove_link()
+ * message_get_contact_block_link()
+ * message_mark_messages_read()
+ * message_page_type_list()
+ * message_can_post_message()
+ * message_is_user_non_contact_blocked()
+ * message_is_user_blocked()
+
=== 3.5 ===
* Changed the database structure so there are no longer two tables for messages, with the only
// To know if we are including userinfo.
$userinfo = $this->get_setting_value('userinfo');
+ $groupinfo = $this->get_setting_value('groups');
// Define each element separated.
$assign = new backup_nested_element('assign', array('id'),
$userflag->set_source_table('assign_user_flags',
array('assignment' => backup::VAR_PARENTID));
- $submission->set_source_table('assign_submission',
- array('assignment' => backup::VAR_PARENTID));
+ $submissionparams = array('assignment' => backup::VAR_PARENTID);
+ if (!$groupinfo) {
+ // Without group info, skip group submissions.
+ $submissionparams['groupid'] = backup_helper::is_sqlparam(0);
+ }
+ $submission->set_source_table('assign_submission', $submissionparams);
$grade->set_source_table('assign_grades',
array('assignment' => backup::VAR_PARENTID));
$overrideparams['userid'] = backup_helper::is_sqlparam(null); // Without userinfo, skip user overrides.
}
+ if (!$groupinfo) {
+ // Without group info, skip group overrides.
+ $overrideparams['groupid'] = backup_helper::is_sqlparam(0);
+ }
$override->set_source_table('assign_overrides', $overrideparams);
// Define id annotations.
return;
}
+ // Skip group overrides if we are not restoring groupinfo.
+ $groupinfo = $this->get_setting_value('groups');
+ if (!$groupinfo && !is_null($data->groupid)) {
+ return;
+ }
+
$data->assignid = $this->get_new_parentid('assign');
if (!is_null($data->userid)) {
// Only load events for this override.
if (isset($override->userid)) {
$conds['userid'] = $override->userid;
- } else {
+ } else if (isset($override->groupid)) {
$conds['groupid'] = $override->groupid;
+ } else {
+ // This is not a valid override, it may have been left from a bad import or restore.
+ $conds['groupid'] = $conds['userid'] = 0;
}
}
$oldevents = $DB->get_records('event', $conds, 'id ASC');
$files = array();
$onlinetextsubmission = $this->get_onlinetext_submission($submission->id);
- if ($onlinetextsubmission) {
+ // Note that this check is the same logic as the result from the is_empty function but we do
+ // not call it directly because we already have the submission record.
+ if ($onlinetextsubmission && !empty($onlinetextsubmission->onlinetext)) {
$finaltext = $this->assignment->download_rewrite_pluginfile_urls($onlinetextsubmission->onlinetext, $user, $this);
$formattedtext = format_text($finaltext,
$onlinetextsubmission->onlineformat,
*/
public function is_empty(stdClass $submission) {
$onlinetextsubmission = $this->get_onlinetext_submission($submission->id);
+ $wordcount = 0;
+
+ if (isset($onlinetextsubmission->onlinetext)) {
+ $wordcount = count_words(trim($onlinetextsubmission->onlinetext));
+ }
- return empty($onlinetextsubmission->onlinetext);
+ return $wordcount == 0;
}
/**
if (!isset($data->onlinetext_editor)) {
return true;
}
- return !strlen((string)$data->onlinetext_editor['text']);
+ $wordcount = 0;
+
+ if (isset($data->onlinetext_editor['text'])) {
+ $wordcount = count_words(trim((string)$data->onlinetext_editor['text']));
+ }
+
+ return $wordcount == 0;
}
/**
]);
$instance = $assign->get_instance();
- $eventparams = ['modulename' => 'assign', 'instance' => $instance->id];
+ $eventparams = [
+ 'modulename' => 'assign',
+ 'instance' => $instance->id,
+ 'eventtype' => ASSIGN_EVENT_TYPE_DUE,
+ 'groupid' => 0
+ ];
// Make sure the calendar event for assignment 1 matches the initial due date.
$eventtime = $DB->get_field('event', 'timestart', $eventparams, MUST_EXIST);
$this->assertEquals($eventtime, $duedate);
// Manually update assignment 1's due date.
- $DB->update_record('assign', (object) ['id' => $instance->id, 'duedate' => $newduedate]);
+ $DB->update_record('assign', (object) [
+ 'id' => $instance->id,
+ 'duedate' => $newduedate,
+ 'course' => $course->id
+ ]);
// Then refresh the assignment events of assignment 1's course.
$this->assertTrue(assign_refresh_events($course->id));
// Create a second course and assignment.
$othercourse = $this->getDataGenerator()->create_course();;
- $otherassign = $this->create_instance($othercourse, ['duedate' => $duedate, 'course' => $othercourse->id]);
+ $otherassign = $this->create_instance($othercourse, [
+ 'duedate' => $duedate,
+ ]);
$otherinstance = $otherassign->get_instance();
// Manually update assignment 1 and 2's due dates.
$newduedate += DAYSECS;
- $DB->update_record('assign', (object)['id' => $instance->id, 'duedate' => $newduedate]);
- $DB->update_record('assign', (object)['id' => $otherinstance->id, 'duedate' => $newduedate]);
+ $DB->update_record('assign', (object)[
+ 'id' => $instance->id,
+ 'duedate' => $newduedate,
+ 'course' => $course->id
+ ]);
+ $DB->update_record('assign', (object)[
+ 'id' => $otherinstance->id,
+ 'duedate' => $newduedate,
+ 'course' => $othercourse->id
+ ]);
- // Refresh events of all courses.
+ // Refresh events of all courses and check the calendar events matches the new date.
$this->assertTrue(assign_refresh_events());
// Check the due date calendar event for assignment 1.
}
$return = html_writer::label(get_string('fieldtypelabel', "datafield_" . $this->type),
'menuf_' . $this->field->id, false, array('class' => 'accesshide'));
- $return .= html_writer::select($options, 'f_'.$this->field->id, $value, null, array('class' => 'custom-select'));
+ $return .= html_writer::select($options, 'f_'.$this->field->id, $value,
+ array('' => 'choosedots'), array('class' => 'custom-select'));
return $return;
}
////////////////////////////////////////////////////////
$id = required_param('id', PARAM_INT);
$subject = optional_param('subject', '', PARAM_CLEANHTML);
-$message = optional_param('message', '', PARAM_CLEANHTML);
+$message = optional_param_array('message', '', PARAM_CLEANHTML);
$format = optional_param('format', FORMAT_MOODLE, PARAM_INT);
$messageuser = optional_param_array('messageuser', false, PARAM_INT);
$action = optional_param('action', '', PARAM_ALPHA);
//get the objects
////////////////////////////////////////////////////////
+if ($message) {
+ $message = $message['text'];
+}
+
list ($course, $cm) = get_course_and_cm_from_cmid($id, 'feedback');
if (! $feedback = $DB->get_record("feedback", array("id"=>$cm->instance))) {
print_error('invalidcoursemodule');
echo '<label for="feedback_subject">'.get_string('subject', 'feedback').' </label>';
echo '<input type="text" id="feedback_subject" size="50" maxlength="255" name="subject" value="'.s($subject).'" />';
echo '</div>';
- print_textarea(true, 15, 25, 30, 10, "message", $message);
+ echo $OUTPUT->print_textarea('message', 'edit-message', $message, 15, 25);
print_string('formathtml');
echo '<input type="hidden" name="format" value="'.FORMAT_HTML.'" />';
echo '<br /><div class="buttons">';
*/
public function format_message_text($cm, $post) {
$context = \context_module::instance($cm->id);
- $message = file_rewrite_pluginfile_urls($post->message, 'pluginfile.php',
+ $message = file_rewrite_pluginfile_urls(
+ $post->message,
+ 'pluginfile.php',
$context->id,
- 'mod_forum', 'post', $post->id);
+ 'mod_forum',
+ 'post',
+ $post->id,
+ [
+ 'includetoken' => true,
+ ]);
$options = new \stdClass();
$options->para = true;
$options->context = $context;
* @return string
*/
public function format_message_text($cm, $post) {
- $message = file_rewrite_pluginfile_urls($post->message, 'pluginfile.php',
- \context_module::instance($cm->id)->id,
- 'mod_forum', 'post', $post->id);
+ $context = \context_module::instance($cm->id);
+ $message = file_rewrite_pluginfile_urls(
+ $post->message,
+ 'pluginfile.php',
+ $context->id,
+ 'mod_forum',
+ 'post',
+ $post->id,
+ [
+ 'includetoken' => true,
+ ]);
return format_text_email($message, $post->messageformat);
}
}
* @return string
*/
public function format_message_text($cm, $post) {
- $message = file_rewrite_pluginfile_urls($post->message, 'pluginfile.php',
- \context_module::instance($cm->id)->id,
- 'mod_forum', 'post', $post->id);
+ $context = \context_module::instance($cm->id);
+ $message = file_rewrite_pluginfile_urls(
+ $post->message,
+ 'pluginfile.php',
+ $context->id,
+ 'mod_forum',
+ 'post',
+ $post->id,
+ [
+ 'includetoken' => true,
+ ]);
return format_text_email($message, $post->messageformat);
}
}
*
* @param \mod_forum_renderer $renderer The render to be used for formatting the message and attachments
* @param bool $plaintext Whethe the target is a plaintext target
- * @return stdClass Data ready for use in a mustache template
+ * @return array Data ready for use in a mustache template
*/
public function export_for_template(\renderer_base $renderer, $plaintext = false) {
if ($plaintext) {
* Export this data so it can be used as the context for a mustache template.
*
* @param \mod_forum_renderer $renderer The render to be used for formatting the message and attachments
- * @return stdClass Data ready for use in a mustache template
+ * @return array Data ready for use in a mustache template
*/
protected function export_for_template_text(\mod_forum_renderer $renderer) {
return array(
'discussionlink' => $this->get_discussionlink(),
'authorlink' => $this->get_authorlink(),
- 'authorpicture' => $this->get_author_picture(),
+ 'authorpicture' => $this->get_author_picture($renderer),
- 'grouppicture' => $this->get_group_picture(),
+ 'grouppicture' => $this->get_group_picture($renderer),
);
}
* Export this data so it can be used as the context for a mustache template.
*
* @param \mod_forum_renderer $renderer The render to be used for formatting the message and attachments
- * @return stdClass Data ready for use in a mustache template
+ * @return array Data ready for use in a mustache template
*/
protected function export_for_template_html(\mod_forum_renderer $renderer) {
return array(
'discussionlink' => $this->get_discussionlink(),
'authorlink' => $this->get_authorlink(),
- 'authorpicture' => $this->get_author_picture(),
+ 'authorpicture' => $this->get_author_picture($renderer),
- 'grouppicture' => $this->get_group_picture(),
+ 'grouppicture' => $this->get_group_picture($renderer),
);
}
/**
* The HTML for the author's user picture.
*
+ * @param \renderer_base $renderer
* @return string
*/
- public function get_author_picture() {
- global $OUTPUT;
-
- return $OUTPUT->user_picture($this->author, array('courseid' => $this->course->id));
+ public function get_author_picture(\renderer_base $renderer) {
+ return $renderer->user_picture($this->author, array('courseid' => $this->course->id));
}
/**
* The HTML for a group picture.
*
+ * @param \renderer_base $renderer
* @return string
*/
- public function get_group_picture() {
+ public function get_group_picture(\renderer_base $renderer) {
if (isset($this->userfrom->groups)) {
$groups = $this->userfrom->groups[$this->forum->id];
} else {
}
if ($this->get_is_firstpost()) {
- return print_group_picture($groups, $this->course->id, false, true, true);
+ return print_group_picture($groups, $this->course->id, false, true, true, true);
}
}
}
'<div class="attachments">( *\n *)?<a href',
'<div class="subject">\n.*HTML text and image', '>Moodle Forum',
'<p>Welcome to Moodle, '
- .'<img src="https://www.example.com/moodle/pluginfile.php/\d+/mod_forum/post/\d+/'
+ .'<img src="https://www.example.com/moodle/tokenpluginfile.php/[^/]*/\d+/mod_forum/post/\d+/'
.'Screen%20Shot%202016-03-22%20at%205\.54\.36%20AM%20%281%29\.png"'
.' alt="" width="200" height="393" class="img-responsive" />!</p>',
'>Love Moodle', '>1\d1');
$options = array()) {
global $DB, $USER;
- // Remove too little terms.
+ // Clean terms.
$terms = explode(' ', $query);
foreach ($terms as $key => $term) {
- if (strlen(trim($term, '+-')) < 2) {
+ if (strlen(trim($term, '+-')) < 1) {
unset($terms[$key]);
}
}
$table->head = array ($strname, $strgrade, $strdeadline);
$table->align = array ("left", "center", "center");
}
-
+// Get all deadlines.
+$deadlines = lesson_get_user_deadline($course->id);
foreach ($lessons as $lesson) {
if (!$lesson->visible) {
//Show dimmed if the mod is hidden
$cm = get_coursemodule_from_instance('lesson', $lesson->id);
$context = context_module::instance($cm->id);
- if ($lesson->deadline == 0) {
+ $deadline = $deadlines[$lesson->id]->userdeadline;
+ if ($deadline == 0) {
$due = $strnodeadline;
- } else if ($lesson->deadline > $timenow) {
- $due = userdate($lesson->deadline);
+ } else if ($deadline > $timenow) {
+ $due = userdate($deadline);
} else {
- $due = "<font color=\"red\">".userdate($lesson->deadline)."</font>";
+ $due = "<font color=\"red\">" . userdate($deadline) . "</font>";
}
if ($usesections) {
return array($answerpages, $userstats);
}
+/**
+ * Return user's deadline for all lessons in a course, hereby taking into account group and user overrides.
+ *
+ * @param int $courseid the course id.
+ * @return object An object with of all lessonsids and close unixdates in this course,
+ * taking into account the most lenient overrides, if existing and 0 if no close date is set.
+ */
+function lesson_get_user_deadline($courseid) {
+ global $DB, $USER;
+
+ // For teacher and manager/admins return lesson's deadline.
+ if (has_capability('moodle/course:update', context_course::instance($courseid))) {
+ $sql = "SELECT lesson.id, lesson.deadline AS userdeadline
+ FROM {lesson} lesson
+ WHERE lesson.course = :courseid";
+
+ $results = $DB->get_records_sql($sql, array('courseid' => $courseid));
+ return $results;
+ }
+
+ $sql = "SELECT a.id,
+ COALESCE(v.userclose, v.groupclose, a.deadline, 0) AS userdeadline
+ FROM (
+ SELECT lesson.id as lessonid,
+ MAX(leo.deadline) AS userclose, MAX(qgo.deadline) AS groupclose
+ FROM {lesson} lesson
+ LEFT JOIN {lesson_overrides} leo on lesson.id = leo.lessonid AND leo.userid = :userid
+ LEFT JOIN {groups_members} gm ON gm.userid = :useringroupid
+ LEFT JOIN {lesson_overrides} qgo on lesson.id = qgo.lessonid AND qgo.groupid = gm.groupid
+ WHERE lesson.course = :courseid
+ GROUP BY lesson.id
+ ) v
+ JOIN {lesson} a ON a.id = v.lessonid";
+
+ $results = $DB->get_records_sql($sql, array('userid' => $USER->id, 'useringroupid' => $USER->id, 'courseid' => $courseid));
+ return $results;
+
+}
/**
* Abstract class that page type's MUST inherit from.
}
}
}
+
+ /**
+ * Test test_lesson_get_user_deadline().
+ */
+ public function test_lesson_get_user_deadline() {
+ global $DB;
+
+ $this->resetAfterTest();
+ $this->setAdminUser();
+
+ $basetimestamp = time(); // The timestamp we will base the enddates on.
+
+ // Create generator, course and lessons.
+ $student1 = $this->getDataGenerator()->create_user();
+ $student2 = $this->getDataGenerator()->create_user();
+ $student3 = $this->getDataGenerator()->create_user();
+ $teacher = $this->getDataGenerator()->create_user();
+ $course = $this->getDataGenerator()->create_course();
+ $lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
+
+ // Both lessons close in two hours.
+ $lesson1 = $lessongenerator->create_instance(array('course' => $course->id, 'deadline' => $basetimestamp + 7200));
+ $lesson2 = $lessongenerator->create_instance(array('course' => $course->id, 'deadline' => $basetimestamp + 7200));
+ $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
+ $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
+
+ $student1id = $student1->id;
+ $student2id = $student2->id;
+ $student3id = $student3->id;
+ $teacherid = $teacher->id;
+
+ // Users enrolments.
+ $studentrole = $DB->get_record('role', array('shortname' => 'student'));
+ $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
+ $this->getDataGenerator()->enrol_user($student1id, $course->id, $studentrole->id, 'manual');
+ $this->getDataGenerator()->enrol_user($student2id, $course->id, $studentrole->id, 'manual');
+ $this->getDataGenerator()->enrol_user($student3id, $course->id, $studentrole->id, 'manual');
+ $this->getDataGenerator()->enrol_user($teacherid, $course->id, $teacherrole->id, 'manual');
+
+ // Create groups.
+ $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
+ $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
+ $group1id = $group1->id;
+ $group2id = $group2->id;
+ $this->getDataGenerator()->create_group_member(array('userid' => $student1id, 'groupid' => $group1id));
+ $this->getDataGenerator()->create_group_member(array('userid' => $student2id, 'groupid' => $group2id));
+
+ // Group 1 gets an group override for lesson 1 to close in three hours.
+ $record1 = (object) [
+ 'lessonid' => $lesson1->id,
+ 'groupid' => $group1id,
+ 'deadline' => $basetimestamp + 10800 // In three hours.
+ ];
+ $DB->insert_record('lesson_overrides', $record1);
+
+ // Let's test lesson 1 closes in three hours for user student 1 since member of group 1.
+ // lesson 2 closes in two hours.
+ $this->setUser($student1id);
+ $params = new stdClass();
+
+ $comparearray = array();
+ $object = new stdClass();
+ $object->id = $lesson1->id;
+ $object->userdeadline = $basetimestamp + 10800; // The overriden deadline for lesson 1.
+
+ $comparearray[$lesson1->id] = $object;
+
+ $object = new stdClass();
+ $object->id = $lesson2->id;
+ $object->userdeadline = $basetimestamp + 7200; // The unchanged deadline for lesson 2.
+
+ $comparearray[$lesson2->id] = $object;
+
+ $this->assertEquals($comparearray, lesson_get_user_deadline($course->id));
+
+ // Let's test lesson 1 closes in two hours (the original value) for user student 3 since member of no group.
+ $this->setUser($student3id);
+ $params = new stdClass();
+
+ $comparearray = array();
+ $object = new stdClass();
+ $object->id = $lesson1->id;
+ $object->userdeadline = $basetimestamp + 7200; // The original deadline for lesson 1.
+
+ $comparearray[$lesson1->id] = $object;
+
+ $object = new stdClass();
+ $object->id = $lesson2->id;
+ $object->userdeadline = $basetimestamp + 7200; // The original deadline for lesson 2.
+
+ $comparearray[$lesson2->id] = $object;
+
+ $this->assertEquals($comparearray, lesson_get_user_deadline($course->id));
+
+ // User 2 gets an user override for lesson 1 to close in four hours.
+ $record2 = (object) [
+ 'lessonid' => $lesson1->id,
+ 'userid' => $student2id,
+ 'deadline' => $basetimestamp + 14400 // In four hours.
+ ];
+ $DB->insert_record('lesson_overrides', $record2);
+
+ // Let's test lesson 1 closes in four hours for user student 2 since personally overriden.
+ // lesson 2 closes in two hours.
+ $this->setUser($student2id);
+
+ $comparearray = array();
+ $object = new stdClass();
+ $object->id = $lesson1->id;
+ $object->userdeadline = $basetimestamp + 14400; // The overriden deadline for lesson 1.
+
+ $comparearray[$lesson1->id] = $object;
+
+ $object = new stdClass();
+ $object->id = $lesson2->id;
+ $object->userdeadline = $basetimestamp + 7200; // The unchanged deadline for lesson 2.
+
+ $comparearray[$lesson2->id] = $object;
+
+ $this->assertEquals($comparearray, lesson_get_user_deadline($course->id));
+
+ // Let's test a teacher sees the original times.
+ // lesson 1 and lesson 2 close in two hours.
+ $this->setUser($teacherid);
+
+ $comparearray = array();
+ $object = new stdClass();
+ $object->id = $lesson1->id;
+ $object->userdeadline = $basetimestamp + 7200; // The unchanged deadline for lesson 1.
+
+ $comparearray[$lesson1->id] = $object;
+
+ $object = new stdClass();
+ $object->id = $lesson2->id;
+ $object->userdeadline = $basetimestamp + 7200; // The unchanged deadline for lesson 2.
+
+ $comparearray[$lesson2->id] = $object;
+
+ $this->assertEquals($comparearray, lesson_get_user_deadline($course->id));
+ }
}
*/
public function parse_value($value) {
- if (strpos($value, '$ToolProxyBinding.memberships.url') !== false) {
+ if (strpos($value, '$LtiLink.memberships.url') !== false) {
$id = optional_param('id', 0, PARAM_INT); // Course Module ID.
if (!empty($id)) {
$cm = get_coursemodule_from_id('lti', $id, 0, false, MUST_EXIST);
$user->id,
$lti->servicesalt,
$lti->typeid));
+ // Not per specification but added to comply with earlier version of the service.
+ $member->resultSourcedId = $message->lis_result_sourcedid;
}
- $membership->message = $message;
+ $membership->message = [$message];
}
foreach ($includedcapabilities as $capabilityname => $capability) {
* lti_get_shortcuts has been deprecated. Please use get_shortcuts() instead to add items to the activity chooser.
* Now, when mod_<modname>_core_calendar_is_event_visible or mod_<modname>_core_calendar_provide_event_action callback functions
are called, the userid of the requesting user is also passed to them.
+* The following functions have been finally deprecated and can not be used anymore:
+ - update_module_button()
+* The final deprecation of xxx_delete_course callback means that this function will no longer be called.
+ Please use the observer for event \core\event\course_content_deleted instead.
=== 3.5 ===
+++ /dev/null
-<?php
-/**
- * This file defines a simple editor
- *
- * @author Jordi Piguillem
- * @author Josep Arus
- *
- * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
- * @package mod_wiki
- *
- */
-
-/**
- * @TODO: Doc this function
- */
-function wiki_print_editor_html($pageid, $content, $version = -1, $section = null, $upload = false, $deleteuploads = array()) {
- global $CFG, $OUTPUT;
-
- $OUTPUT->heading(strtoupper(get_string('formathtml', 'wiki')), 3);
-
- $action = $CFG->wwwroot.'/mod/wiki/edit.php?pageid='.$pageid;
-
- if (!empty($section)) {
- $action .= "§ion=".urlencode($section);
- }
-
- echo $OUTPUT->container_start('container');
- echo '<form method="post" action="'.$action.'">';
- $textarea = print_textarea(true, 20, 100, 0, 0, "newcontent", $content, 0, true, '', 'form-textarea-advanced');
- echo $OUTPUT->container($textarea, 'wiki_editor');
- wiki_print_edit_form_default_fields('html', $pageid, $version, $upload, $deleteuploads);
- echo '</form>';
- echo $OUTPUT->container_end();
-}
echo $OUTPUT->container_start();
echo '<form method="post" id="mform1" action="' . $action . '">';
- echo $OUTPUT->container(print_textarea(false, 20, 60, 0, 0, "newcontent", $content, 0, true), false, 'wiki_editor');
+ $textarea = $OUTPUT->print_textarea('newcontent', 'edit-newcontent', $content, 20, 60);
+ echo $OUTPUT->container($textarea, false, 'wiki_editor');
echo $OUTPUT->container_start();
wiki_print_edit_form_default_fields($editor, $pageid, $version, $upload, $deleteuploads);
echo $OUTPUT->container_end();
$action = optional_param('action', '', PARAM_ALPHANUMEXT);
$id = optional_param('id', 0, PARAM_INT);
$commentid = optional_param('commentid', 0, PARAM_INT);
-$newcontent = optional_param('newcontent', '', PARAM_CLEANHTML);
+$newcontent = optional_param_array('newcontent', '', PARAM_CLEANHTML);
$confirm = optional_param('confirm', 0, PARAM_BOOL);
+if ($newcontent) {
+ $newcontent = $newcontent['text'];
+}
+
if (!$page = wiki_get_page($pageid)) {
print_error('incorrectpageid', 'wiki');
}
*/
// Disable moodle specific debug messages and any errors in output.
-define('NO_DEBUG_DISPLAY', true);
+if (!defined('NO_DEBUG_DISPLAY')) {
+ define('NO_DEBUG_DISPLAY', true);
+}
require_once('config.php');
require_once('lib/filelib.php');
-$relativepath = get_file_argument();
+if (empty($relativepath)) {
+ $relativepath = get_file_argument();
+}
$forcedownload = optional_param('forcedownload', 0, PARAM_BOOL);
$preview = optional_param('preview', null, PARAM_ALPHANUM);
// Offline means download the file from the repository and serve it, even if it was an external link.
global $DB;
$fields = \context_helper::get_preload_record_columns_sql('ctx');
- $wrapper = "SELECT {$fields} FROM {context} ctx WHERE id IN ({$sql})";
+ if ($fieldname = $this->guess_id_field_from_sql($sql)) {
+ if (is_numeric($fieldname)) {
+ $wrapper = "
+ SELECT {$fields}
+ FROM {context} ctx
+ WHERE ctx.id = :fieldvalue";
+ $params = ['fieldvalue' => $fieldname];
+ } else {
+ // Able to guess a field name.
+ $wrapper = "
+ SELECT {$fields}
+ FROM {context} ctx
+ JOIN ({$sql}) target ON ctx.id = target.{$fieldname}";
+ }
+ } else {
+ // No field name available. Fall back on a potentially slower version.
+ $wrapper = "
+ SELECT {$fields}
+ FROM {context} ctx
+ WHERE ctx.id IN ({$sql})";
+ }
$contexts = $DB->get_recordset_sql($wrapper, $params);
$contextids = [];
public function set_component($component) {
parent::set_component($component);
}
+
+ /**
+ * Guess the name of the contextid field from the supplied SQL.
+ *
+ * @param string $sql The SQL to guess from
+ * @return string The field name or a numeric value representing the context id
+ */
+ protected function guess_id_field_from_sql(string $sql) : string {
+ // We are not interested in any subquery/view/conditions for the purpose of this method, so
+ // let's reduce the query to the interesting parts by recursively cleaning all
+ // contents within parenthesis. If there are problems (null), we keep the text unmodified.
+ // So just top-level sql will remain after the reduction.
+ $recursiveregexp = '/\((([^()]*|(?R))*)\)/';
+ $sql = (preg_replace($recursiveregexp, '', $sql) ?: $sql);
+ // Get the list of relevant words from the SQL Query.
+ // We explode the SQL by the space character, then trim any extra whitespace (e.g. newlines), before we filter
+ // empty value, and finally we re-index the array.
+ $sql = rtrim($sql, ';');
+ $words = array_map('trim', preg_split('/\s+/', $sql));
+ $words = array_filter($words, function($word) {
+ return $word !== '';
+ });
+ $words = array_values($words);
+ $uwords = array_map('strtoupper', $words); // Uppercase all them.
+
+ // If the query has boolean operators (UNION, it is the only one we support cross-db)
+ // then we cannot guarantee whats coming after the first query, it can be anything.
+ if (array_search('UNION', $uwords)) {
+ return '';
+ }
+
+ if ($firstfrom = array_search('FROM', $uwords)) {
+ // Found a FROM keyword.
+ // Select the previous word.
+ $fieldname = $words[$firstfrom - 1];
+ if (is_numeric($fieldname)) {
+ return $fieldname;
+ }
+
+ if ($hasdot = strpos($fieldname, '.')) {
+ // This field is against a table alias. Take off the alias.
+ $fieldname = substr($fieldname, $hasdot + 1);
+ }
+
+ return $fieldname;
+
+ } else if ((count($words) == 1) && (is_numeric($words[0]))) {
+ // Not a real SQL, just a single numerical value - such as one returned by {@link self::add_system_context()}.
+ return $words[0];
+
+ } else if ((count($words) == 2) && (strtoupper($words[0]) === 'SELECT') && (is_numeric($words[1]))) {
+ // SQL returning a constant numerical value.
+ return $words[1];
+ }
+
+ return '';
+ }
}
$this->assertContains(\context_user::instance($user1->id)->id, $contexts);
$this->assertContains(\context_user::instance($user2->id)->id, $contexts);
}
+
+ /**
+ * Test {@link \core_privacy\local\request\contextlist::test_guess_id_field_from_sql()} implementation.
+ *
+ * @dataProvider data_guess_id_field_from_sql
+ * @param string $sql Input SQL we try to extract the context id field name from.
+ * @param string $expected Expected detected value.
+ */
+ public function test_guess_id_field_from_sql($sql, $expected) {
+
+ $rc = new \ReflectionClass(contextlist::class);
+ $rcm = $rc->getMethod('guess_id_field_from_sql');
+ $rcm->setAccessible(true);
+ $actual = $rcm->invoke(new contextlist(), $sql);
+
+ $this->assertEquals($expected, $actual, 'Unable to guess context id field in: '.$sql);
+ }
+
+ /**
+ * Provides data sets for {@link self::test_guess_id_field_from_sql()}.
+ *
+ * @return array
+ */
+ public function data_guess_id_field_from_sql() {
+ return [
+ 'easy' => [
+ 'SELECT contextid FROM {foo}',
+ 'contextid',
+ ],
+ 'with_distinct' => [
+ 'SELECT DISTINCT contextid FROM {foo}',
+ 'contextid',
+ ],
+ 'with_dot' => [
+ 'SELECT cx.id FROM {foo} JOIN {context} cx ON blahblahblah',
+ 'id',
+ ],
+ 'letter_case_does_not_matter' => [
+ 'Select ctxid From {foo} Where bar = ?',
+ 'ctxid',
+ ],
+ 'alias' => [
+ 'SELECT foo.contextid AS ctx FROM {bar} JOIN {foo} ON bar.id = foo.barid',
+ 'ctx',
+ ],
+ 'tabs' => [
+ "SELECT\tctxid\t\tFROM foo f",
+ 'ctxid',
+ ],
+ 'whitespace' => [
+ "SELECT
+ ctxid\t
+ \tFROM foo f",
+ 'ctxid',
+ ],
+ 'just_number' => [
+ '1',
+ '1',
+ ],
+ 'select_number' => [
+ 'SELECT 2',
+ '2',
+ ],
+ 'select_number_with_semicolon' => [
+ 'SELECT 3;',
+ '3',
+ ],
+ 'select_number_from_table' => [
+ 'SELECT 4 FROM users',
+ '4',
+ ],
+ 'select_with_complex_subqueries' => [
+ 'SELECT id FROM table WHERE id IN (
+ SELECT x FROM xtable
+ UNION
+ SELECT y FROM (
+ SELECT y FROM ytable
+ JOIN ztable ON (z = y)))',
+ 'id'
+ ],
+ 'invalid_union_with_first_being_column_name' => [
+ 'SELECT id FROM table UNION SELECT 1 FROM table',
+ ''
+ ],
+ 'invalid_union_with_first_being_numeric' => [
+ 'SELECT 1 FROM table UNION SELECT id FROM table',
+ ''
+ ],
+ 'invalid_union_without_from' => [
+ 'SELECT 1 UNION SELECT id FROM table',
+ ''
+ ],
+ 'invalid_1' => [
+ 'SELECT 1+1',
+ '',
+ ],
+ 'invalid_2' => [
+ 'muhehe',
+ '',
+ ],
+ ];
+ }
}
--- /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 drag-and-drop words into sentences edit form.
+ *
+ * @package qtype_ddwtos
+ * @copyright 2018 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/engine/tests/helpers.php');
+require_once($CFG->dirroot . '/question/type/edit_question_form.php');
+require_once($CFG->dirroot . '/question/type/ddwtos/edit_ddwtos_form.php');
+
+/**
+ * Unit tests for the drag-and-drop words into sentences edit form.
+ *
+ * @copyright 2012 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class qtype_ddwtos_edit_form_test extends advanced_testcase {
+ /**
+ * Helper method.
+ *
+ * @param string $classname the question form class to instantiate.
+ *
+ * @return question_edit_form great a question form instance that can be tested.
+ */
+ protected function get_form($classname) {
+ $this->setAdminUser();
+ $this->resetAfterTest();
+
+ $syscontext = context_system::instance();
+ $category = question_make_default_categories(array($syscontext));
+ $fakequestion = new stdClass();
+ $fakequestion->qtype = 'stack';
+ $fakequestion->contextid = $syscontext->id;
+ $fakequestion->createdby = 2;
+ $fakequestion->category = $category->id;
+ $fakequestion->questiontext = 'Test [[1]] question [[2]]';
+ $fakequestion->options = new stdClass();
+ $fakequestion->options->answers = array();
+ $fakequestion->formoptions = new stdClass();
+ $fakequestion->formoptions->movecontext = null;
+ $fakequestion->formoptions->repeatelements = true;
+ $fakequestion->inputs = null;
+ return new $classname(new moodle_url('/'), $fakequestion, $category,
+ new question_edit_contexts($syscontext));
+ }
+
+ /**
+ * Test the form shows the right number of groups of choices.
+ */
+ public function test_number_of_choice_groups() {
+ $form = $this->get_form('qtype_ddwtos_edit_form');
+ // Use reflection to get the protected property we need.
+ $property = new ReflectionProperty('qtype_ddwtos_edit_form', '_form');
+ $property->setAccessible(true);
+ $mform = $property->getValue($form);
+ $choices = $mform->getElement('choices[0]');
+ $groupoptions = $choices->_elements[1];
+ $this->assertCount(8, $groupoptions->_options);
+ }
+}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_gapselect_edit_form_base extends question_edit_form {
- /**
- * Maximum number of different groups of drag items there can be in a question.
- */
- const MAX_GROUPS = 8;
/** @var array of HTML tags allowed in choices / drag boxes. */
protected $allowedhtmltags = array(
get_string('addmorechoiceblanks', 'qtype_gapselect'), true);
}
+ /**
+ * Return how many different groups of choices there should be.
+ *
+ * @return int the maximum group number.
+ */
+ function get_maximum_choice_group_number() {
+ return 8;
+ }
+
/**
* Creates an array with elements for a choice group.
*
* @param object $mform The Moodle form we are working with
+ * @param int $maxgroup The number of max group generate element select.
* @return array Array for form elements
*/
protected function choice_group($mform) {
$options = array();
- for ($i = 1; $i <= self::MAX_GROUPS; $i += 1) {
+ for ($i = 1; $i <= $this->get_maximum_choice_group_number(); $i += 1) {
$options[$i] = $i;
}
$grouparray = array();
public function qtype() {
return 'gapselect';
}
+
+ function get_maximum_choice_group_number() {
+ return 20;
+ }
}
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
- * Unit tests for the select missing words question definition class.
+ * Unit tests for the select missing words question edit form.
*
* @package qtype_gapselect
* @copyright 2012 The Open University
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/gapselect/edit_form_base.php');
+require_once($CFG->dirroot . '/question/type/gapselect/edit_gapselect_form.php');
/**
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_gapselect_edit_form_base_testable extends qtype_gapselect_edit_form_base {
- public function __construct() {
- $syscontext = context_system::instance();
- $category = question_make_default_categories(array($syscontext));
- $fakequestion = new stdClass();
- $fakequestion->qtype = 'stack';
- $fakequestion->contextid = $syscontext->id;
- $fakequestion->createdby = 2;
- $fakequestion->category = $category->id;
- $fakequestion->questiontext = 'Test [[1]] question [[2]]';
- $fakequestion->options = new stdClass();
- $fakequestion->options->answers = array();
- $fakequestion->formoptions = new stdClass();
- $fakequestion->formoptions->movecontext = null;
- $fakequestion->formoptions->repeatelements = true;
- $fakequestion->inputs = null;
- parent::__construct(new moodle_url('/'), $fakequestion, $category,
- new question_edit_contexts($syscontext));
- }
-
public function get_illegal_tag_error($text) {
return parent::get_illegal_tag_error($text);
}
/**
- * Unit tests for Stack question editing form.
+ * Unit tests for select missing words question edit form.
*
* @copyright 2012 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
/**
* Helper method.
- * @return qtype_gapselect_edit_form_base_testable a new form instance that can be tested.
+ *
+ * @param string $classname the question form class to instantiate.
+ *
+ * @return question_edit_form great a question form instance that can be tested.
*/
- protected function get_form() {
+ protected function get_form($classname) {
$this->setAdminUser();
$this->resetAfterTest();
- return new qtype_gapselect_edit_form_base_testable();
+ $syscontext = context_system::instance();
+ $category = question_make_default_categories(array($syscontext));
+ $fakequestion = new stdClass();
+ $fakequestion->qtype = 'stack';
+ $fakequestion->contextid = $syscontext->id;
+ $fakequestion->createdby = 2;
+ $fakequestion->category = $category->id;
+ $fakequestion->questiontext = 'Test [[1]] question [[2]]';
+ $fakequestion->options = new stdClass();
+ $fakequestion->options->answers = array();
+ $fakequestion->formoptions = new stdClass();
+ $fakequestion->formoptions->movecontext = null;
+ $fakequestion->formoptions->repeatelements = true;
+ $fakequestion->inputs = null;
+ return new $classname(new moodle_url('/'), $fakequestion, $category,
+ new question_edit_contexts($syscontext));
}
public function test_get_illegal_tag_error() {
- $form = $this->get_form();
+ $form = $this->get_form('qtype_gapselect_edit_form_base_testable');
$this->assertEquals('', $form->get_illegal_tag_error('frog'));
$this->assertEquals('', $form->get_illegal_tag_error('<i>toad</i>'));
$this->assertEquals(get_string('tagsnotallowedatall', 'qtype_gapselect', $a),
$form->get_illegal_tag_error('<i><br /></i>'));
}
+
+ /**
+ * Test the form shows the right number of groups of choices.
+ */
+ public function test_number_of_choice_groups() {
+ $form = $this->get_form('qtype_gapselect_edit_form');
+ // Use reflection to get the protected property we need.
+ $property = new ReflectionProperty('qtype_gapselect_edit_form', '_form');
+ $property->setAccessible(true);
+ $mform = $property->getValue($form);
+ $choices = $mform->getElement('choices[0]');
+ $groupoptions = $choices->_elements[1];
+ $this->assertCount(20, $groupoptions->_options);
+ }
}
This files describes API changes in /report/* - plugins,
information provided here is intended especially for developers.
+=== 3.6 ===
+
+* The final deprecation of xxx_delete_course callback means that this function will no longer be called.
+ Please use the observer for event \core\event\course_content_deleted instead.
+
=== 3.2 ===
* Callback delete_course is deprecated and should be replaced with observer for event \core\event\course_content_deleted
* The report_log_print_graph signature and behaviour has changed to generate charts using
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
+]>\r
+<svg version="1.1"\r
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"\r
+ x="0px" y="0px" width="74px" height="51px" viewBox="-0.535 -0.774 74 51"\r
+ style="overflow:visible;enable-background:new -0.535 -0.774 74 51;" xml:space="preserve" preserveAspectRatio="xMinYMid meet">\r
+<defs>\r
+</defs>\r
+<radialGradient id="SVGID_1_" cx="137.084" cy="32.2324" r="123.3346" gradientUnits="userSpaceOnUse">\r
+ <stop offset="0" style="stop-color:#FAAF40"/>\r
+ <stop offset="0.0432" style="stop-color:#F9A538"/>\r
+ <stop offset="0.1116" style="stop-color:#F89D31"/>\r
+ <stop offset="0.2269" style="stop-color:#F89A2F"/>\r
+ <stop offset="0.5276" style="stop-color:#F7922D"/>\r
+ <stop offset="1" style="stop-color:#F37B28"/>\r
+ <a:midPointStop offset="0" style="stop-color:#FAAF40"/>\r
+ <a:midPointStop offset="0.1982" style="stop-color:#FAAF40"/>\r
+ <a:midPointStop offset="0.2269" style="stop-color:#F89A2F"/>\r
+ <a:midPointStop offset="0.6064" style="stop-color:#F89A2F"/>\r
+ <a:midPointStop offset="1" style="stop-color:#F37B28"/>\r
+</radialGradient>\r
+<path style="fill:url(#SVGID_1_);" d="M61.192,49.375V26.558c0-4.771-1.972-7.156-5.911-7.156c-3.942,0-5.912,2.386-5.912,7.156\r
+ v22.817H37.754V26.558c0-4.771-1.938-7.156-5.811-7.156c-3.94,0-5.91,2.386-5.91,7.156v22.817H14.417V25.211\r
+ c0-4.979,1.728-8.747,5.185-11.304c3.043-2.282,7.158-3.425,12.343-3.425c5.255,0,9.127,1.349,11.617,4.045\r
+ c2.142-2.696,6.049-4.045,11.72-4.045c5.186,0,9.298,1.143,12.341,3.425c3.457,2.557,5.186,6.325,5.186,11.304v24.164H61.192z"/>\r
+<path style="fill:#58595B;" d="M15.499,16.321c-0.394,1.999-0.788,3.999-1.181,5.997c10.983,3.72,21.4,0.111,26.883-9.489\r
+ C33.184,7.282,25.601,12.914,15.499,16.321"/>\r
+<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="14.4287" y1="16.0166" x2="40.6895" y2="16.0166">\r
+ <stop offset="0" style="stop-color:#929497"/>\r
+ <stop offset="0.1245" style="stop-color:#757578"/>\r
+ <stop offset="0.2792" style="stop-color:#575658"/>\r
+ <stop offset="0.4403" style="stop-color:#403E3F"/>\r
+ <stop offset="0.6085" style="stop-color:#302D2E"/>\r
+ <stop offset="0.7884" style="stop-color:#262223"/>\r
+ <stop offset="1" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="0" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="0.2606" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="1" style="stop-color:#231F20"/>\r
+</linearGradient>\r
+<path style="fill:url(#SVGID_2_);" d="M15.499,14.889c-0.356,2.259-0.714,4.518-1.07,6.776c10.527,3.567,20.84,0.503,26.261-8.944\r
+ C33.708,4.677,25.925,11.373,15.499,14.889"/>\r
+<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="19.457" y1="7.248" x2="30.3611" y2="22.8207">\r
+ <stop offset="0" style="stop-color:#231F20"/>\r
+ <stop offset="1" style="stop-color:#231F20;stop-opacity:0"/>\r
+ <a:midPointStop offset="0" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="0.5" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="1" style="stop-color:#231F20;stop-opacity:0"/>\r
+</linearGradient>\r
+<path style="fill:url(#SVGID_3_);" d="M27.993,17.575c-4.764-0.997-10.036,1.485-13.564,4.09\r
+ C12.103,4.879,22.536,5.222,36.098,9.415c-0.857,4.143-2.387,9.598-5.017,12.903C31.081,20.182,30.052,18.6,27.993,17.575"/>\r
+<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="0.0078" y1="7.7275" x2="48.0068" y2="7.7275">\r
+ <stop offset="0" style="stop-color:#929497"/>\r
+ <stop offset="0.1245" style="stop-color:#757578"/>\r
+ <stop offset="0.2792" style="stop-color:#575658"/>\r
+ <stop offset="0.4403" style="stop-color:#403E3F"/>\r
+ <stop offset="0.6085" style="stop-color:#302D2E"/>\r
+ <stop offset="0.7884" style="stop-color:#262223"/>\r
+ <stop offset="1" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="0" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="0.2606" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="1" style="stop-color:#231F20"/>\r
+</linearGradient>\r
+<path style="fill:url(#SVGID_4_);" d="M0.008,14.889C17.625,4.318,27.468,2.282,48.007,0.202\r
+ C24.279,18.919,23.64,14.889,0.008,14.889"/>\r
+<line style="fill:#383738;stroke:#4A4A4C;stroke-width:0.5;" x1="48.007" y1="0.202" x2="29.186" y2="13.948"/>\r
+<path style="opacity:0.23;fill:#231F20;" d="M25.506,7.567C25.733,9.723,25.286,5.423,25.506,7.567"/>\r
+<line style="fill:#FFFFFF;stroke:#A8ABAD;stroke-width:0.5;" x1="0.008" y1="14.889" x2="29.186" y2="13.948"/>\r
+<path style="fill:none;stroke:#F16922;stroke-width:0.5;" d="M23.79,7.733c-4.996,1.381-21.387,5.041-21.64,7.086\r
+ c-0.483,3.917-0.123,10.143-0.123,10.143"/>\r
+<path style="fill:#F16922;" d="M3.532,39.84C1.697,35.389-0.443,30.363,2.1,24.184C3.794,29.957,3.544,34.362,3.532,39.84"/>\r
+<ellipse transform="matrix(0.942 -0.3356 0.3356 0.942 -1.1544 8.1596)" style="fill:#6D6E70;" cx="23.032" cy="7.42" rx="0.792" ry="0.411"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
+]>\r
+<svg version="1.1"\r
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"\r
+ x="0px" y="0px" width="74px" height="51px" viewBox="-0.535 -0.774 74 51"\r
+ style="overflow:visible;enable-background:new -0.535 -0.774 74 51;" xml:space="preserve" preserveAspectRatio="xMinYMid meet">\r
+<defs>\r
+</defs>\r
+<radialGradient id="SVGID_1_" cx="137.084" cy="32.2324" r="123.3346" gradientUnits="userSpaceOnUse">\r
+ <stop offset="0" style="stop-color:#FAAF40"/>\r
+ <stop offset="0.0432" style="stop-color:#F9A538"/>\r
+ <stop offset="0.1116" style="stop-color:#F89D31"/>\r
+ <stop offset="0.2269" style="stop-color:#F89A2F"/>\r
+ <stop offset="0.5276" style="stop-color:#F7922D"/>\r
+ <stop offset="1" style="stop-color:#F37B28"/>\r
+ <a:midPointStop offset="0" style="stop-color:#FAAF40"/>\r
+ <a:midPointStop offset="0.1982" style="stop-color:#FAAF40"/>\r
+ <a:midPointStop offset="0.2269" style="stop-color:#F89A2F"/>\r
+ <a:midPointStop offset="0.6064" style="stop-color:#F89A2F"/>\r
+ <a:midPointStop offset="1" style="stop-color:#F37B28"/>\r
+</radialGradient>\r
+<path style="fill:url(#SVGID_1_);" d="M61.192,49.375V26.558c0-4.771-1.972-7.156-5.911-7.156c-3.942,0-5.912,2.386-5.912,7.156\r
+ v22.817H37.754V26.558c0-4.771-1.938-7.156-5.811-7.156c-3.94,0-5.91,2.386-5.91,7.156v22.817H14.417V25.211\r
+ c0-4.979,1.728-8.747,5.185-11.304c3.043-2.282,7.158-3.425,12.343-3.425c5.255,0,9.127,1.349,11.617,4.045\r
+ c2.142-2.696,6.049-4.045,11.72-4.045c5.186,0,9.298,1.143,12.341,3.425c3.457,2.557,5.186,6.325,5.186,11.304v24.164H61.192z"/>\r
+<path style="fill:#58595B;" d="M15.499,16.321c-0.394,1.999-0.788,3.999-1.181,5.997c10.983,3.72,21.4,0.111,26.883-9.489\r
+ C33.184,7.282,25.601,12.914,15.499,16.321"/>\r
+<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="14.4287" y1="16.0166" x2="40.6895" y2="16.0166">\r
+ <stop offset="0" style="stop-color:#929497"/>\r
+ <stop offset="0.1245" style="stop-color:#757578"/>\r
+ <stop offset="0.2792" style="stop-color:#575658"/>\r
+ <stop offset="0.4403" style="stop-color:#403E3F"/>\r
+ <stop offset="0.6085" style="stop-color:#302D2E"/>\r
+ <stop offset="0.7884" style="stop-color:#262223"/>\r
+ <stop offset="1" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="0" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="0.2606" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="1" style="stop-color:#231F20"/>\r
+</linearGradient>\r
+<path style="fill:url(#SVGID_2_);" d="M15.499,14.889c-0.356,2.259-0.714,4.518-1.07,6.776c10.527,3.567,20.84,0.503,26.261-8.944\r
+ C33.708,4.677,25.925,11.373,15.499,14.889"/>\r
+<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="19.457" y1="7.248" x2="30.3611" y2="22.8207">\r
+ <stop offset="0" style="stop-color:#231F20"/>\r
+ <stop offset="1" style="stop-color:#231F20;stop-opacity:0"/>\r
+ <a:midPointStop offset="0" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="0.5" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="1" style="stop-color:#231F20;stop-opacity:0"/>\r
+</linearGradient>\r
+<path style="fill:url(#SVGID_3_);" d="M27.993,17.575c-4.764-0.997-10.036,1.485-13.564,4.09\r
+ C12.103,4.879,22.536,5.222,36.098,9.415c-0.857,4.143-2.387,9.598-5.017,12.903C31.081,20.182,30.052,18.6,27.993,17.575"/>\r
+<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="0.0078" y1="7.7275" x2="48.0068" y2="7.7275">\r
+ <stop offset="0" style="stop-color:#929497"/>\r
+ <stop offset="0.1245" style="stop-color:#757578"/>\r
+ <stop offset="0.2792" style="stop-color:#575658"/>\r
+ <stop offset="0.4403" style="stop-color:#403E3F"/>\r
+ <stop offset="0.6085" style="stop-color:#302D2E"/>\r
+ <stop offset="0.7884" style="stop-color:#262223"/>\r
+ <stop offset="1" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="0" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="0.2606" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="1" style="stop-color:#231F20"/>\r
+</linearGradient>\r
+<path style="fill:url(#SVGID_4_);" d="M0.008,14.889C17.625,4.318,27.468,2.282,48.007,0.202\r
+ C24.279,18.919,23.64,14.889,0.008,14.889"/>\r
+<line style="fill:#383738;stroke:#4A4A4C;stroke-width:0.5;" x1="48.007" y1="0.202" x2="29.186" y2="13.948"/>\r
+<path style="opacity:0.23;fill:#231F20;" d="M25.506,7.567C25.733,9.723,25.286,5.423,25.506,7.567"/>\r
+<line style="fill:#FFFFFF;stroke:#A8ABAD;stroke-width:0.5;" x1="0.008" y1="14.889" x2="29.186" y2="13.948"/>\r
+<path style="fill:none;stroke:#F16922;stroke-width:0.5;" d="M23.79,7.733c-4.996,1.381-21.387,5.041-21.64,7.086\r
+ c-0.483,3.917-0.123,10.143-0.123,10.143"/>\r
+<path style="fill:#F16922;" d="M3.532,39.84C1.697,35.389-0.443,30.363,2.1,24.184C3.794,29.957,3.544,34.362,3.532,39.84"/>\r
+<ellipse transform="matrix(0.942 -0.3356 0.3356 0.942 -1.1544 8.1596)" style="fill:#6D6E70;" cx="23.032" cy="7.42" rx="0.792" ry="0.411"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
+]>\r
+<svg version="1.1"\r
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"\r
+ x="0px" y="0px" width="74px" height="51px" viewBox="-0.535 -0.774 74 51"\r
+ style="overflow:visible;enable-background:new -0.535 -0.774 74 51;" xml:space="preserve" preserveAspectRatio="xMinYMid meet">\r
+<defs>\r
+</defs>\r
+<radialGradient id="SVGID_1_" cx="137.084" cy="32.2324" r="123.3346" gradientUnits="userSpaceOnUse">\r
+ <stop offset="0" style="stop-color:#FAAF40"/>\r
+ <stop offset="0.0432" style="stop-color:#F9A538"/>\r
+ <stop offset="0.1116" style="stop-color:#F89D31"/>\r
+ <stop offset="0.2269" style="stop-color:#F89A2F"/>\r
+ <stop offset="0.5276" style="stop-color:#F7922D"/>\r
+ <stop offset="1" style="stop-color:#F37B28"/>\r
+ <a:midPointStop offset="0" style="stop-color:#FAAF40"/>\r
+ <a:midPointStop offset="0.1982" style="stop-color:#FAAF40"/>\r
+ <a:midPointStop offset="0.2269" style="stop-color:#F89A2F"/>\r
+ <a:midPointStop offset="0.6064" style="stop-color:#F89A2F"/>\r
+ <a:midPointStop offset="1" style="stop-color:#F37B28"/>\r
+</radialGradient>\r
+<path style="fill:url(#SVGID_1_);" d="M61.192,49.375V26.558c0-4.771-1.972-7.156-5.911-7.156c-3.942,0-5.912,2.386-5.912,7.156\r
+ v22.817H37.754V26.558c0-4.771-1.938-7.156-5.811-7.156c-3.94,0-5.91,2.386-5.91,7.156v22.817H14.417V25.211\r
+ c0-4.979,1.728-8.747,5.185-11.304c3.043-2.282,7.158-3.425,12.343-3.425c5.255,0,9.127,1.349,11.617,4.045\r
+ c2.142-2.696,6.049-4.045,11.72-4.045c5.186,0,9.298,1.143,12.341,3.425c3.457,2.557,5.186,6.325,5.186,11.304v24.164H61.192z"/>\r
+<path style="fill:#58595B;" d="M15.499,16.321c-0.394,1.999-0.788,3.999-1.181,5.997c10.983,3.72,21.4,0.111,26.883-9.489\r
+ C33.184,7.282,25.601,12.914,15.499,16.321"/>\r
+<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="14.4287" y1="16.0166" x2="40.6895" y2="16.0166">\r
+ <stop offset="0" style="stop-color:#929497"/>\r
+ <stop offset="0.1245" style="stop-color:#757578"/>\r
+ <stop offset="0.2792" style="stop-color:#575658"/>\r
+ <stop offset="0.4403" style="stop-color:#403E3F"/>\r
+ <stop offset="0.6085" style="stop-color:#302D2E"/>\r
+ <stop offset="0.7884" style="stop-color:#262223"/>\r
+ <stop offset="1" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="0" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="0.2606" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="1" style="stop-color:#231F20"/>\r
+</linearGradient>\r
+<path style="fill:url(#SVGID_2_);" d="M15.499,14.889c-0.356,2.259-0.714,4.518-1.07,6.776c10.527,3.567,20.84,0.503,26.261-8.944\r
+ C33.708,4.677,25.925,11.373,15.499,14.889"/>\r
+<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="19.457" y1="7.248" x2="30.3611" y2="22.8207">\r
+ <stop offset="0" style="stop-color:#231F20"/>\r
+ <stop offset="1" style="stop-color:#231F20;stop-opacity:0"/>\r
+ <a:midPointStop offset="0" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="0.5" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="1" style="stop-color:#231F20;stop-opacity:0"/>\r
+</linearGradient>\r
+<path style="fill:url(#SVGID_3_);" d="M27.993,17.575c-4.764-0.997-10.036,1.485-13.564,4.09\r
+ C12.103,4.879,22.536,5.222,36.098,9.415c-0.857,4.143-2.387,9.598-5.017,12.903C31.081,20.182,30.052,18.6,27.993,17.575"/>\r
+<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="0.0078" y1="7.7275" x2="48.0068" y2="7.7275">\r
+ <stop offset="0" style="stop-color:#929497"/>\r
+ <stop offset="0.1245" style="stop-color:#757578"/>\r
+ <stop offset="0.2792" style="stop-color:#575658"/>\r
+ <stop offset="0.4403" style="stop-color:#403E3F"/>\r
+ <stop offset="0.6085" style="stop-color:#302D2E"/>\r
+ <stop offset="0.7884" style="stop-color:#262223"/>\r
+ <stop offset="1" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="0" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="0.2606" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="1" style="stop-color:#231F20"/>\r
+</linearGradient>\r
+<path style="fill:url(#SVGID_4_);" d="M0.008,14.889C17.625,4.318,27.468,2.282,48.007,0.202\r
+ C24.279,18.919,23.64,14.889,0.008,14.889"/>\r
+<line style="fill:#383738;stroke:#4A4A4C;stroke-width:0.5;" x1="48.007" y1="0.202" x2="29.186" y2="13.948"/>\r
+<path style="opacity:0.23;fill:#231F20;" d="M25.506,7.567C25.733,9.723,25.286,5.423,25.506,7.567"/>\r
+<line style="fill:#FFFFFF;stroke:#A8ABAD;stroke-width:0.5;" x1="0.008" y1="14.889" x2="29.186" y2="13.948"/>\r
+<path style="fill:none;stroke:#F16922;stroke-width:0.5;" d="M23.79,7.733c-4.996,1.381-21.387,5.041-21.64,7.086\r
+ c-0.483,3.917-0.123,10.143-0.123,10.143"/>\r
+<path style="fill:#F16922;" d="M3.532,39.84C1.697,35.389-0.443,30.363,2.1,24.184C3.794,29.957,3.544,34.362,3.532,39.84"/>\r
+<ellipse transform="matrix(0.942 -0.3356 0.3356 0.942 -1.1544 8.1596)" style="fill:#6D6E70;" cx="23.032" cy="7.42" rx="0.792" ry="0.411"/>\r
+</svg>\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
+]>\r
+<svg version="1.1"\r
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"\r
+ x="0px" y="0px" width="74px" height="51px" viewBox="-0.535 -0.774 74 51"\r
+ style="overflow:visible;enable-background:new -0.535 -0.774 74 51;" xml:space="preserve" preserveAspectRatio="xMinYMid meet">\r
+<defs>\r
+</defs>\r
+<radialGradient id="SVGID_1_" cx="137.084" cy="32.2324" r="123.3346" gradientUnits="userSpaceOnUse">\r
+ <stop offset="0" style="stop-color:#FAAF40"/>\r
+ <stop offset="0.0432" style="stop-color:#F9A538"/>\r
+ <stop offset="0.1116" style="stop-color:#F89D31"/>\r
+ <stop offset="0.2269" style="stop-color:#F89A2F"/>\r
+ <stop offset="0.5276" style="stop-color:#F7922D"/>\r
+ <stop offset="1" style="stop-color:#F37B28"/>\r
+ <a:midPointStop offset="0" style="stop-color:#FAAF40"/>\r
+ <a:midPointStop offset="0.1982" style="stop-color:#FAAF40"/>\r
+ <a:midPointStop offset="0.2269" style="stop-color:#F89A2F"/>\r
+ <a:midPointStop offset="0.6064" style="stop-color:#F89A2F"/>\r
+ <a:midPointStop offset="1" style="stop-color:#F37B28"/>\r
+</radialGradient>\r
+<path style="fill:url(#SVGID_1_);" d="M61.192,49.375V26.558c0-4.771-1.972-7.156-5.911-7.156c-3.942,0-5.912,2.386-5.912,7.156\r
+ v22.817H37.754V26.558c0-4.771-1.938-7.156-5.811-7.156c-3.94,0-5.91,2.386-5.91,7.156v22.817H14.417V25.211\r
+ c0-4.979,1.728-8.747,5.185-11.304c3.043-2.282,7.158-3.425,12.343-3.425c5.255,0,9.127,1.349,11.617,4.045\r
+ c2.142-2.696,6.049-4.045,11.72-4.045c5.186,0,9.298,1.143,12.341,3.425c3.457,2.557,5.186,6.325,5.186,11.304v24.164H61.192z"/>\r
+<path style="fill:#58595B;" d="M15.499,16.321c-0.394,1.999-0.788,3.999-1.181,5.997c10.983,3.72,21.4,0.111,26.883-9.489\r
+ C33.184,7.282,25.601,12.914,15.499,16.321"/>\r
+<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="14.4287" y1="16.0166" x2="40.6895" y2="16.0166">\r
+ <stop offset="0" style="stop-color:#929497"/>\r
+ <stop offset="0.1245" style="stop-color:#757578"/>\r
+ <stop offset="0.2792" style="stop-color:#575658"/>\r
+ <stop offset="0.4403" style="stop-color:#403E3F"/>\r
+ <stop offset="0.6085" style="stop-color:#302D2E"/>\r
+ <stop offset="0.7884" style="stop-color:#262223"/>\r
+ <stop offset="1" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="0" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="0.2606" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="1" style="stop-color:#231F20"/>\r
+</linearGradient>\r
+<path style="fill:url(#SVGID_2_);" d="M15.499,14.889c-0.356,2.259-0.714,4.518-1.07,6.776c10.527,3.567,20.84,0.503,26.261-8.944\r
+ C33.708,4.677,25.925,11.373,15.499,14.889"/>\r
+<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="19.457" y1="7.248" x2="30.3611" y2="22.8207">\r
+ <stop offset="0" style="stop-color:#231F20"/>\r
+ <stop offset="1" style="stop-color:#231F20;stop-opacity:0"/>\r
+ <a:midPointStop offset="0" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="0.5" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="1" style="stop-color:#231F20;stop-opacity:0"/>\r
+</linearGradient>\r
+<path style="fill:url(#SVGID_3_);" d="M27.993,17.575c-4.764-0.997-10.036,1.485-13.564,4.09\r
+ C12.103,4.879,22.536,5.222,36.098,9.415c-0.857,4.143-2.387,9.598-5.017,12.903C31.081,20.182,30.052,18.6,27.993,17.575"/>\r
+<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="0.0078" y1="7.7275" x2="48.0068" y2="7.7275">\r
+ <stop offset="0" style="stop-color:#929497"/>\r
+ <stop offset="0.1245" style="stop-color:#757578"/>\r
+ <stop offset="0.2792" style="stop-color:#575658"/>\r
+ <stop offset="0.4403" style="stop-color:#403E3F"/>\r
+ <stop offset="0.6085" style="stop-color:#302D2E"/>\r
+ <stop offset="0.7884" style="stop-color:#262223"/>\r
+ <stop offset="1" style="stop-color:#231F20"/>\r
+ <a:midPointStop offset="0" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="0.2606" style="stop-color:#929497"/>\r
+ <a:midPointStop offset="1" style="stop-color:#231F20"/>\r
+</linearGradient>\r
+<path style="fill:url(#SVGID_4_);" d="M0.008