From 33ebbddde22febf711fc34adce82ec99b2ffb217 Mon Sep 17 00:00:00 2001 From: Mathew May Date: Fri, 13 Jan 2023 11:58:09 +0800 Subject: [PATCH] MDL-52805 core: Remove legacy log plugin and more calls --- admin/renderer.php | 16 - admin/tool/log/classes/log/manager.php | 25 - admin/tool/log/db/install.php | 11 - .../legacy/classes/event/legacy_logged.php | 53 -- .../log/store/legacy/classes/log/store.php | 424 ---------------- .../store/legacy/classes/privacy/provider.php | 255 ---------- .../legacy/classes/task/cleanup_task.php | 69 --- admin/tool/log/store/legacy/db/tasks.php | 37 -- .../store/legacy/lang/en/logstore_legacy.php | 37 -- admin/tool/log/store/legacy/settings.php | 52 -- .../log/store/legacy/tests/fixtures/event.php | 47 -- .../log/store/legacy/tests/fixtures/store.php | 43 -- .../legacy/tests/privacy/provider_test.php | 472 ------------------ .../log/store/legacy/tests/store_test.php | 264 ---------- admin/tool/log/store/legacy/version.php | 29 -- admin/tool/log/tests/manager_test.php | 7 +- lib/classes/plugin_manager.php | 3 +- .../report/summary/classes/summary_table.php | 12 +- report/eventlist/classes/list_generator.php | 3 +- report/log/classes/table_log.php | 54 +- report/log/index.php | 5 - report/log/locallib.php | 38 +- report/log/tests/lib_test.php | 1 - report/loglive/classes/table_log.php | 8 +- report/loglive/tests/lib_test.php | 2 - report/outline/lib.php | 2 +- report/outline/locallib.php | 5 - report/outline/tests/behat/outline.feature | 18 - report/outline/tests/behat/user.feature | 30 -- report/outline/tests/lib_test.php | 1 - report/participation/lib.php | 2 +- report/participation/locallib.php | 5 - .../tests/behat/filter_participation.feature | 19 - report/participation/tests/lib_test.php | 1 - report/stats/lib.php | 2 +- report/stats/tests/lib_test.php | 1 - 36 files changed, 39 insertions(+), 2014 deletions(-) delete mode 100644 admin/tool/log/store/legacy/classes/event/legacy_logged.php delete mode 100644 admin/tool/log/store/legacy/classes/log/store.php delete mode 100644 admin/tool/log/store/legacy/classes/privacy/provider.php delete mode 100644 admin/tool/log/store/legacy/classes/task/cleanup_task.php delete mode 100644 admin/tool/log/store/legacy/db/tasks.php delete mode 100644 admin/tool/log/store/legacy/lang/en/logstore_legacy.php delete mode 100644 admin/tool/log/store/legacy/settings.php delete mode 100644 admin/tool/log/store/legacy/tests/fixtures/event.php delete mode 100644 admin/tool/log/store/legacy/tests/fixtures/store.php delete mode 100644 admin/tool/log/store/legacy/tests/privacy/provider_test.php delete mode 100644 admin/tool/log/store/legacy/tests/store_test.php delete mode 100644 admin/tool/log/store/legacy/version.php diff --git a/admin/renderer.php b/admin/renderer.php index 89a35af70de..80cf7d408b4 100644 --- a/admin/renderer.php +++ b/admin/renderer.php @@ -296,7 +296,6 @@ class core_admin_renderer extends plugin_renderer_base { $output .= $this->header(); $output .= $this->output->heading(get_string('notifications', 'admin')); $output .= $this->maturity_info($maturity); - $output .= $this->legacy_log_store_writing_error(); $output .= empty($CFG->disableupdatenotifications) ? $this->available_updates($availableupdates, $availableupdatesfetch) : ''; $output .= $this->insecure_dataroot_warning($insecuredataroot); $output .= $this->development_libs_directories_warning($devlibdir); @@ -2192,21 +2191,6 @@ class core_admin_renderer extends plugin_renderer_base { return $output; } - /** - * Check to see if writing to the deprecated legacy log store is enabled. - * - * @return string An error message if writing to the legacy log store is enabled. - */ - protected function legacy_log_store_writing_error() { - $enabled = get_config('logstore_legacy', 'loglegacy'); - $plugins = explode(',', get_config('tool_log', 'enabled_stores')); - $enabled = $enabled && in_array('logstore_legacy', $plugins); - - if ($enabled) { - return $this->warning(get_string('legacylogginginuse')); - } - } - /** * Display message about the benefits of registering on Moodle.org * diff --git a/admin/tool/log/classes/log/manager.php b/admin/tool/log/classes/log/manager.php index 2b1d49107fa..a65aefd8c3f 100644 --- a/admin/tool/log/classes/log/manager.php +++ b/admin/tool/log/classes/log/manager.php @@ -199,29 +199,4 @@ class manager implements \core\log\manager { $this->readers = null; $this->writers = null; } - - /** - * Legacy add_to_log() redirection. - * - * To be used only from deprecated add_to_log() function and event trigger() method. - * - * NOTE: this is hardcoded to legacy log store plugin, hopefully we can get rid of it soon. - * - * @param int $courseid The course id - * @param string $module The module name e.g. forum, journal, resource, course, user etc - * @param string $action 'view', 'update', 'add' or 'delete', possibly followed by another word to clarify - * @param string $url The file and parameters used to see the results of the action - * @param string $info Additional description information - * @param int $cm The course_module->id if there is one - * @param int|\stdClass $user If log regards $user other than $USER - * @param string $ip Override the IP, should only be used for restore. - * @param int $time Override the log time, should only be used for restore. - */ - public function legacy_add_to_log($courseid, $module, $action, $url = '', $info = '', - $cm = 0, $user = 0, $ip = null, $time = null) { - $this->init(); - if (isset($this->stores['logstore_legacy'])) { - $this->stores['logstore_legacy']->legacy_add_to_log($courseid, $module, $action, $url, $info, $cm, $user, $ip, $time); - } - } } diff --git a/admin/tool/log/db/install.php b/admin/tool/log/db/install.php index 52d2d9de55d..0bfe4cacf0d 100644 --- a/admin/tool/log/db/install.php +++ b/admin/tool/log/db/install.php @@ -37,16 +37,5 @@ function xmldb_tool_log_install() { $enabled[] = 'logstore_standard'; } - // Enable legacy log reading, but only if there are existing data. - if (file_exists("$CFG->dirroot/$CFG->admin/tool/log/store/legacy")) { - unset_config('loglegacy', 'logstore_legacy'); - // Do not enabled legacy logging if somebody installed a new - // site and in less than one day upgraded to 2.7. - $params = array('yesterday' => time() - 60*60*24); - if ($DB->record_exists_select('log', "time < :yesterday", $params)) { - $enabled[] = 'logstore_legacy'; - } - } - set_config('enabled_stores', implode(',', $enabled), 'tool_log'); } diff --git a/admin/tool/log/store/legacy/classes/event/legacy_logged.php b/admin/tool/log/store/legacy/classes/event/legacy_logged.php deleted file mode 100644 index f37365f5100..00000000000 --- a/admin/tool/log/store/legacy/classes/event/legacy_logged.php +++ /dev/null @@ -1,53 +0,0 @@ -. - -namespace logstore_legacy\event; - -defined('MOODLE_INTERNAL') || die(); - -/** - * Legacy log emulation event class. - * - * @package core - * @since Moodle 2.7 - * @copyright 2013 Petr Skoda {@link http://skodak.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class legacy_logged extends \core\event\base { - - public function init() { - throw new \coding_exception('legacy events cannot be triggered'); - } - - public static function get_name() { - return get_string('eventlegacylogged', 'logstore_legacy'); - } - - public function get_description() { - return $this->other['module'] . ' ' . $this->other['action'] . ' ' . $this->other['info']; - } - - public function get_url() { - global $CFG; - require_once("$CFG->dirroot/course/lib.php"); - - $url = \make_log_url($this->other['module'], $this->other['url']); - if (!$url) { - return null; - } - return new \moodle_url($url); - } -} diff --git a/admin/tool/log/store/legacy/classes/log/store.php b/admin/tool/log/store/legacy/classes/log/store.php deleted file mode 100644 index 42ffcfbf763..00000000000 --- a/admin/tool/log/store/legacy/classes/log/store.php +++ /dev/null @@ -1,424 +0,0 @@ -. - -/** - * Legacy log reader. - * @deprecated since Moodle 3.6 MDL-52953 - Please use supported log stores such as "standard" or "external" instead. - * @todo MDL-52805 This is to be removed in Moodle 3.10 - * - * @package logstore_legacy - * @copyright 2013 Petr Skoda {@link http://skodak.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace logstore_legacy\log; - -defined('MOODLE_INTERNAL') || die(); - -class store implements \tool_log\log\store, \core\log\sql_reader { - use \tool_log\helper\store, - \tool_log\helper\reader; - - /** - * @deprecated since Moodle 3.6 MDL-52953 - Please use supported log stores such as "standard" or "external" instead. - * @todo MDL-52805 This is to be removed in Moodle 3.10 - * - * @param \tool_log\log\manager $manager - */ - public function __construct(\tool_log\log\manager $manager) { - $this->helper_setup($manager); - } - - /** @var array list of db fields which needs to be replaced for legacy log query */ - protected static $standardtolegacyfields = array( - 'timecreated' => 'time', - 'courseid' => 'course', - 'contextinstanceid' => 'cmid', - 'origin' => 'ip', - 'anonymous' => 0, - ); - - /** @var string Regex to replace the crud params */ - const CRUD_REGEX = "/(crud).*?(<>|=|!=).*?'(.*?)'/s"; - - /** - * This method contains mapping required for Moodle core to make legacy store compatible with other sql_reader based - * queries. - * - * @param string $selectwhere Select statment - * @param array $params params for the sql - * @param string $sort sort fields - * - * @return array returns an array containing the sql predicate, an array of params and sorting parameter. - */ - protected static function replace_sql_legacy($selectwhere, array $params, $sort = '') { - // Following mapping is done to make can_delete_course() compatible with legacy store. - if ($selectwhere == "userid = :userid AND courseid = :courseid AND eventname = :eventname AND timecreated > :since" and - empty($sort)) { - $replace = "module = 'course' AND action = 'new' AND userid = :userid AND url = :url AND time > :since"; - $params += array('url' => "view.php?id={$params['courseid']}"); - return array($replace, $params, $sort); - } - - // Replace db field names to make it compatible with legacy log. - foreach (self::$standardtolegacyfields as $from => $to) { - $selectwhere = str_replace($from, $to, $selectwhere); - if (!empty($sort)) { - $sort = str_replace($from, $to, $sort); - } - if (isset($params[$from])) { - $params[$to] = $params[$from]; - unset($params[$from]); - } - } - - // Replace crud fields. - $selectwhere = preg_replace_callback("/(crud).*?(<>|=|!=).*?'(.*?)'/s", self::class .'::replace_crud', $selectwhere); - - return array($selectwhere, $params, $sort); - } - - /** - * @deprecated since Moodle 3.6 MDL-52953 - Please use supported log stores such as "standard" or "external" instead. - * @todo MDL-52805 This will be removed in Moodle 3.10 - * - * @param string $selectwhere - * @param array $params - * @param string $sort - * @param int $limitfrom - * @param int $limitnum - * @return array - */ - public function get_events_select($selectwhere, array $params, $sort, $limitfrom, $limitnum) { - global $DB; - - $sort = self::tweak_sort_by_id($sort); - - // Replace the query with hardcoded mappings required for core. - list($selectwhere, $params, $sort) = self::replace_sql_legacy($selectwhere, $params, $sort); - - $records = array(); - - try { - // A custom report + on the fly SQL rewriting = a possible exception. - $records = $DB->get_recordset_select('log', $selectwhere, $params, $sort, '*', $limitfrom, $limitnum); - } catch (\moodle_exception $ex) { - debugging("error converting legacy event data " . $ex->getMessage() . $ex->debuginfo, DEBUG_DEVELOPER); - return array(); - } - - $events = array(); - - foreach ($records as $data) { - $events[$data->id] = $this->get_log_event($data); - } - - $records->close(); - - return $events; - } - - /** - * Get whether events are present for the given select clause. - * @deprecated since Moodle 3.6 MDL-52953 - Please use supported log stores such as "standard" or "external" instead. - * - * @param string $selectwhere select conditions. - * @param array $params params. - * - * @return bool Whether events available for the given conditions - */ - public function get_events_select_exists(string $selectwhere, array $params): bool { - global $DB; - - // Replace the query with hardcoded mappings required for core. - list($selectwhere, $params) = self::replace_sql_legacy($selectwhere, $params); - - try { - return $DB->record_exists_select('log', $selectwhere, $params); - } catch (\moodle_exception $ex) { - debugging("error converting legacy event data " . $ex->getMessage() . $ex->debuginfo, DEBUG_DEVELOPER); - return false; - } - } - - /** - * Fetch records using given criteria returning a Traversable object. - * @deprecated since Moodle 3.6 MDL-52953 - Please use supported log stores such as "standard" or "external" instead. - * @todo MDL-52805 This will be removed in Moodle 3.10 - * - * Note that the traversable object contains a moodle_recordset, so - * remember that is important that you call close() once you finish - * using it. - * - * @param string $selectwhere - * @param array $params - * @param string $sort - * @param int $limitfrom - * @param int $limitnum - * @return \Traversable|\core\event\base[] - */ - public function get_events_select_iterator($selectwhere, array $params, $sort, $limitfrom, $limitnum) { - global $DB; - - $sort = self::tweak_sort_by_id($sort); - - // Replace the query with hardcoded mappings required for core. - list($selectwhere, $params, $sort) = self::replace_sql_legacy($selectwhere, $params, $sort); - - try { - $recordset = $DB->get_recordset_select('log', $selectwhere, $params, $sort, '*', $limitfrom, $limitnum); - } catch (\moodle_exception $ex) { - debugging("error converting legacy event data " . $ex->getMessage() . $ex->debuginfo, DEBUG_DEVELOPER); - return new \EmptyIterator; - } - - return new \core\dml\recordset_walk($recordset, array($this, 'get_log_event')); - } - - /** - * Returns an event from the log data. - * @deprecated since Moodle 3.6 MDL-52953 - Please use supported log stores such as "standard" or "external" instead. - * @todo MDL-52805 This will be removed in Moodle 3.10 - * - * @param stdClass $data Log data - * @return \core\event\base - */ - public function get_log_event($data) { - return \logstore_legacy\event\legacy_logged::restore_legacy($data); - } - - /** - * @deprecated since Moodle 3.6 MDL-52953 - Please use supported log stores such as "standard" or "external" instead. - * @todo MDL-52805 This will be removed in Moodle 3.10 - * - * @param string $selectwhere - * @param array $params - * @return int - */ - public function get_events_select_count($selectwhere, array $params) { - global $DB; - - // Replace the query with hardcoded mappings required for core. - list($selectwhere, $params) = self::replace_sql_legacy($selectwhere, $params); - - try { - return $DB->count_records_select('log', $selectwhere, $params); - } catch (\moodle_exception $ex) { - debugging("error converting legacy event data " . $ex->getMessage() . $ex->debuginfo, DEBUG_DEVELOPER); - return 0; - } - } - - /** - * Are the new events appearing in the reader? - * @deprecated since Moodle 3.6 MDL-52953 - Please use supported log stores such as "standard" or "external" instead. - * @todo MDL-52805 This will be removed in Moodle 3.10 - * - * @return bool true means new log events are being added, false means no new data will be added - */ - public function is_logging() { - return (bool)$this->get_config('loglegacy', true); - } - - /** - * @deprecated since Moodle 3.6 MDL-52953 - Please use supported log stores such as "standard" or "external" instead. - * @todo MDL-52805 This will be removed in Moodle 3.10 - */ - public function dispose() { - } - - /** - * Legacy add_to_log() code. - * @deprecated since Moodle 3.1 MDL-45104 - Please use supported log stores such as "standard" or "external" instead. - * @todo MDL-52805 This will be removed in Moodle 3.3 - * - * @param int $courseid The course id - * @param string $module The module name e.g. forum, journal, resource, course, user etc - * @param string $action 'view', 'update', 'add' or 'delete', possibly followed by another word to clarify. - * @param string $url The file and parameters used to see the results of the action - * @param string $info Additional description information - * @param int $cm The course_module->id if there is one - * @param int|\stdClass $user If log regards $user other than $USER - * @param string $ip Override the IP, should only be used for restore. - * @param int $time Override the log time, should only be used for restore. - */ - public function legacy_add_to_log($courseid, $module, $action, $url, $info, $cm, $user, $ip = null, $time = null) { - // Note that this function intentionally does not follow the normal Moodle DB access idioms. - // This is for a good reason: it is the most frequently used DB update function, - // so it has been optimised for speed. - global $DB, $CFG, $USER; - if (!$this->is_logging()) { - return; - } - - if ($cm === '' || is_null($cm)) { // Postgres won't translate empty string to its default. - $cm = 0; - } - - if ($user) { - $userid = $user; - } else { - if (\core\session\manager::is_loggedinas()) { // Don't log. - return; - } - $userid = empty($USER->id) ? '0' : $USER->id; - } - - if (isset($CFG->logguests) and !$CFG->logguests) { - if (!$userid or isguestuser($userid)) { - return; - } - } - - $remoteaddr = (is_null($ip)) ? getremoteaddr() : $ip; - - $timenow = (is_null($time)) ? time() : $time; - if (!empty($url)) { // Could break doing html_entity_decode on an empty var. - $url = html_entity_decode($url, ENT_QUOTES, 'UTF-8'); - } else { - $url = ''; - } - - // Restrict length of log lines to the space actually available in the - // database so that it doesn't cause a DB error. Log a warning so that - // developers can avoid doing things which are likely to cause this on a - // routine basis. - if (\core_text::strlen($action) > 40) { - $action = \core_text::substr($action, 0, 37) . '...'; - debugging('Warning: logged very long action', DEBUG_DEVELOPER); - } - - if (!empty($info) && \core_text::strlen($info) > 255) { - $info = \core_text::substr($info, 0, 252) . '...'; - debugging('Warning: logged very long info', DEBUG_DEVELOPER); - } - - // If the 100 field size is changed, also need to alter print_log in course/lib.php. - if (!empty($url) && \core_text::strlen($url) > 100) { - $url = \core_text::substr($url, 0, 97) . '...'; - debugging('Warning: logged very long URL', DEBUG_DEVELOPER); - } - - if (defined('MDL_PERFDB')) { - global $PERF; - $PERF->logwrites++; - }; - - $log = array('time' => $timenow, 'userid' => $userid, 'course' => $courseid, 'ip' => $remoteaddr, - 'module' => $module, 'cmid' => $cm, 'action' => $action, 'url' => $url, 'info' => $info); - - try { - $DB->insert_record_raw('log', $log, false); - } catch (\dml_exception $e) { - debugging('Error: Could not insert a new entry to the Moodle log. ' . $e->errorcode, DEBUG_ALL); - - // MDL-11893, alert $CFG->supportemail if insert into log failed. - if ($CFG->supportemail and empty($CFG->noemailever)) { - // Function email_to_user is not usable because email_to_user tries to write to the logs table, - // and this will get caught in an infinite loop, if disk is full. - $site = get_site(); - $subject = 'Insert into log failed at your moodle site ' . $site->fullname; - $message = "Insert into log table failed at " . date('l dS \of F Y h:i:s A') . - ".\n It is possible that your disk is full.\n\n"; - $message .= "The failed query parameters are:\n\n" . var_export($log, true); - - $lasttime = get_config('admin', 'lastloginserterrormail'); - if (empty($lasttime) || time() - $lasttime > 60 * 60 * 24) { // Limit to 1 email per day. - // Using email directly rather than messaging as they may not be able to log in to access a message. - mail($CFG->supportemail, $subject, $message); - set_config('lastloginserterrormail', time(), 'admin'); - } - } - } - } - - /** - * Generate a replace string for crud related sql conditions. This function is called as callback to preg_replace_callback() - * on the actual sql. - * - * @param array $match matched string for the passed pattern - * - * @return string The sql string to use instead of original - */ - protected static function replace_crud($match) { - $return = ''; - unset($match[0]); // The first entry is the whole string. - foreach ($match as $m) { - // We hard code LIKE here because we are not worried about case sensitivity and want this to be fast. - switch ($m) { - case 'crud' : - $replace = 'action'; - break; - case 'c' : - switch ($match[2]) { - case '=' : - $replace = " LIKE '%add%'"; - break; - case '!=' : - case '<>' : - $replace = " NOT LIKE '%add%'"; - break; - default: - $replace = ''; - } - break; - case 'r' : - switch ($match[2]) { - case '=' : - $replace = " LIKE '%view%' OR action LIKE '%report%'"; - break; - case '!=' : - case '<>' : - $replace = " NOT LIKE '%view%' AND action NOT LIKE '%report%'"; - break; - default: - $replace = ''; - } - break; - case 'u' : - switch ($match[2]) { - case '=' : - $replace = " LIKE '%update%'"; - break; - case '!=' : - case '<>' : - $replace = " NOT LIKE '%update%'"; - break; - default: - $replace = ''; - } - break; - case 'd' : - switch ($match[2]) { - case '=' : - $replace = " LIKE '%delete%'"; - break; - case '!=' : - case '<>' : - $replace = " NOT LIKE '%delete%'"; - break; - default: - $replace = ''; - } - break; - default : - $replace = ''; - } - $return .= $replace; - } - return $return; - } -} diff --git a/admin/tool/log/store/legacy/classes/privacy/provider.php b/admin/tool/log/store/legacy/classes/privacy/provider.php deleted file mode 100644 index 271f7ac67a1..00000000000 --- a/admin/tool/log/store/legacy/classes/privacy/provider.php +++ /dev/null @@ -1,255 +0,0 @@ -. - -/** - * Data provider. - * - * @package logstore_legacy - * @copyright 2018 Frédéric Massart - * @author Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace logstore_legacy\privacy; -defined('MOODLE_INTERNAL') || die(); - -use context; -use core_privacy\local\metadata\collection; -use core_privacy\local\request\approved_contextlist; -use core_privacy\local\request\contextlist; -use core_privacy\local\request\transform; -use core_privacy\local\request\writer; -use tool_log\local\privacy\helper; - -/** - * Data provider class. - * - * @package logstore_legacy - * @copyright 2018 Frédéric Massart - * @author Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class provider implements - \core_privacy\local\metadata\provider, - \tool_log\local\privacy\logstore_provider, - \tool_log\local\privacy\logstore_userlist_provider { - - /** - * Returns metadata. - * - * @param collection $collection The initialised collection to add items to. - * @return collection A listing of user data stored through this system. - */ - public static function get_metadata(collection $collection) : collection { - $collection->add_external_location_link('log', [ - 'time' => 'privacy:metadata:log:time', - 'userid' => 'privacy:metadata:log:userid', - 'ip' => 'privacy:metadata:log:ip', - 'action' => 'privacy:metadata:log:action', - 'url' => 'privacy:metadata:log:url', - 'info' => 'privacy:metadata:log:info', - ], 'privacy:metadata:log'); - return $collection; - } - - /** - * Add contexts that contain user information for the specified user. - * - * @param contextlist $contextlist The contextlist to add the contexts to. - * @param int $userid The user to find the contexts for. - * @return void - */ - public static function add_contexts_for_userid(contextlist $contextlist, $userid) { - $sql = " - SELECT ctx.id - FROM {context} ctx - JOIN {log} l - ON (l.cmid = 0 AND l.course = ctx.instanceid AND ctx.contextlevel = :courselevel) - OR (l.cmid > 0 AND l.cmid = ctx.instanceid AND ctx.contextlevel = :modulelevel) - OR (l.course <= 0 AND ctx.id = :syscontextid) - WHERE l.userid = :userid"; - $params = [ - 'courselevel' => CONTEXT_COURSE, - 'modulelevel' => CONTEXT_MODULE, - 'syscontextid' => SYSCONTEXTID, - 'userid' => $userid, - ]; - $contextlist->add_from_sql($sql, $params); - } - - /** - * Add user IDs that contain user information for the specified context. - * - * @param \core_privacy\local\request\userlist $userlist The userlist to add the users to. - * @return void - */ - public static function add_userids_for_context(\core_privacy\local\request\userlist $userlist) { - $context = $userlist->get_context(); - list($insql, $params) = static::get_sql_where_from_contexts([$context]); - - $sql = "SELECT l.userid - FROM {log} l - WHERE $insql"; - $userlist->add_from_sql('userid', $sql, $params); - } - - /** - * Export all user data for the specified user, in the specified contexts. - * - * @param approved_contextlist $contextlist The approved contexts to export information for. - */ - public static function export_user_data(approved_contextlist $contextlist) { - global $DB; - - $userid = $contextlist->get_user()->id; - list($insql, $inparams) = static::get_sql_where_from_contexts($contextlist->get_contexts()); - if (empty($insql)) { - return; - } - $sql = "userid = :userid AND $insql"; - $params = array_merge($inparams, ['userid' => $userid]); - - $path = [get_string('privacy:path:logs', 'tool_log'), get_string('pluginname', 'logstore_legacy')]; - $flush = function($lastcontextid, $data) use ($path) { - $context = context::instance_by_id($lastcontextid); - writer::with_context($context)->export_data($path, (object) ['logs' => $data]); - }; - - $lastcontextid = null; - $data = []; - $recordset = $DB->get_recordset_select('log', $sql, $params, 'course, cmid, time, id'); - foreach ($recordset as $record) { - $event = \logstore_legacy\event\legacy_logged::restore_legacy($record); - $context = $event->get_context(); - if ($lastcontextid && $lastcontextid != $context->id) { - $flush($lastcontextid, $data); - $data = []; - } - - $extra = $event->get_logextra(); - $data[] = [ - 'name' => $event->get_name(), - 'description' => $event->get_description(), - 'timecreated' => transform::datetime($event->timecreated), - 'ip' => $extra['ip'], - 'origin' => helper::transform_origin($extra['origin']), - ]; - - $lastcontextid = $context->id; - } - if ($lastcontextid) { - $flush($lastcontextid, $data); - } - $recordset->close(); - } - - /** - * Delete all data for all users in the specified context. - * - * @param context $context The specific context to delete data for. - */ - public static function delete_data_for_all_users_in_context(context $context) { - global $DB; - list($sql, $params) = static::get_sql_where_from_contexts([$context]); - if (empty($sql)) { - return; - } - $DB->delete_records_select('log', $sql, $params); - } - - /** - * Delete all user data for the specified user, in the specified contexts. - * - * @param approved_contextlist $contextlist The approved contexts and user information to delete information for. - */ - public static function delete_data_for_user(approved_contextlist $contextlist) { - global $DB; - list($sql, $params) = static::get_sql_where_from_contexts($contextlist->get_contexts()); - if (empty($sql)) { - return; - } - $userid = $contextlist->get_user()->id; - $DB->delete_records_select('log', "$sql AND userid = :userid", array_merge($params, ['userid' => $userid])); - } - - - /** - * Delete all data for a list of users in the specified context. - * - * @param \core_privacy\local\request\approved_userlist $userlist The specific context and users to delete data for. - * @return void - */ - public static function delete_data_for_userlist(\core_privacy\local\request\approved_userlist $userlist) { - global $DB; - list($sql, $params) = static::get_sql_where_from_contexts([$userlist->get_context()]); - if (empty($sql)) { - return; - } - list($usersql, $userparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED); - $params = array_merge($params, $userparams); - $DB->delete_records_select('log', "$sql AND userid $usersql", $params); - } - - /** - * Get an SQL where statement from a list of contexts. - * - * @param array $contexts The contexts. - * @return array [$sql, $params] - */ - protected static function get_sql_where_from_contexts(array $contexts) { - global $DB; - - $sorted = array_reduce($contexts, function ($carry, $context) { - $level = $context->contextlevel; - if ($level == CONTEXT_MODULE || $level == CONTEXT_COURSE) { - $carry[$level][] = $context->instanceid; - } else if ($level == CONTEXT_SYSTEM) { - $carry[$level] = $context->id; - } - return $carry; - }, [ - CONTEXT_COURSE => [], - CONTEXT_MODULE => [], - CONTEXT_SYSTEM => null, - ]); - - $sqls = []; - $params = []; - - if (!empty($sorted[CONTEXT_MODULE])) { - list($insql, $inparams) = $DB->get_in_or_equal($sorted[CONTEXT_MODULE], SQL_PARAMS_NAMED); - $sqls[] = "cmid $insql"; - $params = array_merge($params, $inparams); - } - - if (!empty($sorted[CONTEXT_COURSE])) { - list($insql, $inparams) = $DB->get_in_or_equal($sorted[CONTEXT_COURSE], SQL_PARAMS_NAMED); - - $sqls[] = "cmid = 0 AND course $insql"; - $params = array_merge($params, $inparams); - } - - if (!empty($sorted[CONTEXT_SYSTEM])) { - $sqls[] = "course <= 0"; - } - - if (empty($sqls)) { - return [null, null]; - } - - return ['((' . implode(') OR (', $sqls) . '))', $params]; - } -} diff --git a/admin/tool/log/store/legacy/classes/task/cleanup_task.php b/admin/tool/log/store/legacy/classes/task/cleanup_task.php deleted file mode 100644 index 4d0e62aa926..00000000000 --- a/admin/tool/log/store/legacy/classes/task/cleanup_task.php +++ /dev/null @@ -1,69 +0,0 @@ -. - -/** - * Legacy log reader. - * - * @package logstore_legacy - * @copyright 2014 Petr Skoda {@link http://skodak.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace logstore_legacy\task; - -defined('MOODLE_INTERNAL') || die(); - -class cleanup_task extends \core\task\scheduled_task { - - /** - * Get a descriptive name for this task (shown to admins). - * - * @return string - */ - public function get_name() { - return get_string('taskcleanup', 'logstore_legacy'); - } - - /** - * Do the job. - * Throw exceptions on errors (the job will be retried). - */ - public function execute() { - global $CFG, $DB; - - if (empty($CFG->loglifetime)) { - return; - } - - $loglifetime = time() - ($CFG->loglifetime * 3600 * 24); // Value in days. - $lifetimep = array($loglifetime); - $start = time(); - - while ($min = $DB->get_field_select("log", "MIN(time)", "time < ?", $lifetimep)) { - // Break this down into chunks to avoid transaction for too long and generally thrashing database. - // Experiments suggest deleting one day takes up to a few seconds; probably a reasonable chunk size usually. - // If the cleanup has just been enabled, it might take e.g a month to clean the years of logs. - $params = array(min($min + 3600 * 24, $loglifetime)); - $DB->delete_records_select("log", "time < ?", $params); - if (time() > $start + 300) { - // Do not churn on log deletion for too long each run. - break; - } - } - - mtrace(" Deleted old legacy log records"); - } -} diff --git a/admin/tool/log/store/legacy/db/tasks.php b/admin/tool/log/store/legacy/db/tasks.php deleted file mode 100644 index 7aeed6772b0..00000000000 --- a/admin/tool/log/store/legacy/db/tasks.php +++ /dev/null @@ -1,37 +0,0 @@ -. - -/** - * Legacy log reader cron task. - * - * @package logstore_legacy - * @copyright 2014 Petr Skoda {@link http://skodak.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$tasks = array( - array( - 'classname' => '\logstore_legacy\task\cleanup_task', - 'blocking' => 0, - 'minute' => 'R', - 'hour' => '5', - 'day' => '*', - 'dayofweek' => '*', - 'month' => '*' - ), -); \ No newline at end of file diff --git a/admin/tool/log/store/legacy/lang/en/logstore_legacy.php b/admin/tool/log/store/legacy/lang/en/logstore_legacy.php deleted file mode 100644 index d40f4cfd180..00000000000 --- a/admin/tool/log/store/legacy/lang/en/logstore_legacy.php +++ /dev/null @@ -1,37 +0,0 @@ -. - -/** - * Legacy log reader lang strings. - * - * @package logstore_legacy - * @copyright 2013 Petr Skoda {@link http://skodak.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -$string['eventlegacylogged'] = 'Legacy event logged'; -$string['loglegacy'] = 'Log legacy data'; -$string['loglegacy_help'] = 'This plugin records log data to the legacy log table (mdl_log). This functionality has been replaced by newer, richer and more efficient logging plugins, so you should only run this plugin if you have old custom reports that directly query the old log table. Writing to the legacy logs will increase load, so it is recommended that you disable this plugin for performance reasons when it is not needed.'; -$string['pluginname'] = 'Legacy log'; -$string['pluginname_desc'] = 'A log plugin that stores log entries in the legacy log table.'; -$string['privacy:metadata:log'] = 'A collection of past events'; -$string['privacy:metadata:log:action'] = 'A description of the action'; -$string['privacy:metadata:log:info'] = 'Additional information'; -$string['privacy:metadata:log:ip'] = 'The IP address used at the time of the event'; -$string['privacy:metadata:log:time'] = 'The time when the action took place'; -$string['privacy:metadata:log:url'] = 'The URL related to the event'; -$string['privacy:metadata:log:userid'] = 'The ID of the user who performed the action'; -$string['taskcleanup'] = 'Legacy log table cleanup'; diff --git a/admin/tool/log/store/legacy/settings.php b/admin/tool/log/store/legacy/settings.php deleted file mode 100644 index 0a7149ecb7c..00000000000 --- a/admin/tool/log/store/legacy/settings.php +++ /dev/null @@ -1,52 +0,0 @@ -. - -/** - * Legacy logging settings. - * - * @package logstore_legacy - * @copyright 2014 Petr Skoda {@link http://skodak.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -if ($hassiteconfig) { - $settings->add(new admin_setting_configcheckbox('logstore_legacy/loglegacy', - new lang_string('loglegacy', 'logstore_legacy'), - new lang_string('loglegacy_help', 'logstore_legacy'), 0)); - - $settings->add(new admin_setting_configcheckbox('logguests', - new lang_string('logguests', 'admin'), - new lang_string('logguests_help', 'admin'), 1)); - - $options = array(0 => new lang_string('neverdeletelogs'), - 1000 => new lang_string('numdays', '', 1000), - 365 => new lang_string('numdays', '', 365), - 180 => new lang_string('numdays', '', 180), - 150 => new lang_string('numdays', '', 150), - 120 => new lang_string('numdays', '', 120), - 90 => new lang_string('numdays', '', 90), - 60 => new lang_string('numdays', '', 60), - 35 => new lang_string('numdays', '', 35), - 10 => new lang_string('numdays', '', 10), - 5 => new lang_string('numdays', '', 5), - 2 => new lang_string('numdays', '', 2)); - - $settings->add(new admin_setting_configselect('loglifetime', - new lang_string('loglifetime', 'admin'), - new lang_string('configloglifetime', 'admin'), 0, $options)); -} diff --git a/admin/tool/log/store/legacy/tests/fixtures/event.php b/admin/tool/log/store/legacy/tests/fixtures/event.php deleted file mode 100644 index 4afb22bd77d..00000000000 --- a/admin/tool/log/store/legacy/tests/fixtures/event.php +++ /dev/null @@ -1,47 +0,0 @@ -. - -/** - * Fixtures for legacy logging testing. - * - * @package logstore_legacy - * @copyright 2014 Petr Skoda - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace logstore_legacy\event; - -defined('MOODLE_INTERNAL') || die(); - - -class unittest_executed extends \core\event\base { - public static function get_name() { - return 'xxx'; - } - - public function get_description() { - return 'yyy'; - } - - protected function init() { - $this->data['crud'] = 'u'; - $this->data['edulevel'] = self::LEVEL_PARTICIPATING; - } - - public function get_url() { - return new \moodle_url('/somepath/somefile.php', array('id' => $this->data['other']['sample'])); - } -} diff --git a/admin/tool/log/store/legacy/tests/fixtures/store.php b/admin/tool/log/store/legacy/tests/fixtures/store.php deleted file mode 100644 index f8fe163ca01..00000000000 --- a/admin/tool/log/store/legacy/tests/fixtures/store.php +++ /dev/null @@ -1,43 +0,0 @@ -. - -/** - * Fixtures for legacy logging testing. - * - * @package logstore_legacy - * @copyright 2014 onwards Ankit Agarwal - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace logstore_legacy\test; - -defined('MOODLE_INTERNAL') || die(); - -class unittest_logstore_legacy extends \logstore_legacy\log\store { - - /** - * Wrapper to make protected method accessible during testing. - * - * @param string $select sql predicate. - * @param array $params sql params. - * @param string $sort sort options. - * - * @return array returns array of sql predicate, params and sorting criteria. - */ - public static function replace_sql_legacy($select, array $params, $sort = '') { - return parent::replace_sql_legacy($select, $params, $sort); - } -} diff --git a/admin/tool/log/store/legacy/tests/privacy/provider_test.php b/admin/tool/log/store/legacy/tests/privacy/provider_test.php deleted file mode 100644 index f42a19d4bbb..00000000000 --- a/admin/tool/log/store/legacy/tests/privacy/provider_test.php +++ /dev/null @@ -1,472 +0,0 @@ -. - -/** - * Data provider tests. - * - * @package logstore_legacy - * @category test - * @copyright 2018 Frédéric Massart - * @author Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -namespace logstore_legacy\privacy; - -defined('MOODLE_INTERNAL') || die(); -global $CFG; - -use core_privacy\tests\provider_testcase; -use core_privacy\local\request\contextlist; -use core_privacy\local\request\approved_contextlist; -use core_privacy\local\request\transform; -use core_privacy\local\request\writer; -use logstore_legacy\privacy\provider; -use logstore_legacy\event\unittest_executed; - -require_once(__DIR__ . '/../fixtures/event.php'); - -/** - * Data provider testcase class. - * - * @package logstore_legacy - * @category test - * @copyright 2018 Frédéric Massart - * @author Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class provider_test extends provider_testcase { - - public function setUp(): void { - $this->resetAfterTest(); - } - - public function test_get_contexts_for_userid() { - $u1 = $this->getDataGenerator()->create_user(); - $u2 = $this->getDataGenerator()->create_user(); - $u3 = $this->getDataGenerator()->create_user(); - $c1 = $this->getDataGenerator()->create_course(); - $cm1 = $this->getDataGenerator()->create_module('url', ['course' => $c1]); - $sysctx = \context_system::instance(); - $c1ctx = \context_course::instance($c1->id); - $cm1ctx = \context_module::instance($cm1->cmid); - - $this->enable_logging(); - $manager = get_log_manager(true); - - // User 1 is the author. - $this->setUser($u1); - $this->assert_contextlist_equals($this->get_contextlist_for_user($u1), []); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 1]]); - $e->trigger(); - $this->assert_contextlist_equals($this->get_contextlist_for_user($u1), [$cm1ctx]); - - // User 2 is the author. - $this->setUser($u2); - $this->assert_contextlist_equals($this->get_contextlist_for_user($u2), []); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 2]]); - $e->trigger(); - $this->assert_contextlist_equals($this->get_contextlist_for_user($u2), [$cm1ctx]); - - // User 3 is the author. - $this->setUser($u3); - $this->assert_contextlist_equals($this->get_contextlist_for_user($u3), []); - $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 3]]); - $e->trigger(); - $this->assert_contextlist_equals($this->get_contextlist_for_user($u3), [$sysctx]); - } - - /** - * Test returning user IDs for a given context. - */ - public function test_add_userids_for_context() { - $u1 = $this->getDataGenerator()->create_user(); - $u2 = $this->getDataGenerator()->create_user(); - $u3 = $this->getDataGenerator()->create_user(); - $course = $this->getDataGenerator()->create_course(); - $module = $this->getDataGenerator()->create_module('url', ['course' => $course]); - $sysctx = \context_system::instance(); - $c1ctx = \context_course::instance($course->id); - $cm1ctx = \context_module::instance($module->cmid); - - $userctx = \context_user::instance($u1->id); - - $this->enable_logging(); - $manager = get_log_manager(true); - - $this->setUser($u1); - $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 1]]); - $e->trigger(); - $this->setUser($u2); - $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 2]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 3]]); - $e->trigger(); - $this->setUser($u3); - $e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 4]]); - $e->trigger(); - $this->setUser($u1); - $e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 5]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 6]]); - $e->trigger(); - $this->setUser($u2); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 7]]); - $e->trigger(); - $this->setUser($u3); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 8]]); - $e->trigger(); - - // Start with system and check that each of the contexts returns what we expected. - $userlist = new \core_privacy\local\request\userlist($sysctx, 'logstore_legacy'); - provider::add_userids_for_context($userlist); - $systemuserids = $userlist->get_userids(); - $this->assertCount(2, $systemuserids); - $this->assertNotFalse(array_search($u1->id, $systemuserids)); - $this->assertNotFalse(array_search($u2->id, $systemuserids)); - // Check the course context. - $userlist = new \core_privacy\local\request\userlist($c1ctx, 'logstore_legacy'); - provider::add_userids_for_context($userlist); - $courseuserids = $userlist->get_userids(); - $this->assertCount(2, $courseuserids); - $this->assertNotFalse(array_search($u1->id, $courseuserids)); - $this->assertNotFalse(array_search($u3->id, $courseuserids)); - // Check the module context. - $userlist = new \core_privacy\local\request\userlist($cm1ctx, 'logstore_legacy'); - provider::add_userids_for_context($userlist); - $moduleuserids = $userlist->get_userids(); - $this->assertCount(3, $moduleuserids); - $this->assertNotFalse(array_search($u1->id, $moduleuserids)); - $this->assertNotFalse(array_search($u2->id, $moduleuserids)); - $this->assertNotFalse(array_search($u3->id, $moduleuserids)); - } - - public function test_delete_data_for_user() { - global $DB; - - $u1 = $this->getDataGenerator()->create_user(); - $u2 = $this->getDataGenerator()->create_user(); - $u3 = $this->getDataGenerator()->create_user(); - $c1 = $this->getDataGenerator()->create_course(); - $c2 = $this->getDataGenerator()->create_course(); - $cm1 = $this->getDataGenerator()->create_module('url', ['course' => $c1]); - $sysctx = \context_system::instance(); - $c1ctx = \context_course::instance($c1->id); - $c2ctx = \context_course::instance($c2->id); - $cm1ctx = \context_module::instance($cm1->cmid); - - $this->enable_logging(); - $manager = get_log_manager(true); - - // User 1 is the author. - $this->setUser($u1); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 1]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 2]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 3]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 4]]); - $e->trigger(); - - // User 2 is the author. - $this->setUser($u2); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 5]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 6]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 7]]); - $e->trigger(); - - // Assert what we have. - $this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => $cm1->cmid, 'course' => $c1->id])); - $this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => $c1->id])); - $this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => 0])); - $this->assertEquals(4, $DB->count_records('log', ['userid' => $u1->id])); - $this->assertEquals(3, $DB->count_records('log', ['userid' => $u2->id])); - - // Delete other context. - provider::delete_data_for_user(new approved_contextlist($u1, 'logstore_legacy', [$c2ctx->id])); - $this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => $cm1->cmid, 'course' => $c1->id])); - $this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => $c1->id])); - $this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => 0])); - $this->assertEquals(4, $DB->count_records('log', ['userid' => $u1->id])); - $this->assertEquals(3, $DB->count_records('log', ['userid' => $u2->id])); - - // Delete system. - provider::delete_data_for_user(new approved_contextlist($u1, 'logstore_legacy', [$sysctx->id])); - $this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => $cm1->cmid, 'course' => $c1->id])); - $this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => $c1->id])); - $this->assertFalse($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => 0])); - $this->assertEquals(3, $DB->count_records('log', ['userid' => $u1->id])); - $this->assertEquals(3, $DB->count_records('log', ['userid' => $u2->id])); - - // Delete course. - provider::delete_data_for_user(new approved_contextlist($u1, 'logstore_legacy', [$c1ctx->id])); - $this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => $cm1->cmid, 'course' => $c1->id])); - $this->assertFalse($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => $c1->id])); - $this->assertFalse($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => 0])); - $this->assertEquals(2, $DB->count_records('log', ['userid' => $u1->id])); - $this->assertEquals(3, $DB->count_records('log', ['userid' => $u2->id])); - - // Delete course. - provider::delete_data_for_user(new approved_contextlist($u1, 'logstore_legacy', [$cm1ctx->id])); - $this->assertFalse($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => $cm1->cmid, 'course' => $c1->id])); - $this->assertFalse($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => $c1->id])); - $this->assertFalse($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => 0])); - $this->assertEquals(0, $DB->count_records('log', ['userid' => $u1->id])); - $this->assertEquals(3, $DB->count_records('log', ['userid' => $u2->id])); - } - - public function test_delete_data_for_all_users_in_context() { - global $DB; - - $u1 = $this->getDataGenerator()->create_user(); - $u2 = $this->getDataGenerator()->create_user(); - $u3 = $this->getDataGenerator()->create_user(); - $c1 = $this->getDataGenerator()->create_course(); - $c2 = $this->getDataGenerator()->create_course(); - $cm1 = $this->getDataGenerator()->create_module('url', ['course' => $c1]); - $sysctx = \context_system::instance(); - $c1ctx = \context_course::instance($c1->id); - $c2ctx = \context_course::instance($c2->id); - $cm1ctx = \context_module::instance($cm1->cmid); - - $this->enable_logging(); - $manager = get_log_manager(true); - - // User 1 is the author. - $this->setUser($u1); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 1]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 2]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 3]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 4]]); - $e->trigger(); - - // User 2 is the author. - $this->setUser($u2); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 5]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 6]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 7]]); - $e->trigger(); - - // Assert what we have. - $this->assertTrue($DB->record_exists('log', ['cmid' => $cm1->cmid, 'course' => $c1->id])); - $this->assertTrue($DB->record_exists('log', ['cmid' => 0, 'course' => $c1->id])); - $this->assertTrue($DB->record_exists('log', ['cmid' => 0, 'course' => 0])); - $this->assertEquals(4, $DB->count_records('log', ['userid' => $u1->id])); - $this->assertEquals(3, $DB->count_records('log', ['userid' => $u2->id])); - - // Delete other context. - provider::delete_data_for_all_users_in_context($c2ctx); - $this->assertTrue($DB->record_exists('log', ['cmid' => $cm1->cmid, 'course' => $c1->id])); - $this->assertTrue($DB->record_exists('log', ['cmid' => 0, 'course' => $c1->id])); - $this->assertTrue($DB->record_exists('log', ['cmid' => 0, 'course' => 0])); - $this->assertEquals(4, $DB->count_records('log', ['userid' => $u1->id])); - $this->assertEquals(3, $DB->count_records('log', ['userid' => $u2->id])); - - // Delete system. - provider::delete_data_for_all_users_in_context($sysctx); - $this->assertTrue($DB->record_exists('log', ['cmid' => $cm1->cmid, 'course' => $c1->id])); - $this->assertTrue($DB->record_exists('log', ['cmid' => 0, 'course' => $c1->id])); - $this->assertFalse($DB->record_exists('log', ['cmid' => 0, 'course' => 0])); - $this->assertEquals(3, $DB->count_records('log', ['userid' => $u1->id])); - $this->assertEquals(2, $DB->count_records('log', ['userid' => $u2->id])); - - // Delete course. - provider::delete_data_for_all_users_in_context($c1ctx); - $this->assertTrue($DB->record_exists('log', ['cmid' => $cm1->cmid, 'course' => $c1->id])); - $this->assertFalse($DB->record_exists('log', ['cmid' => 0, 'course' => $c1->id])); - $this->assertFalse($DB->record_exists('log', ['cmid' => 0, 'course' => 0])); - $this->assertEquals(2, $DB->count_records('log', ['userid' => $u1->id])); - $this->assertEquals(1, $DB->count_records('log', ['userid' => $u2->id])); - - // Delete course. - provider::delete_data_for_all_users_in_context($cm1ctx); - $this->assertFalse($DB->record_exists('log', ['cmid' => $cm1->cmid, 'course' => $c1->id])); - $this->assertFalse($DB->record_exists('log', ['cmid' => 0, 'course' => $c1->id])); - $this->assertFalse($DB->record_exists('log', ['cmid' => 0, 'course' => 0])); - $this->assertEquals(0, $DB->count_records('log', ['userid' => $u1->id])); - $this->assertEquals(0, $DB->count_records('log', ['userid' => $u2->id])); - } - - /** - * Test the deletion of data for a list of users in a context. - */ - public function test_delete_data_for_userlist() { - global $DB; - - $u1 = $this->getDataGenerator()->create_user(); - $u2 = $this->getDataGenerator()->create_user(); - $u3 = $this->getDataGenerator()->create_user(); - $course = $this->getDataGenerator()->create_course(); - $module = $this->getDataGenerator()->create_module('url', ['course' => $course]); - $sysctx = \context_system::instance(); - $c1ctx = \context_course::instance($course->id); - $cm1ctx = \context_module::instance($module->cmid); - - $userctx = \context_user::instance($u1->id); - - $this->enable_logging(); - $manager = get_log_manager(true); - - $this->setUser($u1); - $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 1]]); - $e->trigger(); - $this->setUser($u2); - $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 2]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 3]]); - $e->trigger(); - $this->setUser($u3); - $e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 4]]); - $e->trigger(); - $this->setUser($u1); - $e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 5]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 6]]); - $e->trigger(); - $this->setUser($u2); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 7]]); - $e->trigger(); - $this->setUser($u3); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 8]]); - $e->trigger(); - - // System context deleting one user. - $this->assertEquals(3, $DB->count_records('log', ['cmid' => 0, 'course' => 0])); - $userlist = new \core_privacy\local\request\approved_userlist($sysctx, 'logstore_legacy', [$u2->id]); - provider::delete_data_for_userlist($userlist); - $this->assertEquals(1, $DB->count_records('log', ['cmid' => 0, 'course' => 0])); - - // Course context deleting one user. - $this->assertEquals(2, $DB->count_records('log', ['cmid' => 0, 'course' => $course->id])); - $userlist = new \core_privacy\local\request\approved_userlist($c1ctx, 'logstore_legacy', [$u1->id]); - provider::delete_data_for_userlist($userlist); - $this->assertEquals(1, $DB->count_records('log', ['cmid' => 0, 'course' => $course->id])); - - // Module context deleting two users. - $this->assertEquals(3, $DB->count_records('log', ['cmid' => $module->cmid, 'course' => $course->id])); - $userlist = new \core_privacy\local\request\approved_userlist($cm1ctx, 'logstore_legacy', [$u1->id, $u3->id]); - provider::delete_data_for_userlist($userlist); - $this->assertEquals(1, $DB->count_records('log', ['cmid' => $module->cmid, 'course' => $course->id])); - } - - public function test_export_data_for_user() { - global $DB; - - $u1 = $this->getDataGenerator()->create_user(); - $u2 = $this->getDataGenerator()->create_user(); - $u3 = $this->getDataGenerator()->create_user(); - $c1 = $this->getDataGenerator()->create_course(); - $c2 = $this->getDataGenerator()->create_course(); - $cm1 = $this->getDataGenerator()->create_module('url', ['course' => $c1]); - $sysctx = \context_system::instance(); - $c1ctx = \context_course::instance($c1->id); - $c2ctx = \context_course::instance($c2->id); - $cm1ctx = \context_module::instance($cm1->cmid); - - $this->enable_logging(); - $manager = get_log_manager(true); - $path = [get_string('privacy:path:logs', 'tool_log'), get_string('pluginname', 'logstore_legacy')]; - - // User 1 is the author. - $this->setUser($u1); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 1]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 2]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 3]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 4]]); - $e->trigger(); - - // User 2 is the author. - $this->setUser($u2); - $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 5]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 6]]); - $e->trigger(); - $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 7]]); - $e->trigger(); - - // Test export. - provider::export_user_data(new approved_contextlist($u1, 'logstore_legacy', [$cm1ctx->id])); - $data = writer::with_context($c1ctx)->get_data($path); - $this->assertEmpty($data); - $data = writer::with_context($cm1ctx)->get_data($path); - $this->assertCount(2, $data->logs); - - writer::reset(); - provider::export_user_data(new approved_contextlist($u1, 'logstore_legacy', [$c1ctx->id])); - $data = writer::with_context($cm1ctx)->get_data($path); - $this->assertEmpty($data); - $data = writer::with_context($c1ctx)->get_data($path); - $this->assertCount(1, $data->logs); - - writer::reset(); - provider::export_user_data(new approved_contextlist($u1, 'logstore_legacy', [$sysctx->id])); - $data = writer::with_context($sysctx)->get_data($path); - $this->assertCount(1, $data->logs); - } - - /** - * Assert the content of a context list. - * - * @param contextlist $contextlist The collection. - * @param array $expected List of expected contexts or IDs. - * @return void - */ - protected function assert_contextlist_equals($contextlist, array $expected) { - $expectedids = array_map(function($context) { - if (is_object($context)) { - return $context->id; - } - return $context; - }, $expected); - $contextids = array_map('intval', $contextlist->get_contextids()); - sort($contextids); - sort($expectedids); - $this->assertEquals($expectedids, $contextids); - } - - /** - * Enable logging. - * - * @return void - */ - protected function enable_logging() { - set_config('enabled_stores', 'logstore_legacy', 'tool_log'); - set_config('loglegacy', 1, 'logstore_legacy'); - get_log_manager(true); - } - - /** - * Get the contextlist for a user. - * - * @param object $user The user. - * @return contextlist - */ - protected function get_contextlist_for_user($user) { - $contextlist = new contextlist(); - provider::add_contexts_for_userid($contextlist, $user->id); - return $contextlist; - } -} diff --git a/admin/tool/log/store/legacy/tests/store_test.php b/admin/tool/log/store/legacy/tests/store_test.php deleted file mode 100644 index 611d8c13daf..00000000000 --- a/admin/tool/log/store/legacy/tests/store_test.php +++ /dev/null @@ -1,264 +0,0 @@ -. - -namespace logstore_legacy; - -defined('MOODLE_INTERNAL') || die(); - -require_once(__DIR__ . '/fixtures/event.php'); -require_once(__DIR__ . '/fixtures/store.php'); - -/** - * Legacy log store tests. - * - * @package logstore_legacy - * @copyright 2014 Petr Skoda {@link http://skodak.org/} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class store_test extends \advanced_testcase { - public function test_log_writing() { - global $DB; - $this->resetAfterTest(); - - $this->setAdminUser(); - $user1 = $this->getDataGenerator()->create_user(); - $course1 = $this->getDataGenerator()->create_course(); - $module1 = $this->getDataGenerator()->create_module('resource', array('course' => $course1)); - $course2 = $this->getDataGenerator()->create_course(); - - // Enable legacy logging plugin. - set_config('enabled_stores', 'logstore_legacy', 'tool_log'); - set_config('loglegacy', 1, 'logstore_legacy'); - $manager = get_log_manager(true); - - $stores = $manager->get_readers(); - $this->assertCount(1, $stores); - $this->assertEquals(array('logstore_legacy'), array_keys($stores)); - $store = $stores['logstore_legacy']; - $this->assertInstanceOf('logstore_legacy\log\store', $store); - $this->assertInstanceOf('core\log\sql_reader', $store); - $this->assertTrue($store->is_logging()); - - $logs = $DB->get_records('log', array(), 'id ASC'); - $this->assertCount(0, $logs); - - $this->setCurrentTimeStart(); - - $this->setUser(0); - $event1 = \logstore_legacy\event\unittest_executed::create( - array('context' => \context_module::instance($module1->cmid), 'other' => array('sample' => 5, 'xx' => 10))); - $event1->trigger(); - - $this->setUser($user1); - $event2 = \logstore_legacy\event\unittest_executed::create( - array('context' => \context_course::instance($course2->id), 'other' => array('sample' => 6, 'xx' => 11))); - $event2->trigger(); - - $logs = $DB->get_records('log', array(), 'id ASC'); - $this->assertCount(2, $logs); - - $log = array_shift($logs); - $this->assertNotEmpty($log->id); - $this->assertTimeCurrent($log->time); - $this->assertEquals(0, $log->userid); - $this->assertSame('0.0.0.0', $log->ip); - $this->assertEquals($course1->id, $log->course); - $this->assertSame('core_unittest', $log->module); - $this->assertEquals($module1->cmid, $log->cmid); - $this->assertSame('view', $log->action); - $this->assertSame('unittest.php?id=5', $log->url); - $this->assertSame('bbb', $log->info); - - $oldlogid = $log->id; - $log = array_shift($logs); - $this->assertGreaterThan($oldlogid, $log->id); - $this->assertNotEmpty($log->id); - $this->assertTimeCurrent($log->time); - $this->assertEquals($user1->id, $log->userid); - $this->assertSame('0.0.0.0', $log->ip); - $this->assertEquals($course2->id, $log->course); - $this->assertSame('core_unittest', $log->module); - $this->assertEquals(0, $log->cmid); - $this->assertSame('view', $log->action); - $this->assertSame('unittest.php?id=6', $log->url); - $this->assertSame('bbb', $log->info); - - // Test if disabling works. - set_config('enabled_stores', 'logstore_legacy', 'tool_log'); - set_config('loglegacy', 0, 'logstore_legacy'); - $manager = get_log_manager(true); - $stores = $manager->get_readers(); - $store = $stores['logstore_legacy']; - $this->assertFalse($store->is_logging()); - - \logstore_legacy\event\unittest_executed::create( - array('context' => \context_system::instance(), 'other' => array('sample' => 5, 'xx' => 10)))->trigger(); - $this->assertEquals(2, $DB->count_records('log')); - - // Another way to disable legacy completely. - set_config('enabled_stores', 'logstore_standard', 'tool_log'); - set_config('loglegacy', 1, 'logstore_legacy'); - get_log_manager(true); - - \logstore_legacy\event\unittest_executed::create( - array('context' => \context_system::instance(), 'other' => array('sample' => 5, 'xx' => 10)))->trigger(); - $this->assertEquals(2, $DB->count_records('log')); - // Set everything back. - set_config('enabled_stores', '', 'tool_log'); - set_config('loglegacy', 0, 'logstore_legacy'); - get_log_manager(true); - } - - /** - * Test replace_sql_legacy() - */ - public function test_replace_sql_legacy() { - $selectwhere = "userid = :userid AND courseid = :courseid AND eventname = :eventname AND timecreated > :since"; - $params = array('userid' => 2, 'since' => 3, 'courseid' => 4, 'eventname' => '\core\event\course_created'); - $expectedselect = "module = 'course' AND action = 'new' AND userid = :userid AND url = :url AND time > :since"; - $expectedparams = $params + array('url' => "view.php?id=4"); - - list($replaceselect, $replaceparams) = \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params); - $this->assertEquals($replaceselect, $expectedselect); - $this->assertEquals($replaceparams, $expectedparams); - - // Test CRUD related changes. - $selectwhere = "edulevel = 0"; - list($updatewhere, $replaceparams) = \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params); - $this->assertEquals($selectwhere, $updatewhere); - - $selectwhere = "edulevel = 0 and crud = 'u'"; - list($updatewhere, $replaceparams) = \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params); - $this->assertEquals("edulevel = 0 and action LIKE '%update%'", $updatewhere); - - $selectwhere = "edulevel = 0 and crud != 'u'"; - list($updatewhere, $replaceparams) = \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params); - $this->assertEquals("edulevel = 0 and action NOT LIKE '%update%'", $updatewhere); - - $selectwhere = "edulevel = 0 and crud <> 'u'"; - list($updatewhere, $replaceparams) = \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params); - $this->assertEquals("edulevel = 0 and action NOT LIKE '%update%'", $updatewhere); - - $selectwhere = "edulevel = 0 and crud = 'r'"; - list($updatewhere, $replaceparams) = \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params); - $this->assertEquals("edulevel = 0 and action LIKE '%view%' OR action LIKE '%report%'", $updatewhere); - - $selectwhere = "edulevel = 0 and crud != 'r'"; - list($updatewhere, $replaceparams) = \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params); - $this->assertEquals("edulevel = 0 and action NOT LIKE '%view%' AND action NOT LIKE '%report%'", $updatewhere); - - $selectwhere = "edulevel = 0 and crud <> 'r'"; - list($updatewhere, $replaceparams) = \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params); - $this->assertEquals("edulevel = 0 and action NOT LIKE '%view%' AND action NOT LIKE '%report%'", $updatewhere); - - // The slq is incorrect, since quotes must not be present. Make sure this is not parsed. - $selectwhere = "edulevel = 0 and 'crud' != 'u'"; - list($updatewhere, $replaceparams) = \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params); - $this->assertNotEquals("edulevel = 0 and action NOT LIKE '%update%'", $updatewhere); - - $selectwhere = "edulevel = 0 and crud = 'u' OR crud != 'r' or crud <> 'd'"; - list($updatewhere, $replaceparams) = \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params); - $this->assertEquals("edulevel = 0 and action LIKE '%update%' OR action NOT LIKE '%view%' AND action NOT LIKE '%report%' or action NOT LIKE '%delete%'", $updatewhere); - - // The anonymous select returns all data. - $selectwhere = "anonymous = 0"; - list($updatewhere, $replaceparams) = \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params); - $this->assertSame("0 = 0", $updatewhere); - - // Test legacy field names are mapped. - $selectwhere = "timecreated = :timecreated and courseid = :courseid and contextinstanceid = :contextinstanceid and origin = :origin"; - $params = array('timecreated' => 2, 'courseid' => 3, 'contextinstanceid' => 4, 'origin' => 5 ); - $expectedparams = array('time' => 2, 'course' => 3, 'cmid' => 4, 'ip' => 5); - list($updatewhere, $replaceparams) = \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params); - $this->assertEquals("time = :time and course = :course and cmid = :cmid and ip = :ip", $updatewhere); - $this->assertSame($expectedparams, $replaceparams); - - // Test sorting parameters. - $selectwhere = "courseid = 3"; - $params = array(); - $sort = 'timecreated DESC'; - list($updatewhere, $replaceparams, $sort) = - \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params, $sort); - $this->assertSame('time DESC', $sort); - - $sort = 'courseid DESC'; - list($updatewhere, $replaceparams, $sort) = - \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params, $sort); - $this->assertSame('course DESC', $sort); - - $sort = 'contextinstanceid DESC'; - list($updatewhere, $replaceparams, $sort) = - \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params, $sort); - $this->assertSame('cmid DESC', $sort); - - $sort = 'origin DESC'; - list($updatewhere, $replaceparams, $sort) = - \logstore_legacy\test\unittest_logstore_legacy::replace_sql_legacy($selectwhere, $params, $sort); - $this->assertSame('ip DESC', $sort); - } - - /* - * Test logmanager::get_supported_reports returns all reports that require this store. - */ - public function test_get_supported_reports() { - $logmanager = get_log_manager(); - $allreports = \core_component::get_plugin_list('report'); - - // Make sure all supported reports are installed. - $expectedreports = array_intersect_key([ - 'log' => 'report_log', - 'loglive' => 'report_loglive', - 'outline' => 'report_outline', - 'participation' => 'report_participation', - 'stats' => 'report_stats' - ], $allreports); - - $supportedreports = $logmanager->get_supported_reports('logstore_legacy'); - - foreach ($expectedreports as $expectedreport) { - $this->assertArrayHasKey($expectedreport, $supportedreports); - } - } - - /** - * Test that the legacy log cleanup works correctly. - */ - public function test_cleanup_task() { - global $DB; - - $this->resetAfterTest(); - - // Create some records spread over various days; test multiple iterations in cleanup. - $record = (object) array('time' => time()); - $DB->insert_record('log', $record); - $record->time -= 3600 * 24 * 30; - $DB->insert_record('log', $record); - $record->time -= 3600 * 24 * 30; - $DB->insert_record('log', $record); - $record->time -= 3600 * 24 * 30; - $DB->insert_record('log', $record); - $this->assertEquals(4, $DB->count_records('log')); - - // Remove all logs before "today". - set_config('loglifetime', 1); - - $this->expectOutputString(" Deleted old legacy log records\n"); - $clean = new \logstore_legacy\task\cleanup_task(); - $clean->execute(); - - $this->assertEquals(1, $DB->count_records('log')); - } -} diff --git a/admin/tool/log/store/legacy/version.php b/admin/tool/log/store/legacy/version.php deleted file mode 100644 index 495cef4020f..00000000000 --- a/admin/tool/log/store/legacy/version.php +++ /dev/null @@ -1,29 +0,0 @@ -. - -/** - * Legacy log reader. - * - * @package logstore_legacy - * @copyright 2013 Petr Skoda {@link http://skodak.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$plugin->version = 2022112800; // The current plugin version (Date: YYYYMMDDXX). -$plugin->requires = 2022111800; // Requires this Moodle version. -$plugin->component = 'logstore_legacy'; // Full name of the plugin (used for diagnostics). diff --git a/admin/tool/log/tests/manager_test.php b/admin/tool/log/tests/manager_test.php index 46d5af672fc..a9fb357117a 100644 --- a/admin/tool/log/tests/manager_test.php +++ b/admin/tool/log/tests/manager_test.php @@ -36,15 +36,14 @@ class manager_test extends \advanced_testcase { $this->assertCount(0, $stores); $this->assertFileExists("$CFG->dirroot/$CFG->admin/tool/log/store/standard/version.php"); - $this->assertFileExists("$CFG->dirroot/$CFG->admin/tool/log/store/legacy/version.php"); - set_config('enabled_stores', 'logstore_standard,logstore_legacy', 'tool_log'); + set_config('enabled_stores', 'logstore_standard', 'tool_log'); $manager = get_log_manager(true); $this->assertInstanceOf('core\log\manager', $manager); $stores = $manager->get_readers(); $this->assertIsArray($stores); - $this->assertCount(2, $stores); + $this->assertCount(1, $stores); foreach ($stores as $key => $store) { $this->assertIsString($key); $this->assertInstanceOf('core\log\sql_reader', $store); @@ -61,7 +60,7 @@ class manager_test extends \advanced_testcase { $stores = $manager->get_readers('core\log\sql_reader'); $this->assertIsArray($stores); - $this->assertCount(2, $stores); + $this->assertCount(1, $stores); foreach ($stores as $key => $store) { $this->assertIsString($key); $this->assertInstanceOf('core\log\sql_reader', $store); diff --git a/lib/classes/plugin_manager.php b/lib/classes/plugin_manager.php index cbcce1c2b5d..00ab4be4d43 100644 --- a/lib/classes/plugin_manager.php +++ b/lib/classes/plugin_manager.php @@ -1745,6 +1745,7 @@ class core_plugin_manager { 'binarius', 'boxxie', 'brick', 'canvas', 'formal_white', 'formfactor', 'fusion', 'leatherbound', 'magazine', 'mymobile', 'nimble', 'nonzero', 'overlay', 'serenity', 'sky_high', 'splash', 'standard', 'standardold'), + 'logstore' => ['legacy'], 'webservice' => array('amf', 'xmlrpc'), ); @@ -1908,7 +1909,7 @@ class core_plugin_manager { ), 'logstore' => array( - 'database', 'legacy', 'standard', + 'database', 'standard', ), 'ltiservice' => array( diff --git a/mod/forum/report/summary/classes/summary_table.php b/mod/forum/report/summary/classes/summary_table.php index 6e921400e2a..72c32a15c90 100644 --- a/mod/forum/report/summary/classes/summary_table.php +++ b/mod/forum/report/summary/classes/summary_table.php @@ -747,7 +747,7 @@ class summary_table extends table_sql { foreach ($readers as $reader) { // If reader is not a sql_internal_table_reader and not legacy store then return. - if (!($reader instanceof \core\log\sql_internal_table_reader) && !($reader instanceof logstore_legacy\log\store)) { + if (!($reader instanceof \core\log\sql_internal_table_reader)) { continue; } $logreader = $reader; @@ -770,14 +770,8 @@ class summary_table extends table_sql { $this->create_log_summary_temp_table(); - if ($this->logreader instanceof logstore_legacy\log\store) { - $logtable = 'log'; - // Anonymous actions are never logged in legacy log. - $nonanonymous = ''; - } else { - $logtable = $this->logreader->get_internal_log_table_name(); - $nonanonymous = 'AND anonymous = 0'; - } + $logtable = $this->logreader->get_internal_log_table_name(); + $nonanonymous = 'AND anonymous = 0'; // Apply dates filter if applied. $datewhere = $this->sql->filterbase['dateslog'] ?? ''; diff --git a/report/eventlist/classes/list_generator.php b/report/eventlist/classes/list_generator.php index e9dbd034937..6f76b303593 100644 --- a/report/eventlist/classes/list_generator.php +++ b/report/eventlist/classes/list_generator.php @@ -54,7 +54,6 @@ class report_eventlist_list_generator { // List of exceptional events that will cause problems if displayed. $eventsignore = [ \core\event\unknown_logged::class, - \logstore_legacy\event\legacy_logged::class, ]; $eventinformation = []; @@ -248,7 +247,7 @@ class report_eventlist_list_generator { if (method_exists($plugineventname, 'get_static_info')) { if ($detail) { $ref = new \ReflectionClass($plugineventname); - if (!$ref->isAbstract() && $plugintype . '_' . $plugin !== 'logstore_legacy') { + if (!$ref->isAbstract()) { $noncorepluginlist = self::format_data($noncorepluginlist, $plugineventname); } } else { diff --git a/report/log/classes/table_log.php b/report/log/classes/table_log.php index 4c982f64605..f240d8ebfcb 100644 --- a/report/log/classes/table_log.php +++ b/report/log/classes/table_log.php @@ -274,12 +274,7 @@ class report_log_table_log extends table_sql { */ public function col_eventname($event) { // Event name. - if ($this->filterparams->logreader instanceof logstore_legacy\log\store) { - // Hack for support of logstore_legacy. - $eventname = $event->eventname; - } else { - $eventname = $event->get_name(); - } + $eventname = $event->get_name(); // Only encode as an action link if we're not downloading. if (($url = $event->get_url()) && empty($this->download)) { $eventname = $this->action_link($url, $eventname, 'action'); @@ -370,17 +365,7 @@ class report_log_table_log extends table_sql { global $DB; // In new logs we have a field to pick, and in legacy try get this from action. - if ($this->filterparams->logreader instanceof logstore_legacy\log\store) { - $action = $this->get_legacy_crud_action($this->filterparams->action); - $firstletter = substr($action, 0, 1); - if ($firstletter == '-') { - $sql = $DB->sql_like('action', ':action', false, true, true); - $params['action'] = '%'.substr($action, 1).'%'; - } else { - $sql = $DB->sql_like('action', ':action', false); - $params['action'] = '%'.$action.'%'; - } - } else if (!empty($this->filterparams->action)) { + if (!empty($this->filterparams->action)) { list($sql, $params) = $DB->get_in_or_equal(str_split($this->filterparams->action), SQL_PARAMS_NAMED, 'crud'); $sql = "crud " . $sql; @@ -402,16 +387,10 @@ class report_log_table_log extends table_sql { $joins = array(); $params = array(); - if ($this->filterparams->logreader instanceof logstore_legacy\log\store) { - // The legacy store doesn't support context level. - $joins[] = "cmid = :cmid"; - $params['cmid'] = $this->filterparams->modid; - } else { - $joins[] = "contextinstanceid = :contextinstanceid"; - $joins[] = "contextlevel = :contextmodule"; - $params['contextinstanceid'] = $this->filterparams->modid; - $params['contextmodule'] = CONTEXT_MODULE; - } + $joins[] = "contextinstanceid = :contextinstanceid"; + $joins[] = "contextlevel = :contextmodule"; + $params['contextinstanceid'] = $this->filterparams->modid; + $params['contextmodule'] = CONTEXT_MODULE; $sql = implode(' AND ', $joins); return array($sql, $params); @@ -430,8 +409,7 @@ class report_log_table_log extends table_sql { $params = array(); // If we filter by userid and module id we also need to filter by crud and edulevel to ensure DB index is engaged. - $useextendeddbindex = !($this->filterparams->logreader instanceof logstore_legacy\log\store) - && !empty($this->filterparams->userid) && !empty($this->filterparams->modid); + $useextendeddbindex = !empty($this->filterparams->userid) && !empty($this->filterparams->modid); $groupid = 0; if (!empty($this->filterparams->courseid) && $this->filterparams->courseid != SITEID) { @@ -503,16 +481,14 @@ class report_log_table_log extends table_sql { } } - if (!($this->filterparams->logreader instanceof logstore_legacy\log\store)) { - // Filter out anonymous actions, this is N/A for legacy log because it never stores them. - if ($this->filterparams->modid) { - $context = context_module::instance($this->filterparams->modid); - } else { - $context = context_course::instance($this->filterparams->courseid); - } - if (!has_capability('moodle/site:viewanonymousevents', $context)) { - $joins[] = "anonymous = 0"; - } + // Filter out anonymous actions, this is N/A for legacy log because it never stores them. + if ($this->filterparams->modid) { + $context = context_module::instance($this->filterparams->modid); + } else { + $context = context_course::instance($this->filterparams->courseid); + } + if (!has_capability('moodle/site:viewanonymousevents', $context)) { + $joins[] = "anonymous = 0"; } $selector = implode(' AND ', $joins); diff --git a/report/log/index.php b/report/log/index.php index 8db48419616..82df2860a91 100644 --- a/report/log/index.php +++ b/report/log/index.php @@ -94,11 +94,6 @@ if (($edulevel != -1)) { if ($origin !== '') { $params['origin'] = $origin; } -// Legacy store hack, as edulevel is not supported. -if ($logreader == 'logstore_legacy') { - $params['edulevel'] = -1; - $edulevel = -1; -} $url = new moodle_url("/report/log/index.php", $params); $PAGE->set_url('/report/log/index.php', array('id' => $id)); diff --git a/report/log/locallib.php b/report/log/locallib.php index 24847dafa15..1ac18e333cb 100644 --- a/report/log/locallib.php +++ b/report/log/locallib.php @@ -59,7 +59,7 @@ function report_log_print_graph($course, $user, $typeormode, $date=0, $logreader $reader = $readers[$logreader]; } // If reader is not a sql_internal_table_reader and not legacy store then don't show graph. - if (!($reader instanceof \core\log\sql_internal_table_reader) && !($reader instanceof logstore_legacy\log\store)) { + if (!($reader instanceof \core\log\sql_internal_table_reader)) { return array(); } $coursecontext = context_course::instance($course->id); @@ -114,23 +114,15 @@ function report_log_usercourse($userid, $courseid, $coursestart, $logreader = '' } // If reader is not a sql_internal_table_reader and not legacy store then return. - if (!($reader instanceof \core\log\sql_internal_table_reader) && !($reader instanceof logstore_legacy\log\store)) { + if (!($reader instanceof \core\log\sql_internal_table_reader)) { return array(); } $coursestart = (int)$coursestart; // Note: unfortunately pg complains if you use name parameter or column alias in GROUP BY. - if ($reader instanceof logstore_legacy\log\store) { - $logtable = 'log'; - $timefield = 'time'; - $coursefield = 'course'; - // Anonymous actions are never logged in legacy log. - $nonanonymous = ''; - } else { - $logtable = $reader->get_internal_log_table_name(); - $timefield = 'timecreated'; - $coursefield = 'courseid'; - $nonanonymous = 'AND anonymous = 0'; - } + $logtable = $reader->get_internal_log_table_name(); + $timefield = 'timecreated'; + $coursefield = 'courseid'; + $nonanonymous = 'AND anonymous = 0'; $params = array(); $courseselect = ''; @@ -166,24 +158,16 @@ function report_log_userday($userid, $courseid, $daystart, $logreader = '') { } // If reader is not a sql_internal_table_reader and not legacy store then return. - if (!($reader instanceof \core\log\sql_internal_table_reader) && !($reader instanceof logstore_legacy\log\store)) { + if (!($reader instanceof \core\log\sql_internal_table_reader)) { return array(); } $daystart = (int)$daystart; // Note: unfortunately pg complains if you use name parameter or column alias in GROUP BY. - if ($reader instanceof logstore_legacy\log\store) { - $logtable = 'log'; - $timefield = 'time'; - $coursefield = 'course'; - // Anonymous actions are never logged in legacy log. - $nonanonymous = ''; - } else { - $logtable = $reader->get_internal_log_table_name(); - $timefield = 'timecreated'; - $coursefield = 'courseid'; - $nonanonymous = 'AND anonymous = 0'; - } + $logtable = $reader->get_internal_log_table_name(); + $timefield = 'timecreated'; + $coursefield = 'courseid'; + $nonanonymous = 'AND anonymous = 0'; $params = array('userid' => $userid); $courseselect = ''; diff --git a/report/log/tests/lib_test.php b/report/log/tests/lib_test.php index 4ac092ed46a..722d1b9bb0b 100644 --- a/report/log/tests/lib_test.php +++ b/report/log/tests/lib_test.php @@ -67,7 +67,6 @@ class lib_test extends \advanced_testcase { $supportedstores = array( 'logstore_database' => '\logstore_database\log\store', - 'logstore_legacy' => '\logstore_legacy\log\store', 'logstore_standard' => '\logstore_standard\log\store' ); diff --git a/report/loglive/classes/table_log.php b/report/loglive/classes/table_log.php index 68a5bec38b3..b29951e62dc 100644 --- a/report/loglive/classes/table_log.php +++ b/report/loglive/classes/table_log.php @@ -230,13 +230,7 @@ class report_loglive_table_log extends table_sql { * @return string HTML for the event name column */ public function col_eventname($event) { - // Event name. - if ($this->filterparams->logreader instanceof logstore_legacy\log\store) { - // Hack for support of logstore_legacy. - $eventname = $event->eventname; - } else { - $eventname = $event->get_name(); - } + $eventname = $event->get_name(); if ($url = $event->get_url()) { $eventname = $this->action_link($url, $eventname, 'action'); } diff --git a/report/loglive/tests/lib_test.php b/report/loglive/tests/lib_test.php index d7e099ac39e..5698bfc75ac 100644 --- a/report/loglive/tests/lib_test.php +++ b/report/loglive/tests/lib_test.php @@ -42,8 +42,6 @@ class lib_test extends \advanced_testcase { $allstores = \core_component::get_plugin_list_with_class('logstore', 'log\store'); $supportedstores = array( - 'logstore_database' => '\logstore_legacy\log\database', - 'logstore_legacy' => '\logstore_legacy\log\store', 'logstore_standard' => '\logstore_standard\log\store' ); diff --git a/report/outline/lib.php b/report/outline/lib.php index 7e4cd42df3e..c4eadeef8d9 100644 --- a/report/outline/lib.php +++ b/report/outline/lib.php @@ -119,7 +119,7 @@ function report_outline_page_type_list($pagetype, $parentcontext, $currentcontex * @return bool returns true if the store is supported by the report, false otherwise. */ function report_outline_supports_logstore($instance) { - if ($instance instanceof \core\log\sql_internal_table_reader || $instance instanceof \logstore_legacy\log\store) { + if ($instance instanceof \core\log\sql_internal_table_reader) { return true; } return false; diff --git a/report/outline/locallib.php b/report/outline/locallib.php index 87067cddde6..fe523b1170c 100644 --- a/report/outline/locallib.php +++ b/report/outline/locallib.php @@ -82,11 +82,6 @@ function report_outline_get_common_log_variables() { // Get preferred reader. if (!empty($readers)) { foreach ($readers as $readerpluginname => $reader) { - // If legacy reader is preferred reader. - if ($readerpluginname == 'logstore_legacy') { - $uselegacyreader = true; - } - // If sql_internal_table_reader is preferred reader. if ($reader instanceof \core\log\sql_internal_table_reader) { $useinternalreader = true; diff --git a/report/outline/tests/behat/outline.feature b/report/outline/tests/behat/outline.feature index 6e6526ab248..775d1c00f9b 100644 --- a/report/outline/tests/behat/outline.feature +++ b/report/outline/tests/behat/outline.feature @@ -24,24 +24,6 @@ Feature: View an outline report | book | Book name | | C1 | book1 | When I am on the "Course 1" course page logged in as admin - Scenario: View the outline report when only the legacy log reader is enabled - Given I navigate to "Plugins > Logging > Manage log stores" in site administration - And I click on "Enable" "link" in the "Legacy log" "table_row" - And I click on "Disable" "link" in the "Standard log" "table_row" - And the following config values are set as admin: - | loglegacy | 1 | logstore_legacy | - And I am on the "Course 1" course page logged in as student1 - And I follow "Forum name" - And I am on "Course 1" course homepage - And I follow "Book name" - And I am on the "Course 1" course page logged in as student2 - And I follow "Book name" - And I am on the "Course 1" course page logged in as teacher1 - When I navigate to "Reports" in current page administration - And I click on "Activity report" "link" - Then I should see "2 views by 2 users" in the "Book name" "table_row" - And I should see "1 views by 1 users" in the "Forum name" "table_row" - Scenario: View the outline report when only the standard log reader is enabled Given I navigate to "Plugins > Logging > Manage log stores" in site administration And "Enable" "link" should exist in the "Legacy log" "table_row" diff --git a/report/outline/tests/behat/user.feature b/report/outline/tests/behat/user.feature index dc08edcfd55..0f1631bc98c 100644 --- a/report/outline/tests/behat/user.feature +++ b/report/outline/tests/behat/user.feature @@ -24,36 +24,6 @@ Feature: View the user page for the outline report | url | URL name | URL description | C1 | folder1 | http://www.google.com | When I log in as "admin" - Scenario: View the user page when only the legacy log reader is enabled - Given I navigate to "Plugins > Logging > Manage log stores" in site administration - And I click on "Enable" "link" in the "Legacy log" "table_row" - And I click on "Disable" "link" in the "Standard log" "table_row" - And the following config values are set as admin: - | loglegacy | 1 | logstore_legacy | - And I log out - And I log in as "student1" - And I am on "Course 1" course homepage - # We want to view this multiple times, to make sure the count is working. - And I follow "Folder name" - And I reload the page - And I reload the page - And I reload the page - # We want to view this multiple times, to make sure the count is working. - And I am on "Course 1" course homepage - And I follow "URL name" - And I reload the page - And I reload the page - And I follow "Profile" in the user menu - And I click on "Course 1" "link" in the "region-main" "region" - When I follow "Outline report" - Then I should see "4 views" in the "Folder name" "table_row" - And I should see "3 views" in the "URL name" "table_row" - And I follow "Profile" in the user menu - And I click on "Course 1" "link" in the "region-main" "region" - And I follow "Complete report" - And I should see "4 views" - And I should see "3 views" - Scenario: View the user page when only the standard log reader is enabled Given I navigate to "Plugins > Logging > Manage log stores" in site administration And "Enable" "link" should exist in the "Legacy log" "table_row" diff --git a/report/outline/tests/lib_test.php b/report/outline/tests/lib_test.php index 71168530438..ecd938e57d9 100644 --- a/report/outline/tests/lib_test.php +++ b/report/outline/tests/lib_test.php @@ -79,7 +79,6 @@ class lib_test extends \advanced_testcase { $allstores = \core_component::get_plugin_list_with_class('logstore', 'log\store'); $supportedstores = array( - 'logstore_legacy' => '\logstore_legacy\log\store', 'logstore_standard' => '\logstore_standard\log\store' ); diff --git a/report/participation/lib.php b/report/participation/lib.php index 75d4904902a..4763b3a6c49 100644 --- a/report/participation/lib.php +++ b/report/participation/lib.php @@ -65,7 +65,7 @@ function report_participation_page_type_list($pagetype, $parentcontext, $current * @return bool returns true if the store is supported by the report, false otherwise. */ function report_participation_supports_logstore($instance) { - if ($instance instanceof \core\log\sql_internal_table_reader || $instance instanceof \logstore_legacy\log\store) { + if ($instance instanceof \core\log\sql_internal_table_reader) { return true; } return false; diff --git a/report/participation/locallib.php b/report/participation/locallib.php index 8ab59b47a9b..45b9d31320c 100644 --- a/report/participation/locallib.php +++ b/report/participation/locallib.php @@ -38,11 +38,6 @@ function report_participation_get_log_table_name() { // Get preferred reader. if (!empty($readers)) { foreach ($readers as $readerpluginname => $reader) { - // If legacy reader is preferred reader. - if ($readerpluginname == 'logstore_legacy') { - break; - } - // If sql_internal_table_reader is preferred reader. if ($reader instanceof \core\log\sql_internal_table_reader) { $logtable = $reader->get_internal_log_table_name(); diff --git a/report/participation/tests/behat/filter_participation.feature b/report/participation/tests/behat/filter_participation.feature index ff36a51c749..e306dd8f756 100644 --- a/report/participation/tests/behat/filter_participation.feature +++ b/report/participation/tests/behat/filter_participation.feature @@ -26,25 +26,6 @@ Feature: In a participation report, admin can filter student actions | title | Test chapter | | content | Test chapter content | - @javascript - Scenario: Filter participation report when only legacy log reader is enabled - Given I log in as "admin" - And I navigate to "Plugins > Logging > Manage log stores" in site administration - And I click on "Disable" "link" in the "Standard log" "table_row" - And I click on "Enable" "link" in the "Legacy log" "table_row" - And the following config values are set as admin: - | loglegacy | 1 | logstore_legacy | - - And I am on the "Test book name" "book activity" page logged in as student1 - - When I am on the "Course 1" course page logged in as admin - When I navigate to "Reports" in current page administration - And I click on "Course participation" "link" - And I set the field "instanceid" to "Test book name" - And I set the field "roleid" to "Student" - And I press "Go" - Then I should see "Yes (1)" - @javascript Scenario: Filter participation report when standard log reader is enabled later Given I log in as "admin" diff --git a/report/participation/tests/lib_test.php b/report/participation/tests/lib_test.php index acbecd89b66..fd4cc371e2d 100644 --- a/report/participation/tests/lib_test.php +++ b/report/participation/tests/lib_test.php @@ -42,7 +42,6 @@ class lib_test extends \advanced_testcase { $allstores = \core_component::get_plugin_list_with_class('logstore', 'log\store'); $supportedstores = array( - 'logstore_legacy' => '\logstore_legacy\log\store', 'logstore_standard' => '\logstore_standard\log\store' ); diff --git a/report/stats/lib.php b/report/stats/lib.php index aec2a9d6f04..8cc3f6c8b98 100644 --- a/report/stats/lib.php +++ b/report/stats/lib.php @@ -126,7 +126,7 @@ function report_stats_page_type_list($pagetype, $parentcontext, $currentcontext) * @return bool returns true if the store is supported by the report, false otherwise. */ function report_stats_supports_logstore($instance) { - if ($instance instanceof \core\log\sql_internal_table_reader || $instance instanceof \logstore_legacy\log\store) { + if ($instance instanceof \core\log\sql_internal_table_reader) { return true; } return false; diff --git a/report/stats/tests/lib_test.php b/report/stats/tests/lib_test.php index 77c0e86c5f1..0da9f424606 100644 --- a/report/stats/tests/lib_test.php +++ b/report/stats/tests/lib_test.php @@ -64,7 +64,6 @@ class lib_test extends \advanced_testcase { $allstores = \core_component::get_plugin_list_with_class('logstore', 'log\store'); $supportedstores = array( - 'logstore_legacy' => '\logstore_legacy\log\store', 'logstore_standard' => '\logstore_standard\log\store' );