Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 39 and 401]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  namespace logstore_database;
  18  
  19  defined('MOODLE_INTERNAL') || die();
  20  
  21  require_once (__DIR__ . '/fixtures/event.php');
  22  require_once (__DIR__ . '/fixtures/store.php');
  23  
  24  /**
  25   * External database log store tests.
  26   *
  27   * @package    logstore_database
  28   * @copyright  2014 Petr Skoda {@link http://skodak.org/}
  29   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  30   */
  31  class store_test extends \advanced_testcase {
  32      /**
  33       * Tests log writing.
  34       *
  35       * @param bool $jsonformat True to test with JSON format
  36       * @dataProvider log_writing_provider
  37       */
  38      public function test_log_writing(bool $jsonformat) {
  39          global $DB, $CFG;
  40          $this->resetAfterTest();
  41          $this->preventResetByRollback(); // Logging waits till the transaction gets committed.
  42  
  43          // Apply JSON format system setting.
  44          set_config('jsonformat', $jsonformat ? 1 : 0, 'logstore_database');
  45  
  46          $dbman = $DB->get_manager();
  47          $this->assertTrue($dbman->table_exists('logstore_standard_log'));
  48          $DB->delete_records('logstore_standard_log');
  49  
  50          $this->setAdminUser();
  51          $user1 = $this->getDataGenerator()->create_user();
  52          $user2 = $this->getDataGenerator()->create_user();
  53          $course1 = $this->getDataGenerator()->create_course();
  54          $module1 = $this->getDataGenerator()->create_module('resource', array('course' => $course1));
  55          $course2 = $this->getDataGenerator()->create_course();
  56          $module2 = $this->getDataGenerator()->create_module('resource', array('course' => $course2));
  57  
  58          // Test all plugins are disabled by this command.
  59          set_config('enabled_stores', '', 'tool_log');
  60          $manager = get_log_manager(true);
  61          $stores = $manager->get_readers();
  62          $this->assertCount(0, $stores);
  63  
  64          // Fake the settings, we will abuse the standard plugin table here...
  65          set_config('dbdriver', $CFG->dblibrary . '/' . $CFG->dbtype, 'logstore_database');
  66          set_config('dbhost', $CFG->dbhost, 'logstore_database');
  67          set_config('dbuser', $CFG->dbuser, 'logstore_database');
  68          set_config('dbpass', $CFG->dbpass, 'logstore_database');
  69          set_config('dbname', $CFG->dbname, 'logstore_database');
  70          set_config('dbtable', $CFG->prefix . 'logstore_standard_log', 'logstore_database');
  71          if (!empty($CFG->dboptions['dbpersist'])) {
  72              set_config('dbpersist', 1, 'logstore_database');
  73          } else {
  74              set_config('dbpersist', 0, 'logstore_database');
  75          }
  76          if (!empty($CFG->dboptions['dbsocket'])) {
  77              set_config('dbsocket', $CFG->dboptions['dbsocket'], 'logstore_database');
  78          } else {
  79              set_config('dbsocket', '', 'logstore_database');
  80          }
  81          if (!empty($CFG->dboptions['dbport'])) {
  82              set_config('dbport', $CFG->dboptions['dbport'], 'logstore_database');
  83          } else {
  84              set_config('dbport', '', 'logstore_database');
  85          }
  86          if (!empty($CFG->dboptions['dbschema'])) {
  87              set_config('dbschema', $CFG->dboptions['dbschema'], 'logstore_database');
  88          } else {
  89              set_config('dbschema', '', 'logstore_database');
  90          }
  91          if (!empty($CFG->dboptions['dbcollation'])) {
  92              set_config('dbcollation', $CFG->dboptions['dbcollation'], 'logstore_database');
  93          } else {
  94              set_config('dbcollation', '', 'logstore_database');
  95          }
  96          if (!empty($CFG->dboptions['dbhandlesoptions'])) {
  97              set_config('dbhandlesoptions', $CFG->dboptions['dbhandlesoptions'], 'logstore_database');
  98          } else {
  99              set_config('dbhandlesoptions', false, 'logstore_database');
 100          }
 101  
 102          // Enable logging plugin.
 103          set_config('enabled_stores', 'logstore_database', 'tool_log');
 104          set_config('buffersize', 0, 'logstore_database');
 105          set_config('logguests', 1, 'logstore_database');
 106          $manager = get_log_manager(true);
 107  
 108          $stores = $manager->get_readers();
 109          $this->assertCount(1, $stores);
 110          $this->assertEquals(array('logstore_database'), array_keys($stores));
 111          $store = $stores['logstore_database'];
 112          $this->assertInstanceOf('logstore_database\log\store', $store);
 113          $this->assertInstanceOf('tool_log\log\writer', $store);
 114          $this->assertTrue($store->is_logging());
 115  
 116          $logs = $DB->get_records('logstore_standard_log', array(), 'id ASC');
 117          $this->assertCount(0, $logs);
 118  
 119          $this->setCurrentTimeStart();
 120  
 121          $this->setUser(0);
 122          $event1 = \logstore_database\event\unittest_executed::create(
 123              array('context' => \context_module::instance($module1->cmid), 'other' => array('sample' => 5, 'xx' => 10)));
 124          $event1->trigger();
 125  
 126          $logs = $DB->get_records('logstore_standard_log', array(), 'id ASC');
 127          $this->assertCount(1, $logs);
 128  
 129          $log1 = reset($logs);
 130          unset($log1->id);
 131          if ($jsonformat) {
 132              $log1->other = json_decode($log1->other, true);
 133          } else {
 134              $log1->other = unserialize($log1->other);
 135          }
 136          $log1 = (array)$log1;
 137          $data = $event1->get_data();
 138          $data['origin'] = 'cli';
 139          $data['ip'] = null;
 140          $data['realuserid'] = null;
 141          $this->assertEquals($data, $log1);
 142  
 143          $this->setAdminUser();
 144          \core\session\manager::loginas($user1->id, \context_system::instance());
 145          $this->assertEquals(2, $DB->count_records('logstore_standard_log'));
 146  
 147          $event2 = \logstore_database\event\unittest_executed::create(
 148              array('context' => \context_module::instance($module2->cmid), 'other' => array('sample' => 6, 'xx' => 9)));
 149          $event2->trigger();
 150  
 151          \core\session\manager::init_empty_session();
 152          $this->assertFalse(\core\session\manager::is_loggedinas());
 153  
 154          $logs = $DB->get_records('logstore_standard_log', array(), 'id ASC');
 155          $this->assertCount(3, $logs);
 156          array_shift($logs);
 157          $log2 = array_shift($logs);
 158          $this->assertSame('\core\event\user_loggedinas', $log2->eventname);
 159  
 160          $log3 = array_shift($logs);
 161          unset($log3->id);
 162          if ($jsonformat) {
 163              $log3->other = json_decode($log3->other, true);
 164          } else {
 165              $log3->other = unserialize($log3->other);
 166          }
 167          $log3 = (array)$log3;
 168          $data = $event2->get_data();
 169          $data['origin'] = 'cli';
 170          $data['ip'] = null;
 171          $data['realuserid'] = 2;
 172          $this->assertEquals($data, $log3);
 173  
 174          // Test reading.
 175          $this->assertSame(3, $store->get_events_select_count('', array()));
 176          $events = $store->get_events_select('', array(), 'timecreated ASC', 0, 0); // Is actually sorted by "timecreated ASC, id ASC".
 177          $this->assertCount(3, $events);
 178          $resev1 = array_shift($events);
 179          array_shift($events);
 180          $resev2 = array_shift($events);
 181          $this->assertEquals($event1->get_data(), $resev1->get_data());
 182          $this->assertEquals($event2->get_data(), $resev2->get_data());
 183  
 184          // Test buffering.
 185          set_config('buffersize', 3, 'logstore_database');
 186          $manager = get_log_manager(true);
 187          $stores = $manager->get_readers();
 188          /** @var \logstore_database\log\store $store */
 189          $store = $stores['logstore_database'];
 190          $DB->delete_records('logstore_standard_log');
 191  
 192          \logstore_database\event\unittest_executed::create(
 193              array('context' => \context_module::instance($module1->cmid), 'other' => array('sample' => 5, 'xx' => 10)))->trigger();
 194          $this->assertEquals(0, $DB->count_records('logstore_standard_log'));
 195          \logstore_database\event\unittest_executed::create(
 196              array('context' => \context_module::instance($module1->cmid), 'other' => array('sample' => 5, 'xx' => 10)))->trigger();
 197          $this->assertEquals(0, $DB->count_records('logstore_standard_log'));
 198          $store->flush();
 199          $this->assertEquals(2, $DB->count_records('logstore_standard_log'));
 200          \logstore_database\event\unittest_executed::create(
 201              array('context' => \context_module::instance($module1->cmid), 'other' => array('sample' => 5, 'xx' => 10)))->trigger();
 202          $this->assertEquals(2, $DB->count_records('logstore_standard_log'));
 203          \logstore_database\event\unittest_executed::create(
 204              array('context' => \context_module::instance($module1->cmid), 'other' => array('sample' => 5, 'xx' => 10)))->trigger();
 205          $this->assertEquals(2, $DB->count_records('logstore_standard_log'));
 206          \logstore_database\event\unittest_executed::create(
 207              array('context' => \context_module::instance($module1->cmid), 'other' => array('sample' => 5, 'xx' => 10)))->trigger();
 208          $this->assertEquals(5, $DB->count_records('logstore_standard_log'));
 209          \logstore_database\event\unittest_executed::create(
 210              array('context' => \context_module::instance($module1->cmid), 'other' => array('sample' => 5, 'xx' => 10)))->trigger();
 211          $this->assertEquals(5, $DB->count_records('logstore_standard_log'));
 212          \logstore_database\event\unittest_executed::create(
 213              array('context' => \context_module::instance($module1->cmid), 'other' => array('sample' => 5, 'xx' => 10)))->trigger();
 214          $this->assertEquals(5, $DB->count_records('logstore_standard_log'));
 215          \logstore_database\event\unittest_executed::create(
 216              array('context' => \context_module::instance($module1->cmid), 'other' => array('sample' => 5, 'xx' => 10)))->trigger();
 217          $this->assertEquals(8, $DB->count_records('logstore_standard_log'));
 218  
 219          // Test guest logging setting.
 220          set_config('logguests', 0, 'logstore_database');
 221          set_config('buffersize', 0, 'logstore_database');
 222          get_log_manager(true);
 223          $DB->delete_records('logstore_standard_log');
 224          get_log_manager(true);
 225  
 226          $this->setUser(null);
 227          \logstore_database\event\unittest_executed::create(
 228              array('context' => \context_module::instance($module1->cmid), 'other' => array('sample' => 5, 'xx' => 10)))->trigger();
 229          $this->assertEquals(0, $DB->count_records('logstore_standard_log'));
 230  
 231          $this->setGuestUser();
 232          \logstore_database\event\unittest_executed::create(
 233              array('context' => \context_module::instance($module1->cmid), 'other' => array('sample' => 5, 'xx' => 10)))->trigger();
 234          $this->assertEquals(0, $DB->count_records('logstore_standard_log'));
 235  
 236          $this->setUser($user1);
 237          \logstore_database\event\unittest_executed::create(
 238              array('context' => \context_module::instance($module1->cmid), 'other' => array('sample' => 5, 'xx' => 10)))->trigger();
 239          $this->assertEquals(1, $DB->count_records('logstore_standard_log'));
 240  
 241          $this->setUser($user2);
 242          \logstore_database\event\unittest_executed::create(
 243              array('context' => \context_module::instance($module1->cmid), 'other' => array('sample' => 5, 'xx' => 10)))->trigger();
 244          $this->assertEquals(2, $DB->count_records('logstore_standard_log'));
 245  
 246          set_config('enabled_stores', '', 'tool_log');
 247          get_log_manager(true);
 248      }
 249  
 250      /**
 251       * Returns different JSON format settings so the test can be run with JSON format either on or
 252       * off.
 253       *
 254       * @return bool[] Array of true/false
 255       */
 256      public static function log_writing_provider(): array {
 257          return [
 258              [false],
 259              [true]
 260          ];
 261      }
 262  
 263      /**
 264       * Test method is_event_ignored.
 265       */
 266      public function test_is_event_ignored() {
 267          $this->resetAfterTest();
 268  
 269          // Test guest filtering.
 270          set_config('logguests', 0, 'logstore_database');
 271          $this->setGuestUser();
 272          $event = \logstore_database\event\unittest_executed::create(
 273                  array('context' => \context_system::instance(), 'other' => array('sample' => 5, 'xx' => 10)));
 274          $logmanager = get_log_manager();
 275          $store = new \logstore_database\test\store($logmanager);
 276          $this->assertTrue($store->is_event_ignored($event));
 277  
 278          set_config('logguests', 1, 'logstore_database');
 279          $store = new \logstore_database\test\store($logmanager); // Reload.
 280          $this->assertFalse($store->is_event_ignored($event));
 281  
 282          // Test action/level filtering.
 283          set_config('includelevels', '', 'logstore_database');
 284          set_config('includeactions', '', 'logstore_database');
 285          $store = new \logstore_database\test\store($logmanager); // Reload.
 286          $this->assertTrue($store->is_event_ignored($event));
 287  
 288          set_config('includelevels', '0,1', 'logstore_database');
 289          $store = new \logstore_database\test\store($logmanager); // Reload.
 290          $this->assertTrue($store->is_event_ignored($event));
 291  
 292          set_config('includelevels', '0,1,2', 'logstore_database');
 293          $store = new \logstore_database\test\store($logmanager); // Reload.
 294          $this->assertFalse($store->is_event_ignored($event));
 295  
 296          set_config('includelevels', '', 'logstore_database');
 297          set_config('includeactions', 'c,r,d', 'logstore_database');
 298          $store = new \logstore_database\test\store($logmanager); // Reload.
 299          $this->assertTrue($store->is_event_ignored($event));
 300  
 301          set_config('includeactions', 'c,r,u,d', 'logstore_database');
 302          $store = new \logstore_database\test\store($logmanager); // Reload.
 303          $this->assertFalse($store->is_event_ignored($event));
 304      }
 305  
 306      /**
 307       * Test logmanager::get_supported_reports returns all reports that require this store.
 308       */
 309      public function test_get_supported_reports() {
 310          $logmanager = get_log_manager();
 311          $allreports = \core_component::get_plugin_list('report');
 312  
 313          // Make sure all supported reports are installed.
 314          $expectedreports = array_intersect_key([
 315              'log' => 'report_log',
 316              'loglive' => 'report_loglive',
 317          ], $allreports);
 318  
 319          $supportedreports = $logmanager->get_supported_reports('logstore_database');
 320  
 321          foreach ($expectedreports as $expectedreport) {
 322              $this->assertArrayHasKey($expectedreport, $supportedreports);
 323          }
 324      }
 325  }