Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]

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