// systems, but let's allow room for expansion.
core_php_time_limit::raise(300);
-$filter = optional_param('filter', '', PARAM_ALPHANUMEXT);
+$filter = optional_param('filter', '', PARAM_NOTAGS);
$type = optional_param('type', false, PARAM_ALPHAEXT);
$component = optional_param('component', '', PARAM_ALPHAEXT);
// The loaded steps depends on the component specified.
behat_config_manager::update_config_file($component, false);
- // The Moodle\BehatExtension\HelpPrinter\MoodleDefinitionsPrinter will parse this search format.
+ // The Moodle\BehatExtension\Definition\Printer\ConsoleDefinitionInformationPrinter will parse this search format.
if ($type) {
$filter .= '&&' . $type;
}
if ($filter) {
- $filteroption = ' -d "' . $filter . '"';
+ $filteroption = ' -d ' . escapeshellarg($filter);
} else {
$filteroption = ' -di';
}
global $CFG;
require_once($CFG->libdir . '/behat/classes/behat_selectors.php');
- $html = $this->generic_info();
-
- // Form.
- ob_start();
- $form->display();
- $html .= ob_get_contents();
- ob_end_clean();
+ $html = $this->output->header();
+ $html .= $this->output->heading(get_string('pluginname', 'tool_behat'));
+ $html .= $form->render();
if (empty($stepsdefinitions)) {
$stepsdefinitions = get_string('nostepsdefinitions', 'tool_behat');
*/
public function render_error($msg) {
- $html = $this->generic_info();
+ $html = $this->output->header();
+ $html .= $this->output->heading(get_string('pluginname', 'tool_behat'));
+ $html .= $this->generic_info();
$a = new stdClass();
$a->errormsg = $msg;
*
* @return string
*/
- protected function generic_info() {
-
- $title = get_string('pluginname', 'tool_behat');
-
- // Header.
- $html = $this->output->header();
- $html .= $this->output->heading($title);
+ public function generic_info() {
// Info.
$installurl = behat_command::DOCS_URL;
);
// List of steps.
- $html .= $this->output->box_start();
- $html .= html_writer::tag('h3', get_string('infoheading', 'tool_behat'));
+ $html = $this->output->box_start();
$html .= html_writer::tag('div', get_string('aim', 'tool_behat'));
$html .= html_writer::start_tag('div');
$html .= html_writer::start_tag('ul');
* @return void
*/
public function definition() {
+ global $PAGE;
$mform = $this->_form;
+ $output = $PAGE->get_renderer('tool_behat');
+
+ $mform->addElement('header', 'info', get_string('infoheading', 'tool_behat'));
+ $mform->setExpanded('info', false);
+ $mform->addElement('html', $output->generic_info());
$mform->addElement('header', 'filters', get_string('stepsdefinitionsfilters', 'tool_behat'));
-.steps-definitions {
- border-style: solid;
- border-width: 1px;
- border-color: #bbb;
- padding: 5px;
- margin: auto;
- width: 50%;
+#page-admin-tool-behat-index .steps-definitions {
+ margin: 1rem auto;
}
-.steps-definitions .step {
- margin: 10px 0 10px 0;
+#page-admin-tool-behat-index .steps-definitions .step {
+ margin: 1rem 0 0 0;
+ border: 1px solid #eee;
+ padding: 1rem;
}
-.steps-definitions .stepdescription {
- color: #bf8c12;
+#page-admin-tool-behat-index .steps-definitions .stepdescription {
+ font-style: italic;
}
-.steps-definitions .steptype {
+#page-admin-tool-behat-index .steps-definitions .stepcontent {
+ margin: 1rem 0;
+}
+
+#page-admin-tool-behat-index .steps-definitions .steptype {
color: #1467a6;
- margin-right: 5px;
+ margin-right: 1ex;
+}
+
+#page-admin-tool-behat-index .steps-definitions .stepapipath {
+ font-family: monospace;
+ font-size: smaller;
}
-.steps-definitions .stepregex {
+#page-admin-tool-behat-index .steps-definitions .stepregex {
color: #060;
}
Given I set the field "Contains" to "homepage"
When I press "Filter"
Then I should see "Opens Moodle homepage."
+
+ @javascript
+ Scenario: Filtering by the multiple words pattern
+ Given I set the field "Contains" to "should exist"
+ When I press "Filter"
+ Then I should not see "There aren't steps definitions matching this filter"
+ And I should see "Checks the provided element and selector type exists in the current page."
+ And I should see "Checks that an element and selector type exists in another element and selector type on the current page."
<?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/>.
+
+/**
+ * Bulk user actions
+ *
+ * @package core
+ * @copyright Moodle
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
require_once('../../config.php');
require_once($CFG->libdir.'/adminlib.php');
if (!isset($SESSION->bulk_users)) {
$SESSION->bulk_users = array();
}
-// create the user filter form
+// Create the user filter form.
$ufiltering = new user_filtering();
-// array of bulk operations
-// create the bulk operations form
-$action_form = new user_bulk_action_form();
-if ($data = $action_form->get_data()) {
- // check if an action should be performed and do so
- switch ($data->action) {
- case 1: redirect($CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk_confirm.php');
- case 2: redirect($CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk_message.php');
- case 3: redirect($CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk_delete.php');
- case 4: redirect($CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk_display.php');
- case 5: redirect($CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk_download.php');
- case 7: redirect($CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk_forcepasswordchange.php');
- case 8: redirect($CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk_cohortadd.php');
+// Create the bulk operations form.
+$actionform = new user_bulk_action_form();
+if ($data = $actionform->get_data()) {
+ // Check if an action should be performed and do so.
+ $bulkactions = $actionform->get_actions();
+ if (array_key_exists($data->action, $bulkactions)) {
+ redirect($bulkactions[$data->action]->url);
}
+
}
-$user_bulk_form = new user_bulk_form(null, get_selection_data($ufiltering));
+$userbulkform = new user_bulk_form(null, get_selection_data($ufiltering));
-if ($data = $user_bulk_form->get_data()) {
+if ($data = $userbulkform->get_data()) {
if (!empty($data->addall)) {
add_selection_all($ufiltering);
if (in_array(0, $data->ausers)) {
add_selection_all($ufiltering);
} else {
- foreach($data->ausers as $userid) {
+ foreach ($data->ausers as $userid) {
if ($userid == -1) {
continue;
}
}
} else if (!empty($data->removeall)) {
- $SESSION->bulk_users= array();
+ $SESSION->bulk_users = array();
} else if (!empty($data->removesel)) {
if (!empty($data->susers)) {
if (in_array(0, $data->susers)) {
- $SESSION->bulk_users= array();
+ $SESSION->bulk_users = array();
} else {
- foreach($data->susers as $userid) {
+ foreach ($data->susers as $userid) {
if ($userid == -1) {
continue;
}
}
}
- // reset the form selections
+ // Reset the form selections.
unset($_POST);
- $user_bulk_form = new user_bulk_form(null, get_selection_data($ufiltering));
+ $userbulkform = new user_bulk_form(null, get_selection_data($ufiltering));
}
-// do output
echo $OUTPUT->header();
$ufiltering->display_add();
$ufiltering->display_active();
-$user_bulk_form->display();
+$userbulkform->display();
-$action_form->display();
+$actionform->display();
echo $OUTPUT->footer();
<?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/>.
+
+/**
+ * Bulk user action forms
+ *
+ * @package core
+ * @copyright Moodle
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir.'/formslib.php');
require_once($CFG->libdir.'/datalib.php');
+/**
+ * Bulk user action form
+ *
+ * @copyright Moodle
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
class user_bulk_action_form extends moodleform {
- function definition() {
- global $CFG;
- $mform =& $this->_form;
+ /**
+ * Returns an array of action_link's of all bulk actions available for this user.
+ *
+ * @return array of action_link objects
+ */
+ public function get_actions(): array {
+
+ global $CFG;
$syscontext = context_system::instance();
- $actions = array(0=>get_string('choose').'...');
+ $actions = [];
if (has_capability('moodle/user:update', $syscontext)) {
- $actions[1] = get_string('confirm');
+ $actions['confirm'] = new action_link(
+ new moodle_url('/admin/user/user_bulk_confirm.php'),
+ get_string('confirm'));
}
if (has_capability('moodle/site:readallmessages', $syscontext) && !empty($CFG->messaging)) {
- $actions[2] = get_string('messageselectadd');
+ $actions['message'] = new action_link(
+ new moodle_url('/admin/user/user_bulk_message.php'),
+ get_string('messageselectadd'));
}
if (has_capability('moodle/user:delete', $syscontext)) {
- $actions[3] = get_string('delete');
+ $actions['delete'] = new action_link(
+ new moodle_url('/admin/user/user_bulk_delete.php'),
+ get_string('delete'));
}
- $actions[4] = get_string('displayonpage');
+ $actions['displayonpage'] = new action_link(
+ new moodle_url('/admin/user/user_bulk_display.php'),
+ get_string('displayonpage'));
+
if (has_capability('moodle/user:update', $syscontext)) {
- $actions[5] = get_string('download', 'admin');
+ $actions['download'] = new action_link(
+ new moodle_url('/admin/user/user_bulk_download.php'),
+ get_string('download', 'admin'));
}
+
if (has_capability('moodle/user:update', $syscontext)) {
- $actions[7] = get_string('forcepasswordchange');
+ $actions['forcepasswordchange'] = new action_link(
+ new moodle_url('/admin/user/user_bulk_forcepasswordchange.php'),
+ get_string('forcepasswordchange'));
}
if (has_capability('moodle/cohort:assign', $syscontext)) {
- $actions[8] = get_string('bulkadd', 'core_cohort');
+ $actions['addtocohort'] = new action_link(
+ new moodle_url('/admin/user/user_bulk_cohortadd.php'),
+ get_string('bulkadd', 'core_cohort'));
+ }
+
+ // Any plugin can append actions to this list by implementing a callback
+ // <component>_bulk_user_actions() which returns an array of action_link.
+ // Each new action's key should have a frankenstyle prefix to avoid clashes.
+ // See MDL-38511 for more details.
+ $moreactions = get_plugins_with_function('bulk_user_actions', 'lib.php');
+ foreach ($moreactions as $plugintype => $plugins) {
+ foreach ($plugins as $pluginfunction) {
+ $actions += $pluginfunction();
+ }
+ }
+
+ return $actions;
+
+ }
+
+ /**
+ * Form definition
+ */
+ public function definition() {
+ global $CFG;
+
+ $mform =& $this->_form;
+
+ $actions = [0 => get_string('choose') . '...'];
+ $bulkactions = $this->get_actions();
+ foreach ($bulkactions as $key => $action) {
+ $actions[$key] = $action->text;
}
$objs = array();
$objs[] =& $mform->createElement('select', 'action', null, $actions);
}
}
+/**
+ * Bulk user form
+ *
+ * @copyright Moodle
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
class user_bulk_form extends moodleform {
- function definition() {
+
+ /**
+ * Form definition
+ */
+ public function definition() {
$mform =& $this->_form;
$acount =& $this->_customdata['acount'];
$objs[1] =& $mform->createElement('select', 'susers', get_string('selected', 'bulkusers'), $schoices, 'size="15"');
$objs[1]->setMultiple(true);
-
$grp =& $mform->addElement('group', 'usersgrp', get_string('users', 'bulkusers'), $objs, ' ', false);
$mform->addHelpButton('usersgrp', 'users', 'bulkusers');
* @param string $value Currently an assertion URL that is added to an image metadata.
*
* @return string $result File content with a new chunk as a string. Can be used in file_put_contents() to write to a file.
+ * @throws \moodle_exception when unsupported chunk type is defined.
*/
public function add_chunks($type, $key, $value) {
if (strlen($key) > 79) {
debugging('Key is too big');
}
- // tEXt Textual data.
- // Keyword: 1-79 bytes (character string)
- // Null separator: 1 byte
- // Text: n bytes (character string)
- $data = $key . "\0" . $value;
+ $dataparts = [];
+ if ($type === 'iTXt') {
+ // International textual data (iTXt).
+ // Keyword: 1-79 bytes (character string).
+ $dataparts[] = $key;
+ // Null separator: 1 byte.
+ $dataparts[] = "\x00";
+ // Compression flag: 1 byte
+ // A value of 0 means no compression.
+ $dataparts[] = "\x00";
+ // Compression method: 1 byte
+ // If compression is disabled, the method should also be 0.
+ $dataparts[] = "\x00";
+ // Language tag: 0 or more bytes (character string)
+ // When there is no language specified leave empty.
+
+ // Null separator: 1 byte.
+ $dataparts[] = "\x00";
+ // Translated keyword: 0 or more bytes
+ // When there is no translation specified, leave empty.
+
+ // Null separator: 1 byte.
+ $dataparts[] = "\x00";
+ // Text: 0 or more bytes.
+ $dataparts[] = $value;
+ } else if ($type === 'tEXt') {
+ // Textual data (tEXt).
+ // Keyword: 1-79 bytes (character string).
+ $dataparts[] = $key;
+ // Null separator: 1 byte.
+ $dataparts[] = "\0";
+ // Text: n bytes (character string).
+ $dataparts[] = $value;
+ } else {
+ throw new \moodle_exception('Unsupported chunk type: ' . $type);
+ }
+
+ $data = implode($dataparts);
+
$crc = pack("N", crc32($type . $data));
$len = pack("N", strlen($data));
// Chunk format: length + type + data + CRC.
// CRC is a CRC-32 computed over the chunk type and chunk data.
$newchunk = $len . $type . $data . $crc;
+ $this->_chunks[$type] = $data;
$result = substr($this->_contents, 0, $this->_size - 12)
. $newchunk
$categoryid = optional_param('category', null, PARAM_INT);
$courseid = optional_param('course', SITEID, PARAM_INT);
$view = optional_param('view', 'upcoming', PARAM_ALPHA);
+$day = optional_param('cal_d', 0, PARAM_INT);
+$mon = optional_param('cal_m', 0, PARAM_INT);
+$year = optional_param('cal_y', 0, PARAM_INT);
$time = optional_param('time', 0, PARAM_INT);
$lookahead = optional_param('lookahead', null, PARAM_INT);
$url = new moodle_url('/calendar/view.php');
+// If a day, month and year were passed then convert it to a timestamp. If these were passed
+// then we can assume the day, month and year are passed as Gregorian, as no where in core
+// should we be passing these values rather than the time. This is done for BC.
+if (!empty($day) && !empty($mon) && !empty($year)) {
+ if (checkdate($mon, $day, $year)) {
+ $time = make_timestamp($year, $mon, $day);
+ }
+}
+
if (empty($time)) {
$time = time();
}
$DB->delete_records(template_cohort::TABLE, array('cohortid' => $cohort->id));
}
+ /**
+ * Action to perform when a user is deleted.
+ *
+ * @param int $userid The user id.
+ */
+ public static function hook_user_deleted($userid) {
+ global $DB;
+
+ $usercompetencies = $DB->get_records(user_competency::TABLE, ['userid' => $userid], '', 'id');
+ foreach ($usercompetencies as $usercomp) {
+ $DB->delete_records(evidence::TABLE, ['usercompetencyid' => $usercomp->id]);
+ }
+
+ $DB->delete_records(user_competency::TABLE, ['userid' => $userid]);
+ $DB->delete_records(user_competency_course::TABLE, ['userid' => $userid]);
+ $DB->delete_records(user_competency_plan::TABLE, ['userid' => $userid]);
+
+ // Delete any associated files.
+ $fs = get_file_storage();
+ $context = context_user::instance($userid);
+ $userevidences = $DB->get_records(user_evidence::TABLE, ['userid' => $userid], '', 'id');
+ foreach ($userevidences as $userevidence) {
+ $DB->delete_records(user_evidence_competency::TABLE, ['userevidenceid' => $userevidence->id]);
+ $DB->delete_records(user_evidence::TABLE, ['id' => $userevidence->id]);
+ $fs->delete_area_files($context->id, 'core_competency', 'userevidence', $userevidence->id);
+ }
+
+ $userplans = $DB->get_records(plan::TABLE, ['userid' => $userid], '', 'id');
+ foreach ($userplans as $userplan) {
+ $DB->delete_records(plan_competency::TABLE, ['planid' => $userplan->id]);
+ $DB->delete_records(plan::TABLE, ['id' => $userplan->id]);
+ }
+ }
+
/**
* Manually grade a user competency.
*
$this->assertEquals(1, \core_competency\template_cohort::count_records(array('templateid' => $t1->get('id'))));
$this->assertEquals(0, \core_competency\template_cohort::count_records(array('templateid' => $t2->get('id'))));
}
+
+ public function test_hook_user_deleted() {
+ $this->resetAfterTest();
+ $dg = $this->getDataGenerator();
+ $ccg = $dg->get_plugin_generator('core_competency');
+
+ $u1 = $dg->create_user();
+
+ $framework = $ccg->create_framework();
+ $comp1 = $ccg->create_competency(['competencyframeworkid' => $framework->get('id')]);
+ $comp2 = $ccg->create_competency(['competencyframeworkid' => $framework->get('id')]);
+
+ $c1 = $dg->create_course();
+ $cc1a = $ccg->create_course_competency(['competencyid' => $comp1->get('id'), 'courseid' => $c1->id]);
+ $cc1b = $ccg->create_course_competency(['competencyid' => $comp2->get('id'), 'courseid' => $c1->id]);
+ $assign1a = $dg->create_module('assign', ['course' => $c1]);
+ $assign1b = $dg->create_module('assign', ['course' => $c1]);
+ $cmc1a = $ccg->create_course_module_competency(['competencyid' => $comp1->get('id'), 'cmid' => $assign1a->cmid]);
+ $cmc1b = $ccg->create_course_module_competency(['competencyid' => $comp1->get('id'), 'cmid' => $assign1b->cmid]);
+ $ucc1a = $ccg->create_user_competency_course(['competencyid' => $comp1->get('id'), 'courseid' => $c1->id,
+ 'userid' => $u1->id]);
+ $ucc1b = $ccg->create_user_competency_course(['competencyid' => $comp2->get('id'), 'courseid' => $c1->id,
+ 'userid' => $u1->id]);
+
+ $c2 = $dg->create_course();
+ $cc2a = $ccg->create_course_competency(['competencyid' => $comp1->get('id'), 'courseid' => $c2->id]);
+ $cc2b = $ccg->create_course_competency(['competencyid' => $comp2->get('id'), 'courseid' => $c2->id]);
+ $assign2a = $dg->create_module('assign', ['course' => $c2]);
+ $assign2b = $dg->create_module('assign', ['course' => $c2]);
+ $cmc2a = $ccg->create_course_module_competency(['competencyid' => $comp1->get('id'), 'cmid' => $assign2a->cmid]);
+ $cmc2b = $ccg->create_course_module_competency(['competencyid' => $comp1->get('id'), 'cmid' => $assign2b->cmid]);
+ $ucc2a = $ccg->create_user_competency_course(['competencyid' => $comp1->get('id'), 'courseid' => $c2->id,
+ 'userid' => $u1->id]);
+ $ucc2b = $ccg->create_user_competency_course(['competencyid' => $comp2->get('id'), 'courseid' => $c2->id,
+ 'userid' => $u1->id]);
+
+ reset_course_userdata((object) ['id' => $c1->id, 'reset_competency_ratings' => true]);
+
+ delete_user($u1);
+
+ // Assert the records don't exist anymore.
+ $this->assertEquals(0, user_competency_course::count_records(['courseid' => $c1->id, 'userid' => $u1->id]));
+ }
}
// $CFG->supportuserid = -20;
//
// Moodle 2.7 introduces a locking api for critical tasks (e.g. cron).
-// The default locking system to use is DB locking for Postgres, and file locking for
-// MySQL, Oracle and SQLServer. If $CFG->preventfilelocking is set, then the default
-// will always be DB locking. It can be manually set to one of the lock
+// The default locking system to use is DB locking for Postgres, MySQL, MariaDB and
+// file locking for Oracle and SQLServer. If $CFG->preventfilelocking is set, then the
+// default will always be DB locking. It can be manually set to one of the lock
// factory classes listed below, or one of your own custom classes implementing the
// \core\lock\lock_factory interface.
//
//
// "\\core\\lock\\db_record_lock_factory" - DB locking based on table rows.
//
+// "\\core\\lock\\mysql_lock_factory" - DB locking based on MySQL / MariaDB locks.
+//
// "\\core\\lock\\postgres_lock_factory" - DB locking based on postgres advisory locks.
//
// Settings used by the lock factories
* 0 - array of ids of top-level categories (always present)
* '0i' - array of ids of top-level categories that have visible=0 (always present but may be empty array)
* $id (int) - array of ids of categories that are direct children of category with id $id. If
- * category with id $id does not exist returns false. If category has no children returns empty array
+ * category with id $id does not exist, or category has no children, returns empty array
* $id.'i' - array of ids of children categories that have visible=0
*
* @param int|string $id
* @return mixed
*/
protected static function get_tree($id) {
+ $all = self::get_cached_cat_tree();
+ if (is_null($all) || !isset($all[$id])) {
+ // Could not get or rebuild the tree, or requested a non-existant ID.
+ return [];
+ } else {
+ return $all[$id];
+ }
+ }
+
+ /**
+ * Return the course category tree.
+ *
+ * Returns the category tree array, from the cache if available or rebuilding the cache
+ * if required. Uses locking to prevent the cache being rebuilt by multiple requests at once.
+ *
+ * @return array|null The tree as an array, or null if rebuilding the tree failed due to a lock timeout.
+ * @throws coding_exception
+ * @throws dml_exception
+ * @throws moodle_exception
+ */
+ private static function get_cached_cat_tree() : ?array {
$coursecattreecache = cache::make('core', 'coursecattree');
- $rv = $coursecattreecache->get($id);
- if ($rv !== false) {
- return $rv;
+ $all = $coursecattreecache->get('all');
+ if ($all !== false) {
+ return $all;
}
// Might need to rebuild the tree. Put a lock in place to ensure other requests don't try and do this in parallel.
$lockfactory = \core\lock\lock_config::get_lock_factory('core_coursecattree');
course_modinfo::COURSE_CACHE_LOCK_WAIT, course_modinfo::COURSE_CACHE_LOCK_EXPIRY);
if ($lock === false) {
// Couldn't get a lock to rebuild the tree.
- return [];
+ return null;
}
- $rv = $coursecattreecache->get($id);
- if ($rv !== false) {
+ $all = $coursecattreecache->get('all');
+ if ($all !== false) {
// Tree was built while we were waiting for the lock.
$lock->release();
- return $rv;
+ return $all;
}
// Re-build the tree.
try {
$all = self::rebuild_coursecattree_cache_contents();
- $coursecattreecache->set_many($all);
+ $coursecattreecache->set('all', $all);
} finally {
$lock->release();
}
- if (array_key_exists($id, $all)) {
- return $all[$id];
- }
- // Requested non-existing category.
- return array();
+ return $all;
}
/**
while (count($walk) > 0) {
$catid = array_pop($walk);
$directchildren = self::get_tree($catid);
- if ($directchildren !== false && count($directchildren) > 0) {
+ if (count($directchildren) > 0) {
$walk = array_merge($walk, $directchildren);
$children = array_merge($children, $directchildren);
}
return self::$singleton;
}
+ /**
+ * Run reset code after unit tests to reset the singleton usage.
+ */
+ public static function reset_caches(): void {
+ if (!PHPUNIT_TEST) {
+ throw new \coding_exception('This feature is only intended for use in unit tests');
+ }
+
+ static::$singleton = null;
+ }
+
/**
* The current user can configure custom fields on this component.
*
// Output section activities summary:
$o = '';
- $o.= html_writer::start_tag('div', array('class' => 'section-summary-activities mdl-right'));
+ $o.= html_writer::start_tag('div', array('class' => 'section-summary-activities pr-2 mdl-right'));
foreach ($sectionmods as $mod) {
$o.= html_writer::start_tag('span', array('class' => 'activity-count'));
$o.= $mod['name'].': '.$mod['count'];
$a->complete = $complete;
$a->total = $total;
- $o.= html_writer::start_tag('div', array('class' => 'section-summary-activities mdl-right'));
+ $o.= html_writer::start_tag('div', array('class' => 'section-summary-activities pr-2 mdl-right'));
$o.= html_writer::tag('span', get_string('progresstotal', 'completion', $a), array('class' => 'activity-count'));
$o.= html_writer::end_tag('div');
}
}
// Delete activity context questions and question categories.
- question_delete_activity($cm);
+ $showinfo = !defined('AJAX_SCRIPT') || AJAX_SCRIPT == '0';
+
+ question_delete_activity($cm, $showinfo);
// Call the delete_instance function, if it returns false throw an exception.
if (!$deleteinstancefunction($cm->instance)) {
}
/**
- * Get the list of admin settings for this module and apply any defaults/advanced/locked settings.
+ * Get the list of admin settings for this module and apply any defaults/advanced/locked/required settings.
*
* @param $datetimeoffsets array - If passed, this is an array of fieldnames => times that the
* default date/time value should be relative to. If not passed, all
if (!empty($settings->$advancedsetting)) {
$mform->setAdvanced($name);
}
+ $requiredsetting = $name . '_required';
+ if (!empty($settings->$requiredsetting)) {
+ $mform->addRule($name, null, 'required', null, 'client');
+ }
}
}
}
class core_customfield_api_testcase extends advanced_testcase {
/**
- * This method is called after the last test of this test class is run.
- */
- public static function tearDownAfterClass() {
- $handler = core_course\customfield\course_handler::create();
- $handler->delete_all();
- }
-
- /**
- * Tests set up.
- */
- public function setUp() {
- $this->resetAfterTest();
- }
-
- /**
- * Get generator
+ * Get generator.
+ *
* @return core_customfield_generator
*/
- protected function get_generator() : core_customfield_generator {
+ protected function get_generator(): core_customfield_generator {
return $this->getDataGenerator()->get_plugin_generator('core_customfield');
}
*
* @param array $expected
* @param array $array array of objects with "get($property)" method
- * @param sring $propertyname
+ * @param string $propertyname
*/
protected function assert_property_in_array($expected, $array, $propertyname) {
$this->assertEquals($expected, array_values(array_map(function($a) use ($propertyname) {
* in the interface using drag-drop.
*/
public function test_move_category() {
+ $this->resetAfterTest();
+
// Create the categories.
$params = ['component' => 'core_course', 'area' => 'course', 'itemid' => 0];
$id0 = $this->get_generator()->create_category($params)->get('id');
* Tests for \core_customfield\api::get_categories_with_fields() behaviour.
*/
public function test_get_categories_with_fields() {
+ $this->resetAfterTest();
+
// Create the categories.
$options = [
'component' => 'core_course',
* Test for functions api::save_category() and rename_category)
*/
public function test_save_category() {
+ $this->resetAfterTest();
+
$params = ['component' => 'core_course', 'area' => 'course', 'itemid' => 0, 'name' => 'Cat1',
'contextid' => context_system::instance()->id];
$c1 = category_controller::create(0, (object)$params);
* Test for function handler::create_category
*/
public function test_create_category() {
+ $this->resetAfterTest();
+
$handler = \core_course\customfield\course_handler::create();
$c1id = $handler->create_category();
$c1 = $handler->get_categories_with_fields()[$c1id];
* Tests for \core_customfield\api::delete_category() behaviour.
*/
public function test_delete_category_with_fields() {
+ $this->resetAfterTest();
+
global $DB;
// Create two categories with fields and data.
$options = [
class core_customfield_category_controller_testcase extends advanced_testcase {
/**
- * This method is called after the last test of this test class is run.
+ * Get generator.
+ *
+ * @return core_customfield_generator
*/
- public static function tearDownAfterClass() {
- $handler = core_course\customfield\course_handler::create();
- $handler->delete_all();
+ protected function get_generator(): core_customfield_generator {
+ return $this->getDataGenerator()->get_plugin_generator('core_customfield');
}
/**
- * Tests set up.
+ * Test for the field_controller::__construct function.
*/
- public function setUp() {
+ public function test_constructor() {
$this->resetAfterTest();
- }
-
- /**
- * Get generator
- * @return core_customfield_generator
- */
- protected function get_generator() : core_customfield_generator {
- return $this->getDataGenerator()->get_plugin_generator('core_customfield');
- }
- public function test_constructor() {
$c = category_controller::create(0, (object)['component' => 'core_course', 'area' => 'course', 'itemid' => 0]);
$handler = $c->get_handler();
$this->assertTrue($c instanceof category_controller);
*/
public function test_constructor_errors() {
global $DB;
+ $this->resetAfterTest();
+
$cat = $this->get_generator()->create_category();
$catrecord = $cat->to_record();
* \core_customfield\category_controller::get()
*/
public function test_create_category() {
+ $this->resetAfterTest();
// Create the category.
$lpg = $this->get_generator();
* Tests for \core_customfield\category_controller::set() behaviour.
*/
public function test_rename_category() {
+ $this->resetAfterTest();
+
// Create the category.
$params = ['component' => 'core_course', 'area' => 'course', 'itemid' => 0, 'name' => 'Cat1',
'contextid' => context_system::instance()->id];
* Tests for \core_customfield\category_controller::delete() behaviour.
*/
public function test_delete_category() {
+ $this->resetAfterTest();
+
// Create the category.
$lpg = $this->get_generator();
$category0 = $lpg->create_category();
class core_customfield_data_controller_testcase extends advanced_testcase {
/**
- * This method is called after the last test of this test class is run.
- */
- public static function tearDownAfterClass() {
- $handler = core_course\customfield\course_handler::create();
- $handler->delete_all();
- }
-
- /**
- * Tests set up.
- */
- public function setUp() {
- $this->resetAfterTest();
- }
-
- /**
- * Get generator
+ * Get generator.
+ *
* @return core_customfield_generator
*/
- protected function get_generator() : core_customfield_generator {
+ protected function get_generator(): core_customfield_generator {
return $this->getDataGenerator()->get_plugin_generator('core_customfield');
}
*/
public function test_constructor() {
global $DB;
+ $this->resetAfterTest();
+
// Create a course, fields category and fields.
$course = $this->getDataGenerator()->create_course();
$category0 = $this->get_generator()->create_category(['name' => 'aaaa']);
*/
public function test_constructor_errors() {
global $DB;
+ $this->resetAfterTest();
+
// Create a category, field and data.
$category = $this->get_generator()->create_category();
$field = $this->get_generator()->create_field(['categoryid' => $category->get('id')]);
$this->assertEquals(moodle_exception::class, get_class($e));
}
}
-}
\ No newline at end of file
+}
class core_customfield_field_controller_testcase extends advanced_testcase {
/**
- * This method is called after the last test of this test class is run.
- */
- public static function tearDownAfterClass() {
- $handler = core_course\customfield\course_handler::create();
- $handler->delete_all();
- }
-
- /**
- * Tests set up.
- */
- public function setUp() {
- $this->resetAfterTest();
- }
-
- /**
- * Get generator
+ * Get generator.
+ *
* @return core_customfield_generator
*/
- protected function get_generator() : core_customfield_generator {
+ protected function get_generator(): core_customfield_generator {
return $this->getDataGenerator()->get_plugin_generator('core_customfield');
}
*/
public function test_constructor() {
global $DB;
+ $this->resetAfterTest();
+
// Create the category.
$category0 = $this->get_generator()->create_category();
*/
public function test_constructor_errors() {
global $DB;
+ $this->resetAfterTest();
+
// Create a category and a field.
$category = $this->get_generator()->create_category();
$field = $this->get_generator()->create_field(['categoryid' => $category->get('id')]);
*/
public function test_create_field() {
global $DB;
+ $this->resetAfterTest();
+
$lpg = $this->get_generator();
$category = $lpg->create_category();
$fields = $DB->get_records(\core_customfield\field::TABLE, ['categoryid' => $category->get('id')]);
*/
public function test_delete_field() {
global $DB;
+ $this->resetAfterTest();
+
$lpg = $this->get_generator();
$category = $lpg->create_category();
$fields = $DB->get_records(\core_customfield\field::TABLE, ['categoryid' => $category->get('id')]);
* Tests for \core_customfield\field_controller::get_configdata_property() behaviour.
*/
public function test_get_configdata_property() {
+ $this->resetAfterTest();
+
$lpg = $this->get_generator();
$category = $lpg->create_category();
$configdata = ['a' => 'b', 'c' => ['d', 'e']];
$this->assertEquals(['d', 'e'], $field->get_configdata_property('c'));
$this->assertEquals(null, $field->get_configdata_property('x'));
}
-}
\ No newline at end of file
+}
*/
class core_customfield_generator_testcase extends advanced_testcase {
- /**
- * This method is called after the last test of this test class is run.
- */
- public static function tearDownAfterClass() {
- $handler = core_course\customfield\course_handler::create();
- $handler->delete_all();
- }
-
/**
* Get generator
* @return core_customfield_generator
*/
- protected function get_generator() : core_customfield_generator {
+ protected function get_generator(): core_customfield_generator {
return $this->getDataGenerator()->get_plugin_generator('core_customfield');
}
*/
class core_customfield_privacy_testcase extends provider_testcase {
- /** @var stdClass[] */
- private $courses = [];
- /** @var \core_customfield\category_controller[] */
- private $cfcats = [];
- /** @var \core_customfield\field_controller[] */
- private $cffields = [];
-
- /**
- * This method is called after the last test of this test class is run.
- */
- public static function tearDownAfterClass() {
- $handler = core_course\customfield\course_handler::create();
- $handler->delete_all();
- }
-
/**
- * Set up
+ * Generate data.
+ *
+ * @return array
*/
- public function setUp() {
+ protected function generate_test_data(): array {
$this->resetAfterTest();
- $this->cfcats[1] = $this->get_generator()->create_category();
- $this->cfcats[2] = $this->get_generator()->create_category();
- $this->cffields[11] = $this->get_generator()->create_field(
- ['categoryid' => $this->cfcats[1]->get('id'), 'type' => 'checkbox']);
- $this->cffields[12] = $this->get_generator()->create_field(
- ['categoryid' => $this->cfcats[1]->get('id'), 'type' => 'date']);
- $this->cffields[13] = $this->get_generator()->create_field(
- ['categoryid' => $this->cfcats[1]->get('id'),
+ $generator = $this->getDataGenerator()->get_plugin_generator('core_customfield');
+ $cfcats[1] = $generator->create_category();
+ $cfcats[2] = $generator->create_category();
+ $cffields[11] = $generator->create_field(
+ ['categoryid' => $cfcats[1]->get('id'), 'type' => 'checkbox']);
+ $cffields[12] = $generator->create_field(
+ ['categoryid' => $cfcats[1]->get('id'), 'type' => 'date']);
+ $cffields[13] = $generator->create_field(
+ ['categoryid' => $cfcats[1]->get('id'),
'type' => 'select', 'configdata' => ['options' => "a\nb\nc"]]);
- $this->cffields[14] = $this->get_generator()->create_field(
- ['categoryid' => $this->cfcats[1]->get('id'), 'type' => 'text']);
- $this->cffields[15] = $this->get_generator()->create_field(
- ['categoryid' => $this->cfcats[1]->get('id'), 'type' => 'textarea']);
- $this->cffields[21] = $this->get_generator()->create_field(
- ['categoryid' => $this->cfcats[2]->get('id')]);
- $this->cffields[22] = $this->get_generator()->create_field(
- ['categoryid' => $this->cfcats[2]->get('id')]);
-
- $this->courses[1] = $this->getDataGenerator()->create_course();
- $this->courses[2] = $this->getDataGenerator()->create_course();
- $this->courses[3] = $this->getDataGenerator()->create_course();
-
- $this->get_generator()->add_instance_data($this->cffields[11], $this->courses[1]->id, 1);
- $this->get_generator()->add_instance_data($this->cffields[12], $this->courses[1]->id, 1546300800);
- $this->get_generator()->add_instance_data($this->cffields[13], $this->courses[1]->id, 2);
- $this->get_generator()->add_instance_data($this->cffields[14], $this->courses[1]->id, 'Hello1');
- $this->get_generator()->add_instance_data($this->cffields[15], $this->courses[1]->id,
+ $cffields[14] = $generator->create_field(
+ ['categoryid' => $cfcats[1]->get('id'), 'type' => 'text']);
+ $cffields[15] = $generator->create_field(
+ ['categoryid' => $cfcats[1]->get('id'), 'type' => 'textarea']);
+ $cffields[21] = $generator->create_field(
+ ['categoryid' => $cfcats[2]->get('id')]);
+ $cffields[22] = $generator->create_field(
+ ['categoryid' => $cfcats[2]->get('id')]);
+
+ $courses[1] = $this->getDataGenerator()->create_course();
+ $courses[2] = $this->getDataGenerator()->create_course();
+ $courses[3] = $this->getDataGenerator()->create_course();
+
+ $generator->add_instance_data($cffields[11], $courses[1]->id, 1);
+ $generator->add_instance_data($cffields[12], $courses[1]->id, 1546300800);
+ $generator->add_instance_data($cffields[13], $courses[1]->id, 2);
+ $generator->add_instance_data($cffields[14], $courses[1]->id, 'Hello1');
+ $generator->add_instance_data($cffields[15], $courses[1]->id,
['text' => '<p>Hi there</p>', 'format' => FORMAT_HTML]);
- $this->get_generator()->add_instance_data($this->cffields[21], $this->courses[1]->id, 'hihi1');
+ $generator->add_instance_data($cffields[21], $courses[1]->id, 'hihi1');
- $this->get_generator()->add_instance_data($this->cffields[14], $this->courses[2]->id, 'Hello2');
+ $generator->add_instance_data($cffields[14], $courses[2]->id, 'Hello2');
- $this->get_generator()->add_instance_data($this->cffields[21], $this->courses[2]->id, 'hihi2');
+ $generator->add_instance_data($cffields[21], $courses[2]->id, 'hihi2');
- $this->setUser($this->getDataGenerator()->create_user());
- }
+ $user = $this->getDataGenerator()->create_user();
+ $this->setUser($user);
- /**
- * Get generator
- * @return core_customfield_generator
- */
- protected function get_generator() : core_customfield_generator {
- return $this->getDataGenerator()->get_plugin_generator('core_customfield');
+ return [
+ 'user' => $user,
+ 'cfcats' => $cfcats,
+ 'cffields' => $cffields,
+ 'courses' => $courses,
+ ];
}
/**
*/
public function test_get_customfields_data_contexts() {
global $DB;
- list($sql, $params) = $DB->get_in_or_equal([$this->courses[1]->id, $this->courses[2]->id], SQL_PARAMS_NAMED);
+ [
+ 'cffields' => $cffields,
+ 'cfcats' => $cfcats,
+ 'courses' => $courses,
+ ] = $this->generate_test_data();
+
+ list($sql, $params) = $DB->get_in_or_equal([$courses[1]->id, $courses[2]->id], SQL_PARAMS_NAMED);
$r = provider::get_customfields_data_contexts('core_course', 'course', '=0',
$sql, $params);
- $this->assertEquals([context_course::instance($this->courses[1]->id)->id,
- context_course::instance($this->courses[2]->id)->id],
+ $this->assertEquals([context_course::instance($courses[1]->id)->id,
+ context_course::instance($courses[2]->id)->id],
$r->get_contextids(), '', 0, 10, true);
}
* Test for provider::get_customfields_configuration_contexts()
*/
public function test_get_customfields_configuration_contexts() {
+ $this->generate_test_data();
+
$r = provider::get_customfields_configuration_contexts('core_course', 'course');
$this->assertEquals([context_system::instance()->id], $r->get_contextids());
}
*/
public function test_export_customfields_data() {
global $USER, $DB;
+ $this->resetAfterTest();
+ [
+ 'cffields' => $cffields,
+ 'cfcats' => $cfcats,
+ 'courses' => $courses,
+ ] = $this->generate_test_data();
+
// Hack one of the fields so it has an invalid field type.
- $invalidfieldid = $this->cffields[21]->get('id');
+ $invalidfieldid = $cffields[21]->get('id');
$DB->update_record('customfield_field', ['id' => $invalidfieldid, 'type' => 'invalid']);
- $context = context_course::instance($this->courses[1]->id);
+ $context = context_course::instance($courses[1]->id);
$contextlist = new approved_contextlist($USER, 'core_customfield', [$context->id]);
- provider::export_customfields_data($contextlist, 'core_course', 'course', '=0', '=:i', ['i' => $this->courses[1]->id]);
+ provider::export_customfields_data($contextlist, 'core_course', 'course', '=0', '=:i', ['i' => $courses[1]->id]);
/** @var core_privacy\tests\request\content_writer $writer */
$writer = writer::with_context($context);
$invaldfieldischecked = false;
foreach ($DB->get_records('customfield_data', []) as $dbrecord) {
$data = $writer->get_data(['Custom fields data', $dbrecord->id]);
- if ($dbrecord->instanceid == $this->courses[1]->id) {
+ if ($dbrecord->instanceid == $courses[1]->id) {
$this->assertEquals($dbrecord->fieldid, $data->fieldid);
$this->assertNotEmpty($data->fieldtype);
$this->assertNotEmpty($data->fieldshortname);
*/
public function test_delete_customfields_data() {
global $USER, $DB;
- $approvedcontexts = new approved_contextlist($USER, 'core_course', [context_course::instance($this->courses[1]->id)->id]);
+ $this->resetAfterTest();
+ [
+ 'cffields' => $cffields,
+ 'cfcats' => $cfcats,
+ 'courses' => $courses,
+ ] = $this->generate_test_data();
+
+ $approvedcontexts = new approved_contextlist($USER, 'core_course', [context_course::instance($courses[1]->id)->id]);
provider::delete_customfields_data($approvedcontexts, 'core_course', 'course');
- $this->assertEmpty($DB->get_records('customfield_data', ['instanceid' => $this->courses[1]->id]));
- $this->assertNotEmpty($DB->get_records('customfield_data', ['instanceid' => $this->courses[2]->id]));
+ $this->assertEmpty($DB->get_records('customfield_data', ['instanceid' => $courses[1]->id]));
+ $this->assertNotEmpty($DB->get_records('customfield_data', ['instanceid' => $courses[2]->id]));
}
/**
*/
public function test_delete_customfields_configuration() {
global $USER, $DB;
+ $this->resetAfterTest();
+ [
+ 'cffields' => $cffields,
+ 'cfcats' => $cfcats,
+ 'courses' => $courses,
+ ] = $this->generate_test_data();
+
// Remember the list of fields in the category 2 before we delete it.
- $catid1 = $this->cfcats[1]->get('id');
- $catid2 = $this->cfcats[2]->get('id');
+ $catid1 = $cfcats[1]->get('id');
+ $catid2 = $cfcats[2]->get('id');
$fids2 = $DB->get_fieldset_select('customfield_field', 'id', 'categoryid=?', [$catid2]);
$this->assertNotEmpty($fids2);
list($fsql, $fparams) = $DB->get_in_or_equal($fids2, SQL_PARAMS_NAMED);
*/
public function test_delete_customfields_configuration_for_context() {
global $USER, $DB;
+ $this->resetAfterTest();
+ [
+ 'cffields' => $cffields,
+ 'cfcats' => $cfcats,
+ 'courses' => $courses,
+ ] = $this->generate_test_data();
+
// Remember the list of fields in the category 2 before we delete it.
- $catid1 = $this->cfcats[1]->get('id');
- $catid2 = $this->cfcats[2]->get('id');
+ $catid1 = $cfcats[1]->get('id');
+ $catid2 = $cfcats[2]->get('id');
$fids2 = $DB->get_fieldset_select('customfield_field', 'id', 'categoryid=?', [$catid2]);
$this->assertNotEmpty($fids2);
list($fsql, $fparams) = $DB->get_in_or_equal($fids2, SQL_PARAMS_NAMED);
*/
public function test_delete_customfields_data_for_context() {
global $DB;
+ $this->resetAfterTest();
+ [
+ 'cffields' => $cffields,
+ 'cfcats' => $cfcats,
+ 'courses' => $courses,
+ ] = $this->generate_test_data();
+
provider::delete_customfields_data_for_context('core_course', 'course',
- context_course::instance($this->courses[1]->id));
+ context_course::instance($courses[1]->id));
$fids2 = $DB->get_fieldset_select('customfield_field', 'id', '1=1', []);
list($fsql, $fparams) = $DB->get_in_or_equal($fids2, SQL_PARAMS_NAMED);
- $fparams['course1'] = $this->courses[1]->id;
- $fparams['course2'] = $this->courses[2]->id;
+ $fparams['course1'] = $courses[1]->id;
+ $fparams['course2'] = $courses[2]->id;
$this->assertEmpty($DB->get_records_select('customfield_data', 'instanceid = :course1 AND fieldid ' . $fsql, $fparams));
$this->assertNotEmpty($DB->get_records_select('customfield_data', 'instanceid = :course2 AND fieldid ' . $fsql, $fparams));
}
// Check the mockstore for all objects with properties matching the key => val pairs in $criteria.
foreach ($mockstore as $index => $mockrow) {
$mockrowarr = (array)$mockrow;
- if (array_diff($criteria, $mockrowarr) == []) {
+ if (array_diff_assoc($criteria, $mockrowarr) == []) {
$returns[$index] = $mockrow;
}
}
$crit = ['userid' => $userid, 'component' => $comp, 'itemtype' => $type, 'itemid' => $id, 'contextid' => $ctxid];
foreach ($mockstore as $fakerow) {
$fakerowarr = (array)$fakerow;
- if (array_diff($crit, $fakerowarr) == []) {
+ if (array_diff_assoc($crit, $fakerowarr) == []) {
return $fakerow;
}
}
// Check the mockstore for all objects with properties matching the key => val pairs in $criteria.
foreach ($mockstore as $index => $mockrow) {
$mockrowarr = (array)$mockrow;
- if (array_diff($criteria, $mockrowarr) == []) {
+ if (array_diff_assoc($criteria, $mockrowarr) == []) {
$count++;
}
}
// Check the mockstore for all objects with properties matching the key => val pairs in $criteria.
foreach ($mockstore as $index => $mockrow) {
$mockrowarr = (array)$mockrow;
- if (array_diff($criteria, $mockrowarr) == []) {
+ if (array_diff_assoc($criteria, $mockrowarr) == []) {
unset($mockstore[$index]);
}
}
foreach ($mockstore as $index => $mockrow) {
$mockrowarr = (array)$mockrow;
echo "Here";
- if (array_diff($criteria, $mockrowarr) == []) {
+ if (array_diff_assoc($criteria, $mockrowarr) == []) {
return true;
}
}
// Check the mockstore for all objects with properties matching the key => val pairs in $criteria.
foreach ($mockstore as $index => $mockrow) {
$mockrowarr = (array)$mockrow;
- if (array_diff($criteria, $mockrowarr) == []) {
+ if (array_diff_assoc($criteria, $mockrowarr) == []) {
$returns[$index] = $mockrow;
}
}
$crit = ['userid' => $userid, 'component' => $comp, 'itemtype' => $type, 'itemid' => $id, 'contextid' => $ctxid];
foreach ($mockstore as $fakerow) {
$fakerowarr = (array)$fakerow;
- if (array_diff($crit, $fakerowarr) == []) {
+ if (array_diff_assoc($crit, $fakerowarr) == []) {
return $fakerow;
}
}
// Check the mockstore for all objects with properties matching the key => val pairs in $criteria.
foreach ($mockstore as $index => $mockrow) {
$mockrowarr = (array)$mockrow;
- if (array_diff($criteria, $mockrowarr) == []) {
+ if (array_diff_assoc($criteria, $mockrowarr) == []) {
$count++;
}
}
// Check the mockstore for all objects with properties matching the key => val pairs in $criteria.
foreach ($mockstore as $index => $mockrow) {
$mockrowarr = (array)$mockrow;
- if (array_diff($criteria, $mockrowarr) == []) {
+ if (array_diff_assoc($criteria, $mockrowarr) == []) {
return true;
}
}
$string['invalidmd5'] = 'Η μεταβλητή ελέγχου ήταν λανθασμένη - δοκιμάστε ξανά';
$string['missingrequiredfield'] = 'Κάποιο απαιτούμενο πεδίο λείπει';
$string['remotedownloaderror'] = '<p>Η λήψη του στοιχείου λογισμικού στον εξυπηρετητή σας απέτυχε. Παρακαλούμε επαληθεύστε τις ρυθμίσεις του διακομιστή μεσολάβησης (proxy)· η επέκταση PHP cURL συνιστάται θερμά.</p><br /><p>Πρέπει να κατεβάσετε το αρχείο <a href="{$a->url}">{$a->url}</a> χειροκίνητα, να το αντιγράψετε στο «{$a->dest}» στον εξυπηρετητή σας και να το αποσυμπιέσετε εκεί.</p>';
-$string['wrongdestpath'] = 'Î\9bανθαÏ\83μÎνη διαδÏ\81ομή Ï\80Ï\81οοÏ\81ιÏ\83μοÏ\8d (Ï\80λήÏ\81εÏ\82 Ï\8cνομα).';
+$string['wrongdestpath'] = 'Î\9bανθαÏ\83μÎνο μονοÏ\80άÏ\84ι Ï\80Ï\81οοÏ\81ιÏ\83μοÏ\8d.';
$string['wrongsourcebase'] = 'Λανθασμένη βάση πηγής URL.';
$string['wrongzipfilename'] = 'Λανθασμένo όνομα αρχείου ZIP.';
--- /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/>.
+
+/**
+ * Automatically generated strings for Moodle installer
+ *
+ * Do not edit this file manually! It contains just a subset of strings
+ * needed during the very first steps of installation. This file was
+ * generated automatically by export-installer.php (which is part of AMOS
+ * {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
+ * list of strings defined in /install/stringnames.txt.
+ *
+ * @package installer
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$string['clianswerno'] = 'ל';
+$string['cliansweryes'] = 'כ';
+$string['cliincorrectvalueretry'] = 'ערך לא תקין, נסו שוב בבקשה';
$string['requiredentrieschanged'] = 'Note: After upgrading, the setting \'Required entries before viewing\' is now enforced in the following database activities:<br/>{$a->text}<br/>';
$string['requiremodintro'] = 'Require activity description';
$string['requiremodintro_desc'] = 'If enabled, users will be forced to enter a description for each activity.';
+$string['required'] = 'Required';
$string['requires'] = 'Requires';
$string['purgecaches'] = 'Purge all caches';
$string['purgecachesconfirm'] = 'Moodle can cache themes, javascript, language strings, filtered text, rss feeds and many other pieces of calculated data. Purging these caches will delete that data from the server and force browsers to refetch data, so that you can be sure you are seeing the most up-to-date values produced by the current code. There is no danger in purging caches, but your site may appear slower for a while until the server and clients calculate new information and cache it.';
$this->set_flag_options($enabled, $default, 'locked', new lang_string('locked', 'core_admin'));
}
+ /**
+ * Set the required options flag on this admin setting.
+ *
+ * @param bool $enabled - One of self::OPTION_ENABLED or self::OPTION_DISABLED.
+ * @param bool $default - The default for the flag.
+ */
+ public function set_required_flag_options($enabled, $default) {
+ $this->set_flag_options($enabled, $default, 'required', new lang_string('required', 'core_admin'));
+ }
+
/**
* Get the currently saved value for a setting flag
*
/**
* An additional option that can be applied to an admin setting.
- * The currently supported options are 'ADVANCED' and 'LOCKED'.
+ * The currently supported options are 'ADVANCED', 'LOCKED' and 'REQUIRED'.
*
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Latest version is available at http://adodb.org/
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Latest version is available at http://adodb.org/
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- * @version v5.20.15 24-Nov-2019
+ * @version v5.20.16 12-Jan-2020
* @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
* @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
* Released under both BSD license and Lesser GPL library license.
<?php
/**
- * @version v5.20.15 24-Nov-2019
+ * @version v5.20.16 12-Jan-2020
* @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
* @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
* Released under both BSD license and Lesser GPL library license.
<?php
/**
- * @version v5.20.15 24-Nov-2019
+ * @version v5.20.16 12-Jan-2020
* @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
* @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
* Released under both BSD license and Lesser GPL library license.
<?php
/**
- * @version v5.20.15 24-Nov-2019
+ * @version v5.20.16 12-Jan-2020
* @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
* @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
* Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
$ADODB_INCLUDED_LIB = 1;
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- * @version v5.20.15 24-Nov-2019
+ * @version v5.20.16 12-Jan-2020
* @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
* @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
* Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
Latest version is available at http://adodb.org/
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
/**
\mainpage
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
/**
* ADODB version as a string.
*/
- $ADODB_vers = 'v5.20.15 24-Nov-2019';
+ $ADODB_vers = 'v5.20.16 12-Jan-2020';
/**
* Determines whether recordset->RecordCount() is used.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
-* @version v5.20.15 24-Nov-2019
+* @version v5.20.16 12-Jan-2020
* @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
* @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
* Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim. All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
is running. All associated result memory for the specified result identifier will automatically be freed. */
function _close()
{
- if(is_object($this->_queryID)) {
+ if(is_resource($this->_queryID)) {
$rez = sqlsrv_free_stmt($this->_queryID);
$this->_queryID = false;
return $rez;
<?php
/**
-* @version v5.20.15 24-Nov-2019
+* @version v5.20.16 12-Jan-2020
* @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
* @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
* Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim. All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
<?php
/**
- * @version v5.20.15 24-Nov-2019
+ * @version v5.20.16 12-Jan-2020
* @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
* @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
* Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim. All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
/*
* find the next character of the string
*/
- $c = $sql[$i];
+ $c = $sql[$i];
if ($c == "'" && !$inString && $escaped==0)
/*
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim. All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
reserved.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim. All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/*
-@version v5.20.15 24-Nov-2019
+@version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
<?php
/**
- * @version v5.20.15 24-Nov-2019
+ * @version v5.20.16 12-Jan-2020
* @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
* @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
* Released under both BSD license and Lesser GPL library license.
-Description of ADODB V5.20.15 library import into Moodle
+Description of ADODB V5.20.16 library import into Moodle
This library will be probably removed in Moodle 2.1,
it is now used only in enrol and auth db plugins.
Our changes:
* MDL-67034 Fixes to make the library php74 compliant.
-
-skodak, iarenaza, moodler, stronk7, abgreeve, lameze, ankitagarwal, marinaglancy, rezaie9
<?php
/**
- * @version v5.20.15 24-Nov-2019
+ * @version v5.20.16 12-Jan-2020
* @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
* @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
* Released under both BSD license and Lesser GPL library license.
<?php
/**
- * @version v5.20.15 24-Nov-2019
+ * @version v5.20.16 12-Jan-2020
* @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
* @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
* Released under both BSD license and Lesser GPL library license.
<?php
/*
- @version v5.20.15 24-Nov-2019
+ @version v5.20.16 12-Jan-2020
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
});
var context = $.extend({items: items}, options, state);
// Render the template.
- return templates.render('core/form_autocomplete_selection', context)
+ return templates.render('core/form_autocomplete_selection_items', context)
.then(function(html, js) {
// Add it to the page.
templates.replaceNodeContents(newSelection, html, js);
// return SCAN_RESULT_FOUND result.
if ($this->get_config('clamfailureonupload') === 'actlikevirus') {
return self::SCAN_RESULT_FOUND;
+ } else if ($this->get_config('clamfailureonupload') === 'tryagain') {
+ // Do not upload the file, just give a message to the user to try again later.
+ unlink($file);
+ throw new \core\antivirus\scanner_exception('antivirusfailed', '', ['item' => $filename],
+ null, 'antivirus_clamav');
}
}
return $return;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+$string['antivirusfailed'] = 'There is a problem with AntiVirus scanning at the moment. Your file {$a->item} has not been uploaded. Please try again later.';
$string['configclamactlikevirus'] = 'Treat files like viruses';
$string['configclamdonothing'] = 'Treat files as OK';
-$string['configclamfailureonupload'] = 'If you have configured clam to scan uploaded files, but it is configured incorrectly or fails to run for some unknown reason, how should it behave? If you choose \'Treat files like viruses\', they\'ll be moved into the quarantine area, or deleted. If you choose \'Treat files as OK\', the files will be moved to the destination directory like normal. Either way, admins will be alerted that clam has failed. If you choose \'Treat files like viruses\' and for some reason clam fails to run (usually because you have entered an invalid pathtoclam), ALL files that are uploaded will be moved to the given quarantine area, or deleted. Be careful with this setting.';
+$string['configclamfailureonupload'] = 'If you have configured clam to scan uploaded files, but it is configured incorrectly or fails to run for some unknown reason, how should it behave? If you choose \'Treat files like viruses\', they\'ll be moved into the quarantine area, or deleted. If you choose \'Treat files as OK\', the files will be moved to the destination directory like normal. If you choose \'Refuse upload, try again\' (useful if failures occur during regular virus updating periods) a try again later message will be displayed to the user. Either way, admins will be alerted that clam has failed. If you choose \'Treat files like viruses\' and for some reason clam fails to run (usually because you have entered an invalid pathtoclam), ALL files that are uploaded will be moved to the given quarantine area, or deleted. Be careful with this setting.';
+$string['configclamtryagain'] = 'Refuse upload, try again';
$string['clamfailed'] = 'ClamAV has failed to run. The return error message was "{$a}". Here is the output from ClamAV:';
$string['clamfailureonupload'] = 'On ClamAV failure';
$string['errorcantopensocket'] = 'Connecting to Unix domain socket resulted in error {$a}';
$options = array(
'donothing' => new lang_string('configclamdonothing', 'antivirus_clamav'),
'actlikevirus' => new lang_string('configclamactlikevirus', 'antivirus_clamav'),
+ 'tryagain' => new lang_string('configclamtryagain', 'antivirus_clamav')
);
$settings->add(new admin_setting_configselect('antivirus_clamav/clamfailureonupload',
new lang_string('clamfailureonupload', 'antivirus_clamav'),
$this->assertEquals(1, $antivirus->scan_file($this->tempfile, ''));
}
+ public function test_scan_file_error_tryagain() {
+ $methods = array(
+ 'scan_file_execute_commandline',
+ 'scan_file_execute_unixsocket',
+ 'message_admins',
+ 'get_config',
+ 'get_scanning_notice',
+ );
+ $antivirus = $this->getMockBuilder('\antivirus_clamav\scanner')->setMethods($methods)->getMock();
+
+ // Configure scan_file_execute_commandline and scan_file_execute_unixsocket
+ // method stubs to behave as if there is a scanning error (SCAN_RESULT_ERROR).
+ $antivirus->method('scan_file_execute_commandline')->willReturn(2);
+ $antivirus->method('scan_file_execute_unixsocket')->willReturn(2);
+ $antivirus->method('get_scanning_notice')->willReturn('someerror');
+
+ // Set expectation that message_admins is called.
+ $antivirus->expects($this->atLeastOnce())->method('message_admins')->with($this->equalTo('someerror'));
+
+ // Initiate mock scanning with configuration setting to act like virus on
+ // scanning error and using commandline.
+ $configmap = array(array('clamfailureonupload', 'tryagain'), array('runningmethod', 'commandline'));
+ $antivirus->method('get_config')->will($this->returnValueMap($configmap));
+
+ // Run mock scanning.
+ $this->assertFileExists($this->tempfile);
+ $this->expectException(\core\antivirus\scanner_exception::class);
+ $antivirus->scan_file($this->tempfile, '');
+ $this->assertEquals('antivirusfailed', $this->getExpectedExceptionCode());
+ $this->assertFileNotExists($this->tempfile);
+ }
+
public function test_scan_data_no_virus() {
$methods = array(
'scan_data_execute_socket',
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2019122900; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->version = 2020012400; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2019111200; // Requires this Moodle version.
$plugin->component = 'antivirus_clamav'; // Full name of the plugin (used for diagnostics).
$contents = $file->get_content();
$filehandler = new PNG_MetaDataHandler($contents);
- $assertion = new moodle_url('/badges/assertion.php', array('b' => $hash));
- if ($filehandler->check_chunks("tEXt", "openbadges")) {
- // Add assertion URL tExt chunk.
- $newcontents = $filehandler->add_chunks("tEXt", "openbadges", $assertion->out(false));
+ // For now, the site backpack OB version will be used as default.
+ $obversion = badges_open_badges_backpack_api();
+ $assertion = new core_badges_assertion($hash, $obversion);
+ $assertionjson = json_encode($assertion->get_badge_assertion());
+ if ($filehandler->check_chunks("iTXt", "openbadges")) {
+ // Add assertion URL iTXt chunk.
+ $newcontents = $filehandler->add_chunks("iTXt", "openbadges", $assertionjson);
$fileinfo = array(
'contextid' => $user_context->id,
'component' => 'badges',
* @param string $link
* @param mixed $a
* @param mixed $debuginfo
+ * @param string $module optional plugin name
*/
- public function __construct($errorcode, $link = '', $a = null, $debuginfo = null) {
- parent::__construct($errorcode, 'antivirus', $link, $a, $debuginfo);
+ public function __construct($errorcode, $link = '', $a = null, $debuginfo = null, $module = 'antivirus') {
+ parent::__construct($errorcode, $module, $link, $a, $debuginfo);
}
}
* Collection of components related methods.
*/
class core_component {
- /** @var array list of ignored directories - watch out for auth/db exception */
- protected static $ignoreddirs = array('CVS'=>true, '_vti_cnf'=>true, 'simpletest'=>true, 'db'=>true, 'yui'=>true, 'tests'=>true, 'classes'=>true, 'fonts'=>true);
+ /** @var array list of ignored directories in plugin type roots - watch out for auth/db exception */
+ protected static $ignoreddirs = [
+ 'CVS' => true,
+ '_vti_cnf' => true,
+ 'amd' => true,
+ 'classes' => true,
+ 'db' => true,
+ 'fonts' => true,
+ 'lang' => true,
+ 'pix' => true,
+ 'simpletest' => true,
+ 'templates' => true,
+ 'tests' => true,
+ 'yui' => true,
+ ];
/** @var array list plugin types that support subplugins, do not add more here unless absolutely necessary */
protected static $supportsubplugins = array('mod', 'editor', 'tool', 'local');
--- /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/>.
+
+/**
+ * MySQL / MariaDB locking factory.
+ *
+ * @package core
+ * @category lock
+ * @copyright Brendan Heywood <brendan@catalyst-au.net>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core\lock;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * MySQL / MariaDB locking factory.
+ *
+ * @package core
+ * @category lock
+ * @copyright Brendan Heywood <brendan@catalyst-au.net>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class mysql_lock_factory implements lock_factory {
+
+ /** @var string $dbprefix - used as a namespace for these types of locks */
+ protected $dbprefix = '';
+
+ /** @var \moodle_database $db Hold a reference to the global $DB */
+ protected $db;
+
+ /** @var array $openlocks - List of held locks - used by auto-release */
+ protected $openlocks = [];
+
+ /**
+ * Return a unique prefix based on the database name and prefix.
+ * @param string $type - Used to prefix lock keys.
+ * @return string.
+ */
+ protected function get_unique_db_prefix($type) {
+ global $CFG;
+ $prefix = $CFG->dbname . ':';
+ if (isset($CFG->prefix)) {
+ $prefix .= $CFG->prefix;
+ }
+ $prefix .= '_' . $type . '_';
+ return $prefix;
+ }
+
+ /**
+ * Lock constructor.
+ * @param string $type - Used to prefix lock keys.
+ */
+ public function __construct($type) {
+ global $DB;
+
+ $this->dbprefix = $this->get_unique_db_prefix($type);
+ // Save a reference to the global $DB so it will not be released while we still have open locks.
+ $this->db = $DB;
+
+ \core_shutdown_manager::register_function([$this, 'auto_release']);
+ }
+
+ /**
+ * Is available.
+ * @return boolean - True if this lock type is available in this environment.
+ */
+ public function is_available() {
+ return $this->db->get_dbfamily() === 'mysql';
+ }
+
+ /**
+ * Return information about the blocking behaviour of the lock type on this platform.
+ * @return boolean - Defer to the DB driver.
+ */
+ public function supports_timeout() {
+ return true;
+ }
+
+ /**
+ * Will this lock type will be automatically released when a process ends.
+ *
+ * @return boolean - Via shutdown handler.
+ */
+ public function supports_auto_release() {
+ return true;
+ }
+
+ /**
+ * Multiple locks for the same resource can NOT be held by a single process.
+ *
+ * Hard coded to false and workaround inconsistent support in different
+ * versions of MySQL / MariaDB.
+ *
+ * @return boolean - false
+ */
+ public function supports_recursion() {
+ return false;
+ }
+
+ /**
+ * Create and get a lock
+ * @param string $resource - The identifier for the lock. Should use frankenstyle prefix.
+ * @param int $timeout - The number of seconds to wait for a lock before giving up.
+ * @param int $maxlifetime - Unused by this lock type.
+ * @return boolean - true if a lock was obtained.
+ */
+ public function get_lock($resource, $timeout, $maxlifetime = 86400) {
+
+ // We sha1 to avoid long key names hitting the mysql str limit.
+ $resourcekey = sha1($this->dbprefix . $resource);
+
+ // Even though some versions of MySQL and MariaDB can support stacked locks
+ // just never stack them and always fail fast.
+ if (isset($this->openlocks[$resourcekey])) {
+ return false;
+ }
+
+ $params = [
+ 'resourcekey' => $resourcekey,
+ 'timeout' => $timeout
+ ];
+
+ $result = $this->db->get_record_sql('SELECT GET_LOCK(:resourcekey, :timeout) AS locked', $params);
+ $locked = $result->locked == 1;
+
+ if ($locked) {
+ $this->openlocks[$resourcekey] = 1;
+ return new lock($resourcekey, $this);
+ }
+ return false;
+ }
+
+ /**
+ * Release a lock that was previously obtained with @lock.
+ * @param lock $lock - a lock obtained from this factory.
+ * @return boolean - true if the lock is no longer held (including if it was never held).
+ */
+ public function release_lock(lock $lock) {
+
+ $params = [
+ 'resourcekey' => $lock->get_key()
+ ];
+ $result = $this->db->get_record_sql('SELECT RELEASE_LOCK(:resourcekey) AS unlocked', $params);
+ $result = $result->unlocked == 1;
+ if ($result) {
+ unset($this->openlocks[$lock->get_key()]);
+ }
+ return $result;
+ }
+
+ /**
+ * Extend a lock that was previously obtained with @lock.
+ * @param lock $lock - a lock obtained from this factory.
+ * @param int $maxlifetime - the new lifetime for the lock (in seconds).
+ * @return boolean - true if the lock was extended.
+ */
+ public function extend_lock(lock $lock, $maxlifetime = 86400) {
+ // Not supported by this factory.
+ return false;
+ }
+
+ /**
+ * Auto release any open locks on shutdown.
+ * This is required, because we may be using persistent DB connections.
+ */
+ public function auto_release() {
+ // Called from the shutdown handler. Must release all open locks.
+ foreach ($this->openlocks as $key => $unused) {
+ $lock = new lock($key, $this);
+ $lock->release();
+ }
+ }
+
+}
// Trigger event for sending a message or notification - we need to do this before marking as read!
self::trigger_message_events($eventdata, $savemessage);
- if ($eventdata->notification or empty($CFG->messaging)) {
- // If they have deselected all processors and its a notification mark it read. The user doesn't want to be bothered.
- // The same goes if the messaging is completely disabled.
- if ($eventdata->notification) {
- $savemessage->timeread = null;
- \core_message\api::mark_notification_as_read($savemessage);
- } else {
- \core_message\api::mark_message_as_read($eventdata->userto->id, $savemessage);
- }
+ if ($eventdata->notification) {
+ // If they have deselected all processors and it's a notification mark it read. The user doesn't want to be
+ // bothered.
+ $savemessage->timeread = null;
+ \core_message\api::mark_notification_as_read($savemessage);
+ } else if (empty($CFG->messaging)) {
+ // If it's a message and messaging is disabled mark it read.
+ \core_message\api::mark_message_as_read($eventdata->userto->id, $savemessage);
}
return $savemessage->id;
// Trigger event for sending a message or notification - we need to do this before marking as read!
self::trigger_message_events($eventdata, $savemessage);
- if (empty($CFG->messaging)) {
- // If they have deselected all processors and its a notification mark it read. The user doesn't want to be bothered.
- // The same goes if the messaging is completely disabled.
- if ($eventdata->notification) {
- $savemessage->timeread = null;
- \core_message\api::mark_notification_as_read($savemessage);
- } else {
- \core_message\api::mark_message_as_read($eventdata->userto->id, $savemessage);
- }
+ if (!$eventdata->notification && empty($CFG->messaging)) {
+ // If it's a message and messaging is disabled mark it read.
+ \core_message\api::mark_message_as_read($eventdata->userto->id, $savemessage);
}
return $savemessage->id;
return;
}
- $DB->delete_records_list('task_log', 'id', $logids);
+ $chunks = array_chunk($logids, 1000);
+ foreach ($chunks as $chunk) {
+ $DB->delete_records_list('task_log', 'id', $chunk);
+ }
}
}
// Now loop through again and remove old files and directories.
for ($iter->rewind(); $iter->valid(); $iter->next()) {
$node = $iter->getRealPath();
- if (!is_readable($node)) {
+ if (!isset($modifieddateobject[$node]) || !is_readable($node)) {
continue;
}
upgrade_main_savepoint(true, 2020011700.02);
}
+ if ($oldversion < 2020013000.01) {
+ global $DB;
+ // Delete any associated files.
+ $fs = get_file_storage();
+ $sql = "SELECT cuc.id, cuc.userid
+ FROM {competency_usercomp} cuc
+ LEFT JOIN {user} u ON cuc.userid = u.id
+ WHERE u.deleted = 1";
+ $usercompetencies = $DB->get_records_sql($sql);
+ foreach ($usercompetencies as $usercomp) {
+ $DB->delete_records('competency_evidence', ['usercompetencyid' => $usercomp->id]);
+ $DB->delete_records('competency_usercompcourse', ['userid' => $usercomp->userid]);
+ $DB->delete_records('competency_usercompplan', ['userid' => $usercomp->userid]);
+ $DB->delete_records('competency_usercomp', ['userid' => $usercomp->userid]);
+ }
+
+ $sql = "SELECT cue.id, cue.userid
+ FROM {competency_userevidence} cue
+ LEFT JOIN {user} u ON cue.userid = u.id
+ WHERE u.deleted = 1";
+ $userevidences = $DB->get_records_sql($sql);
+ foreach ($userevidences as $userevidence) {
+ $DB->delete_records('competency_userevidencecomp', ['userevidenceid' => $userevidence->id]);
+ $DB->delete_records('competency_userevidence', ['id' => $userevidence->id]);
+
+ $context = context_user::instance($userevidence->userid);
+ $fs->delete_area_files($context->id, 'core_competency', 'userevidence', $userevidence->id);
+ }
+
+ $sql = "SELECT cp.id
+ FROM {competency_plan} cp
+ LEFT JOIN {user} u ON cp.userid = u.id
+ WHERE u.deleted = 1";
+ $userplans = $DB->get_records_sql($sql);
+ foreach ($userplans as $userplan) {
+ $DB->delete_records('competency_plancomp', ['planid' => $userplan->id]);
+ $DB->delete_records('competency_plan', ['id' => $userplan->id]);
+ }
+
+ // Main savepoint reached.
+ upgrade_main_savepoint(true, 2020013000.01);
+ }
+
return true;
}
throw new ddl_exception('ddlunknownerror', null, 'table drop sql not generated');
}
$this->execute_sql_arr($sqlarr, array($xmldb_table->getName()));
+
+ $this->generator->cleanup_after_drop($xmldb_table);
}
/**
return $sqlarr;
}
- /**
- * Given one correct xmldb_table, returns the SQL statements
- * to drop it (inside one array).
- *
- * @param xmldb_table $xmldb_table The table to drop.
- * @return array SQL statement(s) for dropping the specified table.
- */
- public function getDropTableSQL($xmldb_table) {
- $sqlarr = parent::getDropTableSQL($xmldb_table);
- if ($this->temptables->is_temptable($xmldb_table->getName())) {
- $this->temptables->delete_temptable($xmldb_table->getName());
- }
- return $sqlarr;
- }
-
/**
* Given one XMLDB Type, length and decimals, returns the DB proper SQL type.
*
$sqlarr = parent::getDropTableSQL($xmldb_table);
if ($this->temptables->is_temptable($xmldb_table->getName())) {
$sqlarr = preg_replace('/^DROP TABLE/', "DROP TEMPORARY TABLE", $sqlarr);
- $this->temptables->delete_temptable($xmldb_table->getName());
}
return $sqlarr;
}
$sqlarr = parent::getDropTableSQL($xmldb_table);
if ($this->temptables->is_temptable($xmldb_table->getName())) {
array_unshift($sqlarr, "TRUNCATE TABLE ". $this->getTableName($xmldb_table)); // oracle requires truncate before being able to drop a temp table
- $this->temptables->delete_temptable($xmldb_table->getName());
}
return $sqlarr;
}
return $sqlarr;
}
- /**
- * Given one correct xmldb_table, returns the SQL statements
- * to drop it (inside one array).
- *
- * @param xmldb_table $xmldb_table The table to drop.
- * @return array SQL statement(s) for dropping the specified table.
- */
- public function getDropTableSQL($xmldb_table) {
- $sqlarr = parent::getDropTableSQL($xmldb_table);
- if ($this->temptables->is_temptable($xmldb_table->getName())) {
- $this->temptables->delete_temptable($xmldb_table->getName());
- }
- return $sqlarr;
- }
-
/**
* Given one correct xmldb_index, returns the SQL statements
* needed to create it (in array).
}
/**
- * Given one correct xmldb_table and the new name, returns the SQL statements
+ * Given one correct xmldb_table, returns the SQL statements
* to drop it (inside one array). Works also for temporary tables.
*
* @param xmldb_table $xmldb_table The table to drop.
return $results;
}
+ /**
+ * Performs any clean up that needs to be done after a table is dropped.
+ *
+ * @param xmldb_table $table
+ */
+ public function cleanup_after_drop(xmldb_table $table): void {
+ if ($this->temptables->is_temptable($table->getName())) {
+ $this->temptables->delete_temptable($table->getName());
+ }
+ }
+
/**
* Given one xmldb_table and one xmldb_field, return the SQL statements needed to add the field to the table.
*
$this->assertFalse($dbman->table_exists('test_table1'));
}
+ /**
+ * get_columns should return an empty array for ex-temptables.
+ */
+ public function test_leftover_temp_tables_columns() {
+ $DB = $this->tdb; // Do not use global $DB!
+ $dbman = $this->tdb->get_manager();
+
+ // Create temp table0.
+ $table0 = $this->tables['test_table0'];
+ $dbman->create_temp_table($table0);
+
+ $dbman->drop_table($table0);
+
+ // Get columns and perform some basic tests.
+ $columns = $DB->get_columns('test_table0');
+ $this->assertEquals([], $columns);
+ }
+
+ /**
+ * Deleting a temp table should not purge the whole cache
+ */
+ public function test_leftover_temp_tables_cache() {
+ $DB = $this->tdb; // Do not use global $DB!
+ $dbman = $this->tdb->get_manager();
+
+ // Create 2 temp tables.
+ $table0 = $this->tables['test_table0'];
+ $dbman->create_temp_table($table0);
+ $table1 = $this->tables['test_table1'];
+ $dbman->create_temp_table($table1);
+
+ // Create a normal table.
+ $table2 = new xmldb_table ('test_table2');
+ $table2->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+ $table2->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
+ $table2->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+ $table2->setComment("This is a test'n drop table. You can drop it safely");
+ $this->tables[$table2->getName()] = $table2;
+ $dbman->create_table($table2);
+
+ // Get columns for the tables, so that relevant caches are populated with their data.
+ $DB->get_columns('test_table0');
+ $DB->get_columns('test_table1');
+ $DB->get_columns('test_table2');
+
+ $dbman->drop_table($table0);
+
+ $rc = new ReflectionClass('moodle_database');
+ $rcm = $rc->getMethod('get_temp_tables_cache');
+ $rcm->setAccessible(true);
+ $metacachetemp = $rcm->invokeArgs($DB, []);
+
+ // Data of test_table0 should be removed from the cache.
+ $this->assertEquals(false, $metacachetemp->has('test_table0'));
+
+ // Data of test_table1 should be intact.
+ $this->assertEquals(true, $metacachetemp->has('test_table1'));
+
+ $rc = new ReflectionClass('moodle_database');
+ $rcm = $rc->getMethod('get_metacache');
+ $rcm->setAccessible(true);
+ $metacache = $rcm->invokeArgs($DB, []);
+
+ // Data of test_table2 should be intact.
+ $this->assertEquals(true, $metacache->has('test_table2'));
+
+ // Delete the leftover temp table.
+ $dbman->drop_table($table1);
+ }
+
public function test_reset_sequence() {
$DB = $this->tdb;
$dbman = $DB->get_manager();
/**
* Returns detailed information about columns in table. This information is cached internally.
+ *
* @param string $table The table's name.
* @param bool $usecache Flag to use internal cacheing. The default is true.
* @return database_column_info[] of database_column_info objects indexed with column names
*/
- public abstract function get_columns($table, $usecache=true);
+ public function get_columns($table, $usecache = true): array {
+ if (!$table) { // Table not specified, return empty array directly.
+ return [];
+ }
+
+ if ($usecache) {
+ if ($this->temptables->is_temptable($table)) {
+ if ($data = $this->get_temp_tables_cache()->get($table)) {
+ return $data;
+ }
+ } else {
+ if ($data = $this->get_metacache()->get($table)) {
+ return $data;
+ }
+ }
+ }
+
+ $structure = $this->fetch_columns($table);
+
+ if ($usecache) {
+ if ($this->temptables->is_temptable($table)) {
+ $this->get_temp_tables_cache()->set($table, $structure);
+ } else {
+ $this->get_metacache()->set($table, $structure);
+ }
+ }
+
+ return $structure;
+ }
+
+ /**
+ * Returns detailed information about columns in table. This information is cached internally.
+ *
+ * @param string $table The table's name.
+ * @return database_column_info[] of database_column_info objects indexed with column names
+ */
+ protected abstract function fetch_columns(string $table): array;
/**
* Normalise values based on varying RDBMS's dependencies (booleans, LOBs...)
}
/**
- * Returns detailed information about columns in table. This information is cached internally.
+ * Fetches detailed information about columns in table.
+ *
* @param string $table name
- * @param bool $usecache
* @return database_column_info[] array of database_column_info objects indexed with column names
*/
- public function get_columns($table, $usecache=true) {
- if ($usecache) {
- if ($this->temptables->is_temptable($table)) {
- if ($data = $this->get_temp_tables_cache()->get($table)) {
- return $data;
- }
- } else {
- if ($data = $this->get_metacache()->get($table)) {
- return $data;
- }
- }
- }
-
+ protected function fetch_columns(string $table): array {
$structure = array();
$sql = "SELECT column_name, data_type, character_maximum_length, numeric_precision,
$result->close();
}
- if ($usecache) {
- if ($this->temptables->is_temptable($table)) {
- $this->get_temp_tables_cache()->set($table, $structure);
- } else {
- $this->get_metacache()->set($table, $structure);
- }
- }
-
return $structure;
}
}
/**
- * Returns detailed information about columns in table. This information is cached internally.
+ * Fetches detailed information about columns in table.
+ *
* @param string $table name
- * @param bool $usecache
* @return array array of database_column_info objects indexed with column names
*/
- public function get_columns($table, $usecache=true) {
-
- if ($usecache) {
- if ($this->temptables->is_temptable($table)) {
- if ($data = $this->get_temp_tables_cache()->get($table)) {
- return $data;
- }
- } else {
- if ($data = $this->get_metacache()->get($table)) {
- return $data;
- }
- }
- }
-
- if (!$table) { // table not specified, return empty array directly
- return array();
- }
-
+ protected function fetch_columns(string $table): array {
$structure = array();
// We give precedence to CHAR_LENGTH for VARCHAR2 columns over WIDTH because the former is always
$structure[$info->name] = new database_column_info($info);
}
- if ($usecache) {
- if ($this->temptables->is_temptable($table)) {
- $this->get_temp_tables_cache()->set($table, $structure);
- } else {
- $this->get_metacache()->set($table, $structure);
- }
- }
-
return $structure;
}
}
/**
- * Returns detailed information about columns in table. This information is cached internally.
+ * Returns detailed information about columns in table.
+ *
* @param string $table name
- * @param bool $usecache
* @return database_column_info[] array of database_column_info objects indexed with column names
*/
- public function get_columns($table, $usecache=true) {
- if ($usecache) {
- if ($this->temptables->is_temptable($table)) {
- if ($data = $this->get_temp_tables_cache()->get($table)) {
- return $data;
- }
- } else {
- if ($data = $this->get_metacache()->get($table)) {
- return $data;
- }
- }
- }
-
+ protected function fetch_columns(string $table): array {
$structure = array();
$tablename = $this->prefix.$table;
- $sql = "SELECT a.attnum, a.attname AS field, t.typname AS type, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, d.adsrc
+ $sql = "SELECT a.attnum, a.attname AS field, t.typname AS type, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef,
+ CASE WHEN a.atthasdef THEN pg_catalog.pg_get_expr(d.adbin, d.adrelid) END AS adsrc
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace as ns ON ns.oid = c.relnamespace
JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid
pg_free_result($result);
- if ($usecache) {
- if ($this->temptables->is_temptable($table)) {
- $this->get_temp_tables_cache()->set($table, $structure);
- } else {
- $this->get_metacache()->set($table, $structure);
- }
- }
-
return $structure;
}
}
/**
- * Returns detailed information about columns in table. This information is cached internally.
+ * Returns detailed information about columns in table.
+ *
* @param string $table name
- * @param bool $usecache
* @return array array of database_column_info objects indexed with column names
*/
- public function get_columns($table, $usecache=true) {
-
- if ($usecache) {
- if ($this->temptables->is_temptable($table)) {
- if ($data = $this->get_temp_tables_cache()->get($table)) {
- return $data;
- }
- } else {
- if ($data = $this->get_metacache()->get($table)) {
- return $data;
- }
- }
- }
-
+ protected function fetch_columns(string $table): array {
$structure = array();
// get table's CREATE TABLE command (we'll need it for autoincrement fields)
$structure[$columninfo['name']] = new database_column_info($columninfo);
}
- if ($usecache) {
- if ($this->temptables->is_temptable($table)) {
- $this->get_temp_tables_cache()->set($table, $structure);
- } else {
- $this->get_metacache()->set($table, $structure);
- }
- }
-
return $structure;
}
return 'mssql';
}
- /**
+ /**
* Returns more specific database driver type
* Note: can be used before connect()
* @return string db type mysqli, pgsql, oci, mssql, sqlsrv
return 'sqlsrv';
}
- /**
+ /**
* Returns general database library name
* Note: can be used before connect()
* @return string db type pdo, native
}
/**
- * Returns detailed information about columns in table. This information is cached internally.
+ * Returns detailed information about columns in table.
+ *
* @param string $table name
- * @param bool $usecache
* @return array array of database_column_info objects indexed with column names
*/
- public function get_columns($table, $usecache = true) {
- if ($usecache) {
- if ($this->temptables->is_temptable($table)) {
- if ($data = $this->get_temp_tables_cache()->get($table)) {
- return $data;
- }
- } else {
- if ($data = $this->get_metacache()->get($table)) {
- return $data;
- }
- }
- }
-
+ protected function fetch_columns(string $table): array {
$structure = array();
if (!$this->temptables->is_temptable($table)) { // normal table, get metadata from own schema
}
$this->free_result($result);
- if ($usecache) {
- if ($this->temptables->is_temptable($table)) {
- $this->get_temp_tables_cache()->set($table, $structure);
- } else {
- $this->get_metacache()->set($table, $structure);
- }
- }
-
return $structure;
}
public function get_last_error() {}
public function get_tables($usecache=true) {}
public function get_indexes($table) {}
- public function get_columns($table, $usecache=true) {}
+ protected function fetch_columns(string $table): array {
+ return [];
+ }
protected function normalise_value($column, $value) {}
public function set_debug($state) {}
public function get_debug() {}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class MoodleQuickForm_duration extends MoodleQuickForm_group {
- /**
- * Control the fieldnames for form elements
- * optional => if true, show a checkbox beside the element to turn it on (or off)
- * @var array
- */
- protected $_options = array('optional' => false, 'defaultunit' => 60);
+ /**
+ * Control the fieldnames for form elements
+ * optional => if true, show a checkbox beside the element to turn it on (or off)
+ * @var array
+ */
+ protected $_options = array('optional' => false, 'defaultunit' => MINSECS);
- /** @var array associative array of time units (days, hours, minutes, seconds) */
- private $_units = null;
+ /** @var array associative array of time units (days, hours, minutes, seconds) */
+ private $_units = null;
/**
* constructor
* @param string $elementName Element's name
* @param mixed $elementLabel Label(s) for an element
* @param array $options Options to control the element's display. Recognised values are
- * 'optional' => true/false - whether to display an 'enabled' checkbox next to the element.
- * 'defaultunit' => 1|60|3600|86400|604800 - the default unit to display when the time is blank.
- * If not specified, minutes is used.
+ * 'optional' => true/false - whether to display an 'enabled' checkbox next to the element.
+ * 'defaultunit' => 1|MINSECS|HOURSECS|DAYSECS|WEEKSECS - the default unit to display when
+ * the time is blank. If not specified, minutes is used.
+ * 'units' => array containing some or all of 1, MINSECS, HOURSECS, DAYSECS and WEEKSECS
+ * which unit choices to offer.
* @param mixed $attributes Either a typical HTML attribute string or an associative array
*/
- public function __construct($elementName = null, $elementLabel = null, $options = array(), $attributes = null) {
+ public function __construct($elementName = null, $elementLabel = null,
+ $options = array(), $attributes = null) {
// TODO MDL-52313 Replace with the call to parent::__construct().
HTML_QuickForm_element::__construct($elementName, $elementLabel, $attributes);
$this->_persistantFreeze = true;
}
$this->_options['defaultunit'] = $options['defaultunit'];
}
+ if (isset($options['units'])) {
+ if (!is_array($options['units'])) {
+ throw new coding_exception(
+ 'When creating a duration form field, units option must be an array.');
+ }
+ // Validate and register requested units.
+ $availableunits = $this->get_units();
+ $displayunits = [];
+ foreach ($options['units'] as $requestedunit) {
+ if (!isset($availableunits[$requestedunit])) {
+ throw new coding_exception($requestedunit .
+ ' is not a recognised unit in MoodleQuickForm_duration.');
+ }
+ $displayunits[$requestedunit] = $availableunits[$requestedunit];
+ }
+ krsort($displayunits, SORT_NUMERIC);
+ $this->_options['units'] = $displayunits;
+ }
}
/**
*
* @deprecated since Moodle 3.1
*/
- public function MoodleQuickForm_duration($elementName = null, $elementLabel = null, $options = array(), $attributes = null) {
+ public function MoodleQuickForm_duration($elementName = null, $elementLabel = null,
+ $options = array(), $attributes = null) {
debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
self::__construct($elementName, $elementLabel, $options, $attributes);
}
public function get_units() {
if (is_null($this->_units)) {
$this->_units = array(
- 604800 => get_string('weeks'),
- 86400 => get_string('days'),
- 3600 => get_string('hours'),
- 60 => get_string('minutes'),
+ WEEKSECS => get_string('weeks'),
+ DAYSECS => get_string('days'),
+ HOURSECS => get_string('hours'),
+ MINSECS => get_string('minutes'),
1 => get_string('seconds'),
);
}
return $this->_units;
}
+ /**
+ * Get the units to be used for this field.
+ *
+ * The ones specified in the options passed to the constructor, or all by default.
+ *
+ * @return array number of seconds => lang string.
+ */
+ protected function get_units_used() {
+ if (!empty($this->_options['units'])) {
+ return $this->_options['units'];
+ } else {
+ return $this->get_units();
+ }
+ }
+
/**
* Converts seconds to the best possible time unit. for example
- * 1800 -> array(30, 60) = 30 minutes.
+ * 1800 -> [30, MINSECS] = 30 minutes.
*
* @param int $seconds an amout of time in seconds.
* @return array associative array ($number => $unit)
if ($seconds == 0) {
return array(0, $this->_options['defaultunit']);
}
- foreach ($this->get_units() as $unit => $notused) {
+ foreach ($this->get_units_used() as $unit => $notused) {
if (fmod($seconds, $unit) == 0) {
return array($seconds / $unit, $unit);
}
}
$this->_elements = array();
// E_STRICT creating elements without forms is nasty because it internally uses $this
- $number = $this->createFormElement('text', 'number', get_string('time', 'form'), $attributes, true);
+ $number = $this->createFormElement('text', 'number',
+ get_string('time', 'form'), $attributes, true);
$number->set_force_ltr(true);
$this->_elements[] = $number;
unset($attributes['size']);
- $this->_elements[] = $this->createFormElement('select', 'timeunit', get_string('timeunit', 'form'), $this->get_units(), $attributes, true);
+ $this->_elements[] = $this->createFormElement('select', 'timeunit',
+ get_string('timeunit', 'form'), $this->get_units_used(), $attributes, true);
// If optional we add a checkbox which the user can use to turn if on
if($this->_options['optional']) {
- $this->_elements[] = $this->createFormElement('checkbox', 'enabled', null, get_string('enable'), $this->getAttributes(), true);
+ $this->_elements[] = $this->createFormElement('checkbox', 'enabled', null,
+ get_string('enable'), $this->getAttributes(), true);
}
foreach ($this->_elements as $element){
if (method_exists($element, 'setHiddenLabel')){
*
* @param string $event Name of event
* @param mixed $arg event arguments
- * @param object $caller calling object
+ * @param MoodleQuickForm $caller calling object
* @return bool
*/
function onQuickFormEvent($event, $arg, &$caller) {
<div class="form-group row {{#error}}has-danger{{/error}} fitem {{#advanced}}advanced{{/advanced}} {{{element.extraclasses}}}">
<div class="col-md-3">
+ <span class="float-sm-right text-nowrap">
+ {{#required}}<abbr class="initialism text-danger" title="{{#str}}required{{/str}}">{{#pix}}req, core, {{#str}}required{{/str}}{{/pix}}</abbr>{{/required}}
+ {{#advanced}}<abbr class="initialism text-info" title="{{#str}}advanced{{/str}}">!</abbr>{{/advanced}}
+ {{{helpbutton}}}
+ </span>
{{#text}}
<label for="{{element.id}}">
{{{label}}}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_form_duration_testcase extends basic_testcase {
- /** @var MoodleQuickForm Keeps reference of dummy form object */
- private $mform;
- /** @var MoodleQuickForm_duration Keeps reference of MoodleQuickForm_duration object */
- private $element;
/**
- * Initalize test wide variable, it is called in start of the testcase
+ * Get a form that can be used for testing.
+ *
+ * @return MoodleQuickForm
*/
- protected function setUp() {
- parent::setUp();
-
- // Get form data.
+ protected function get_test_form() {
$form = new temp_form_duration();
- $this->mform = $form->getform();
- $this->element = $this->mform->addElement('duration', 'duration');
+ return $form->getform();
}
/**
- * Clears the data set in the setUp() method call.
- * @see duration_form_element_test::setUp()
+ * Get a form with a duration element that can be used for testing.
+ *
+ * @return array with two elements, a MoodleQuickForm and a MoodleQuickForm_duration.
*/
- protected function tearDown() {
- $this->element = null;
+ protected function get_test_form_and_element() {
+ $mform = $this->get_test_form();
+ $element = $mform->addElement('duration', 'duration');
+ return [$mform, $element];
}
/**
* Testcase for testing contructor.
+ *
* @expectedException coding_exception
- * @retrun void
*/
public function test_constructor() {
// Test trying to create with an invalid unit.
- $this->element = $this->mform->addElement('duration', 'testel', null, array('defaultunit' => 123, 'optional' => false));
+ $mform = $this->get_test_form();
+ $mform->addElement('duration', 'testel', null, ['defaultunit' => 123, 'optional' => false]);
+ }
+
+ /**
+ * Test contructor only some units.
+ */
+ public function test_constructor_limited_units() {
+ $mform = $this->get_test_form();
+ $mform->addElement('duration', 'testel', null, ['units' => [MINSECS, 1], 'optional' => false]);
+ $html = $mform->toHtml();
+ $html = preg_replace('~ +>~', '>', $html); // Clean HTML to avoid spurious errors.
+ $this->assertContains('<option value="60" selected>minutes</option>', $html);
+ $this->assertContains('<option value="1">seconds</option>', $html);
+ $this->assertNotContains('value="3600"', $html);
}
/**
* Testcase for testing units (seconds, minutes, hours and days)
*/
public function test_get_units() {
- $units = $this->element->get_units();
- ksort($units);
- $this->assertEquals($units, array(1 => get_string('seconds'), 60 => get_string('minutes'),
- 3600 => get_string('hours'), 86400 => get_string('days'), 604800 => get_string('weeks')));
+ [$mform, $element] = $this->get_test_form_and_element();
+ $units = $element->get_units();
+ $this->assertEquals($units, [1 => get_string('seconds'), 60 => get_string('minutes'),
+ 3600 => get_string('hours'), 86400 => get_string('days'), 604800 => get_string('weeks')]);
}
/**
* Testcase for testing conversion of seconds to the best possible unit
*/
public function test_seconds_to_unit() {
- $this->assertEquals(array(0, 60), $this->element->seconds_to_unit(0)); // Zero minutes, for a nice default unit.
- $this->assertEquals(array(1, 1), $this->element->seconds_to_unit(1));
- $this->assertEquals(array(3601, 1), $this->element->seconds_to_unit(3601));
- $this->assertEquals(array(1, 60), $this->element->seconds_to_unit(60));
- $this->assertEquals(array(3, 60), $this->element->seconds_to_unit(180));
- $this->assertEquals(array(1, 3600), $this->element->seconds_to_unit(3600));
- $this->assertEquals(array(2, 3600), $this->element->seconds_to_unit(7200));
- $this->assertEquals(array(1, 86400), $this->element->seconds_to_unit(86400));
- $this->assertEquals(array(25, 3600), $this->element->seconds_to_unit(90000));
-
- $this->element = $this->mform->addElement('duration', 'testel', null, array('defaultunit' => 86400, 'optional' => false));
- $this->assertEquals(array(0, 86400), $this->element->seconds_to_unit(0)); // Zero minutes, for a nice default unit.
+ [$mform, $element] = $this->get_test_form_and_element();
+ $this->assertEquals([0, MINSECS], $element->seconds_to_unit(0)); // Zero minutes, for a nice default unit.
+ $this->assertEquals([1, 1], $element->seconds_to_unit(1));
+ $this->assertEquals([3601, 1], $element->seconds_to_unit(3601));
+ $this->assertEquals([1, MINSECS], $element->seconds_to_unit(60));
+ $this->assertEquals([3, MINSECS], $element->seconds_to_unit(180));
+ $this->assertEquals([1, HOURSECS], $element->seconds_to_unit(3600));
+ $this->assertEquals([2, HOURSECS], $element->seconds_to_unit(7200));
+ $this->assertEquals([1, DAYSECS], $element->seconds_to_unit(86400));
+ $this->assertEquals([25, HOURSECS], $element->seconds_to_unit(90000));
+
+ $element = $mform->addElement('duration', 'testel', null,
+ ['defaultunit' => DAYSECS, 'optional' => false]);
+ $this->assertEquals([0, DAYSECS], $element->seconds_to_unit(0)); // Zero minutes, for a nice default unit.
}
/**
* Testcase to check generated timestamp
*/
public function test_exportValue() {
- /** @var MoodleQuickForm_duration $el */
- $el = $this->mform->addElement('duration', 'testel');
- $values = array('testel' => array('number' => 10, 'timeunit' => 1));
- $this->assertEquals(array('testel' => 10), $el->exportValue($values, true));
+ $mform = $this->get_test_form();
+ $el = $mform->addElement('duration', 'testel');
+ $values = ['testel' => ['number' => 10, 'timeunit' => 1]];
+ $this->assertEquals(['testel' => 10], $el->exportValue($values, true));
$this->assertEquals(10, $el->exportValue($values));
- $values = array('testel' => array('number' => 3, 'timeunit' => 60));
- $this->assertEquals(array('testel' => 180), $el->exportValue($values, true));
+ $values = ['testel' => ['number' => 3, 'timeunit' => MINSECS]];
+ $this->assertEquals(['testel' => 180], $el->exportValue($values, true));
$this->assertEquals(180, $el->exportValue($values));
- $values = array('testel' => array('number' => 1.5, 'timeunit' => 60));
- $this->assertEquals(array('testel' => 90), $el->exportValue($values, true));
+ $values = ['testel' => ['number' => 1.5, 'timeunit' => MINSECS]];
+ $this->assertEquals(['testel' => 90], $el->exportValue($values, true));
$this->assertEquals(90, $el->exportValue($values));
- $values = array('testel' => array('number' => 2, 'timeunit' => 3600));
- $this->assertEquals(array('testel' => 7200), $el->exportValue($values, true));
+ $values = ['testel' => ['number' => 2, 'timeunit' => HOURSECS]];
+ $this->assertEquals(['testel' => 7200], $el->exportValue($values, true));
$this->assertEquals(7200, $el->exportValue($values));
- $values = array('testel' => array('number' => 1, 'timeunit' => 86400));
- $this->assertEquals(array('testel' => 86400), $el->exportValue($values, true));
+ $values = ['testel' => ['number' => 1, 'timeunit' => DAYSECS]];
+ $this->assertEquals(['testel' => 86400], $el->exportValue($values, true));
$this->assertEquals(86400, $el->exportValue($values));
- $values = array('testel' => array('number' => 0, 'timeunit' => 3600));
- $this->assertEquals(array('testel' => 0), $el->exportValue($values, true));
+ $values = ['testel' => ['number' => 0, 'timeunit' => HOURSECS]];
+ $this->assertEquals(['testel' => 0], $el->exportValue($values, true));
$this->assertEquals(0, $el->exportValue($values));
- $el = $this->mform->addElement('duration', 'testel', null, array('optional' => true));
- $values = array('testel' => array('number' => 10, 'timeunit' => 1));
- $this->assertEquals(array('testel' => 0), $el->exportValue($values, true));
+ $el = $mform->addElement('duration', 'testel', null, ['optional' => true]);
+ $values = ['testel' => ['number' => 10, 'timeunit' => 1]];
+ $this->assertEquals(['testel' => 0], $el->exportValue($values, true));
$this->assertEquals(0, $el->exportValue($values));
- $values = array('testel' => array('number' => 20, 'timeunit' => 1, 'enabled' => 1));
- $this->assertEquals(array('testel' => 20), $el->exportValue($values, true));
+ $values = ['testel' => ['number' => 20, 'timeunit' => 1, 'enabled' => 1]];
+ $this->assertEquals(['testel' => 20], $el->exportValue($values, true));
$this->assertEquals(20, $el->exportValue($values));
// Optional element.
- $el2 = $this->mform->addElement('duration', 'testel', '', ['optional' => true]);
- $values = array('testel' => array('number' => 10, 'timeunit' => 1, 'enabled' => 1));
- $this->assertEquals(array('testel' => 10), $el2->exportValue($values, true));
+ $el2 = $mform->addElement('duration', 'testel', '', ['optional' => true]);
+ $values = ['testel' => ['number' => 10, 'timeunit' => 1, 'enabled' => 1]];
+ $this->assertEquals(['testel' => 10], $el2->exportValue($values, true));
$this->assertEquals(10, $el2->exportValue($values));
- $values = array('testel' => array('number' => 10, 'timeunit' => 1, 'enabled' => 0));
- $this->assertEquals(array('testel' => 0), $el2->exportValue($values, true));
+ $values = ['testel' => ['number' => 10, 'timeunit' => 1, 'enabled' => 0]];
+ $this->assertEquals(['testel' => 0], $el2->exportValue($values, true));
$this->assertEquals(null, $el2->exportValue($values));
}
}
public function definition() {
// No definition required.
}
+
/**
* Returns form reference
* @return MoodleQuickForm
// This might be slow but it is really needed - modules might do some extra cleanup!
role_unassign_all(array('userid' => $user->id));
+ // Notify the competency subsystem.
+ \core_competency\api::hook_user_deleted($user->id);
+
// Now do a brute force cleanup.
// Delete all user events and subscription events.
if (class_exists('\core\update\checker')) {
\core\update\checker::reset_caches(true);
}
+ if (class_exists('\core_course\customfield\course_handler')) {
+ \core_course\customfield\course_handler::reset_caches();
+ }
// Clear static cache within restore.
if (class_exists('restore_section_structure_step')) {
{{!
@template core/form_autocomplete_selection
- Moodle template for the currently selected items in an autocomplate form element.
+ Moodle template for the wrapper of currently selected items in an autocomplate form element.
Classes required for JS:
* none
Context variables required for this template:
* multiple True if this field allows multiple selections
* selectionId The dom id of the current selection list.
- * items List of items with label and value fields.
- * noSelectionString String to use when no items are selected
+ * items List of items with label and value fields (used by the partial).
+ * noSelectionString String to use when no items are selected (used by the partial).
Example context (json):
{ "multiple": true, "selectionId": 1, "items": [
}}
<div class="form-autocomplete-selection w-100 {{#multiple}}form-autocomplete-multiple{{/multiple}}" id="{{selectionId}}" role="list" aria-atomic="true" {{#multiple}}tabindex="0" aria-multiselectable="true"{{/multiple}}>
<span class="accesshide">{{#str}}selecteditems, form{{/str}}</span>
- {{#items}}
- <span role="listitem" data-value="{{value}}" aria-selected="true" class="badge badge-info mb-3 mr-1" style="font-size: 100%">
- <span aria-hidden="true">× </span>{{{label}}}
- </span>
- {{/items}}
- {{^items}}
- <span class="mb-3 mr-1">{{noSelectionString}}</span>
- {{/items}}
+ {{> core/form_autocomplete_selection_items }}
</div>
--- /dev/null
+{{!
+ This file is part of Moodle - http://moodle.org/
+
+ Moodle is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Moodle is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+}}
+{{!
+ @template core/form_autocomplete_selection_items
+
+ Moodle template for the currently selected items in an autocomplate form element.
+
+ Classes required for JS:
+ * none
+
+ Data attributes required for JS:
+ * data-value
+
+ Context variables required for this template:
+ * items List of items with label and value fields.
+ * - value Value of the selected item.
+ * - label HTML representing the value.
+ * noSelectionString String to use when no items are selected
+
+ Example context (json):
+ { "items": [
+ { "label": "Item label with <strong>tags</strong>", "value": "5" },
+ { "label": "Another item label with <strong>tags</strong>", "value": "4" }
+ ], "noSelectionString": "No selection" }
+}}
+{{#items}}
+ <span role="listitem" data-value="{{value}}" aria-selected="true" class="badge badge-info mb-3 mr-1" style="font-size: 100%">
+ <span aria-hidden="true">× </span>{{{label}}}
+ </span>
+{{/items}}
+{{^items}}
+ <span class="mb-3 mr-1">{{noSelectionString}}</span>
+{{/items}}
-<div class="toast-wrapper mx-auto py-3 fixed-top" role="status" aria-live="polite"></div>
+<div class="toast-wrapper mx-auto py-0 fixed-top" role="status" aria-live="polite"></div>
* Test filters.
*/
class core_filterlib_testcase extends advanced_testcase {
- private $syscontext;
- private $childcontext;
- private $childcontext2;
- private $catcontext;
- private $coursecontext;
- private $course;
- private $activity1context;
- private $activity2context;
-
- protected function setUp() {
- global $DB;
- parent::setUp();
-
- $this->resetAfterTest();
- $DB->delete_records('filter_active', array());
- $DB->delete_records('filter_config', array());
- }
private function assert_only_one_filter_globally($filter, $state) {
global $DB;
}
public function test_set_filter_globally_on() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Setup fixture.
// Exercise SUT.
filter_set_global_state('name', TEXTFILTER_ON);
}
public function test_set_filter_globally_off() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Setup fixture.
// Exercise SUT.
filter_set_global_state('name', TEXTFILTER_OFF);
}
public function test_set_filter_globally_disabled() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Setup fixture.
// Exercise SUT.
filter_set_global_state('name', TEXTFILTER_DISABLED);
* @expectedException coding_exception
*/
public function test_global_config_exception_on_invalid_state() {
+ $this->resetAfterTest();
filter_set_global_state('name', 0);
}
public function test_auto_sort_order() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Setup fixture.
// Exercise SUT.
filter_set_global_state('one', TEXTFILTER_DISABLED);
}
public function test_auto_sort_order_enabled() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Setup fixture.
// Exercise SUT.
filter_set_global_state('one', TEXTFILTER_ON);
}
public function test_update_existing_dont_duplicate() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Setup fixture.
// Exercise SUT.
filter_set_global_state('name', TEXTFILTER_ON);
}
public function test_update_reorder_down() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Setup fixture.
filter_set_global_state('one', TEXTFILTER_ON);
filter_set_global_state('two', TEXTFILTER_ON);
}
public function test_update_reorder_up() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Setup fixture.
filter_set_global_state('one', TEXTFILTER_ON);
filter_set_global_state('two', TEXTFILTER_ON);
}
public function test_auto_sort_order_change_to_enabled() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Setup fixture.
filter_set_global_state('one', TEXTFILTER_ON);
filter_set_global_state('two', TEXTFILTER_DISABLED);
}
public function test_auto_sort_order_change_to_disabled() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Setup fixture.
filter_set_global_state('one', TEXTFILTER_ON);
filter_set_global_state('two', TEXTFILTER_ON);
}
public function test_filter_get_global_states() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Setup fixture.
filter_set_global_state('one', TEXTFILTER_ON);
filter_set_global_state('two', TEXTFILTER_OFF);
}
public function test_local_on() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Exercise SUT.
filter_set_local_state('name', 123, TEXTFILTER_ON);
// Validate.
}
public function test_local_off() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Exercise SUT.
filter_set_local_state('name', 123, TEXTFILTER_OFF);
// Validate.
}
public function test_local_inherit() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Exercise SUT.
filter_set_local_state('name', 123, TEXTFILTER_INHERIT);
// Validate.
* @expectedException coding_exception
*/
public function test_local_invalid_state_throws_exception() {
+ $this->resetAfterTest();
// Exercise SUT.
filter_set_local_state('name', 123, -9999);
}
* @expectedException coding_exception
*/
public function test_throws_exception_when_setting_global() {
+ $this->resetAfterTest();
// Exercise SUT.
filter_set_local_state('name', context_system::instance()->id, TEXTFILTER_INHERIT);
}
public function test_local_inherit_deletes_existing() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Setup fixture.
filter_set_local_state('name', 123, TEXTFILTER_INHERIT);
// Exercise SUT.
}
public function test_set_new_config() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Exercise SUT.
filter_set_local_config('name', 123, 'settingname', 'An arbitrary value');
// Validate.
}
public function test_update_existing_config() {
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
// Setup fixture.
filter_set_local_config('name', 123, 'settingname', 'An arbitrary value');
// Exercise SUT.
}
public function test_filter_get_local_config() {
+ $this->resetAfterTest();
// Setup fixture.
filter_set_local_config('name', 123, 'setting1', 'An arbitrary value');
filter_set_local_config('name', 123, 'setting2', 'Another arbitrary value');
protected function setup_available_in_context_tests() {
$course = $this->getDataGenerator()->create_course(array('category'=>1));
- $this->childcontext = context_coursecat::instance(1);
- $this->childcontext2 = context_course::instance($course->id);
- $this->syscontext = context_system::instance();
+ $childcontext = context_coursecat::instance(1);
+ $childcontext2 = context_course::instance($course->id);
+ $syscontext = context_system::instance();
+
+ return [
+ 'syscontext' => $syscontext,
+ 'childcontext' => $childcontext,
+ 'childcontext2' => $childcontext2
+ ];
+ }
+
+ protected function remove_all_filters_from_config() {
+ global $DB;
+ $DB->delete_records('filter_active', array());
+ $DB->delete_records('filter_config', array());
}
private function assert_filter_list($expectedfilters, $filters) {
- $this->setup_available_in_context_tests();
$this->assertEquals($expectedfilters, array_keys($filters), '', 0, 10, true);
}
public function test_globally_on_is_returned() {
- $this->setup_available_in_context_tests();
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
+ [
+ 'syscontext' => $syscontext
+ ] = $this->setup_available_in_context_tests();
// Setup fixture.
filter_set_global_state('name', TEXTFILTER_ON);
// Exercise SUT.
- $filters = filter_get_active_in_context($this->syscontext);
+ $filters = filter_get_active_in_context($syscontext);
// Validate.
$this->assert_filter_list(array('name'), $filters);
// Check no config returned correctly.
}
public function test_globally_off_not_returned() {
- $this->setup_available_in_context_tests();
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
+ [
+ 'childcontext2' => $childcontext2
+ ] = $this->setup_available_in_context_tests();
// Setup fixture.
filter_set_global_state('name', TEXTFILTER_OFF);
// Exercise SUT.
- $filters = filter_get_active_in_context($this->childcontext2);
+ $filters = filter_get_active_in_context($childcontext2);
// Validate.
$this->assert_filter_list(array(), $filters);
}
public function test_globally_off_overridden() {
- $this->setup_available_in_context_tests();
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
+ [
+ 'childcontext' => $childcontext,
+ 'childcontext2' => $childcontext2
+ ] = $this->setup_available_in_context_tests();
// Setup fixture.
filter_set_global_state('name', TEXTFILTER_OFF);
- filter_set_local_state('name', $this->childcontext->id, TEXTFILTER_ON);
+ filter_set_local_state('name', $childcontext->id, TEXTFILTER_ON);
// Exercise SUT.
- $filters = filter_get_active_in_context($this->childcontext2);
+ $filters = filter_get_active_in_context($childcontext2);
// Validate.
$this->assert_filter_list(array('name'), $filters);
}
public function test_globally_on_overridden() {
- $this->setup_available_in_context_tests();
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
+ [
+ 'childcontext' => $childcontext,
+ 'childcontext2' => $childcontext2
+ ] = $this->setup_available_in_context_tests();
// Setup fixture.
filter_set_global_state('name', TEXTFILTER_ON);
- filter_set_local_state('name', $this->childcontext->id, TEXTFILTER_OFF);
+ filter_set_local_state('name', $childcontext->id, TEXTFILTER_OFF);
// Exercise SUT.
- $filters = filter_get_active_in_context($this->childcontext2);
+ $filters = filter_get_active_in_context($childcontext2);
// Validate.
$this->assert_filter_list(array(), $filters);
}
public function test_globally_disabled_not_overridden() {
- $this->setup_available_in_context_tests();
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
+ [
+ 'syscontext' => $syscontext,
+ 'childcontext' => $childcontext
+ ] = $this->setup_available_in_context_tests();
// Setup fixture.
filter_set_global_state('name', TEXTFILTER_DISABLED);
- filter_set_local_state('name', $this->childcontext->id, TEXTFILTER_ON);
+ filter_set_local_state('name', $childcontext->id, TEXTFILTER_ON);
// Exercise SUT.
- $filters = filter_get_active_in_context($this->syscontext);
+ $filters = filter_get_active_in_context($syscontext);
// Validate.
$this->assert_filter_list(array(), $filters);
}
public function test_single_config_returned() {
- $this->setup_available_in_context_tests();
+ $this->resetAfterTest();
+ [
+ 'childcontext' => $childcontext
+ ] = $this->setup_available_in_context_tests();
// Setup fixture.
filter_set_global_state('name', TEXTFILTER_ON);
- filter_set_local_config('name', $this->childcontext->id, 'settingname', 'A value');
+ filter_set_local_config('name', $childcontext->id, 'settingname', 'A value');
// Exercise SUT.
- $filters = filter_get_active_in_context($this->childcontext);
+ $filters = filter_get_active_in_context($childcontext);
// Validate.
$this->assertEquals(array('settingname' => 'A value'), $filters['name']);
}
public function test_multi_config_returned() {
- $this->setup_available_in_context_tests();
+ $this->resetAfterTest();
+ [
+ 'childcontext' => $childcontext
+ ] = $this->setup_available_in_context_tests();
// Setup fixture.
filter_set_global_state('name', TEXTFILTER_ON);
- filter_set_local_config('name', $this->childcontext->id, 'settingname', 'A value');
- filter_set_local_config('name', $this->childcontext->id, 'anothersettingname', 'Another value');
+ filter_set_local_config('name', $childcontext->id, 'settingname', 'A value');
+ filter_set_local_config('name', $childcontext->id, 'anothersettingname', 'Another value');
// Exercise SUT.
- $filters = filter_get_active_in_context($this->childcontext);
+ $filters = filter_get_active_in_context($childcontext);
// Validate.
$this->assertEquals(array('settingname' => 'A value', 'anothersettingname' => 'Another value'), $filters['name']);
}
public function test_config_from_other_context_not_returned() {
- $this->setup_available_in_context_tests();
+ $this->resetAfterTest();
+ [
+ 'childcontext' => $childcontext,
+ 'childcontext2' => $childcontext2
+ ] = $this->setup_available_in_context_tests();
// Setup fixture.
filter_set_global_state('name', TEXTFILTER_ON);
- filter_set_local_config('name', $this->childcontext->id, 'settingname', 'A value');
- filter_set_local_config('name', $this->childcontext2->id, 'anothersettingname', 'Another value');
+ filter_set_local_config('name', $childcontext->id, 'settingname', 'A value');
+ filter_set_local_config('name', $childcontext2->id, 'anothersettingname', 'Another value');
// Exercise SUT.
- $filters = filter_get_active_in_context($this->childcontext2);
+ $filters = filter_get_active_in_context($childcontext2);
// Validate.
$this->assertEquals(array('anothersettingname' => 'Another value'), $filters['name']);
}
public function test_config_from_other_filter_not_returned() {
- $this->setup_available_in_context_tests();
+ $this->resetAfterTest();
+ [
+ 'childcontext' => $childcontext
+ ] = $this->setup_available_in_context_tests();
// Setup fixture.
filter_set_global_state('name', TEXTFILTER_ON);
- filter_set_local_config('name', $this->childcontext->id, 'settingname', 'A value');
- filter_set_local_config('other', $this->childcontext->id, 'anothersettingname', 'Another value');
+ filter_set_local_config('name', $childcontext->id, 'settingname', 'A value');
+ filter_set_local_config('other', $childcontext->id, 'anothersettingname', 'Another value');
// Exercise SUT.
- $filters = filter_get_active_in_context($this->childcontext);
+ $filters = filter_get_active_in_context($childcontext);
// Validate.
$this->assertEquals(array('settingname' => 'A value'), $filters['name']);
}
protected function assert_one_available_filter($filter, $localstate, $inheritedstate, $filters) {
- $this->setup_available_in_context_tests();
$this->assertEquals(1, count($filters), 'More than one record returned %s.');
$rec = $filters[$filter];
unset($rec->id);
}
public function test_available_in_context_localoverride() {
- $this->setup_available_in_context_tests();
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
+ [
+ 'childcontext' => $childcontext
+ ] = $this->setup_available_in_context_tests();
// Setup fixture.
filter_set_global_state('name', TEXTFILTER_ON);
- filter_set_local_state('name', $this->childcontext->id, TEXTFILTER_OFF);
+ filter_set_local_state('name', $childcontext->id, TEXTFILTER_OFF);
// Exercise SUT.
- $filters = filter_get_available_in_context($this->childcontext);
+ $filters = filter_get_available_in_context($childcontext);
// Validate.
$this->assert_one_available_filter('name', TEXTFILTER_OFF, TEXTFILTER_ON, $filters);
}
public function test_available_in_context_nolocaloverride() {
- $this->setup_available_in_context_tests();
+ $this->resetAfterTest();
+ $this->remove_all_filters_from_config(); // Remove all filters.
+ [
+ 'childcontext' => $childcontext,
+ 'childcontext2' => $childcontext2
+ ] = $this->setup_available_in_context_tests();
// Setup fixture.
filter_set_global_state('name', TEXTFILTER_ON);
- filter_set_local_state('name', $this->childcontext->id, TEXTFILTER_OFF);
+ filter_set_local_state('name', $childcontext->id, TEXTFILTER_OFF);
// Exercise SUT.
- $filters = filter_get_available_in_context($this->childcontext2);
+ $filters = filter_get_available_in_context($childcontext2);
// Validate.
$this->assert_one_available_filter('name', TEXTFILTER_INHERIT, TEXTFILTER_OFF, $filters);
}
public function test_available_in_context_disabled_not_returned() {
- $this->setup_available_in_context_tests();
+ $this->resetAfterTest();
+ &