Differences Between: [Versions 311 and 401] [Versions 311 and 402] [Versions 311 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 store. 19 * 20 * @package logstore_database 21 * @copyright 2013 Petr Skoda {@link http://skodak.org} 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace logstore_database\log; 26 defined('MOODLE_INTERNAL') || die(); 27 28 class store implements \tool_log\log\writer, \core\log\sql_reader { 29 use \tool_log\helper\store, 30 \tool_log\helper\reader, 31 \tool_log\helper\buffered_writer { 32 dispose as helper_dispose; 33 } 34 35 /** @var \moodle_database $extdb */ 36 protected $extdb; 37 38 /** @var bool $logguests true if logging guest access */ 39 protected $logguests; 40 41 /** @var array $includelevels An array of education levels to include */ 42 protected $includelevels = array(); 43 44 /** @var array $includeactions An array of actions types to include */ 45 protected $includeactions = array(); 46 47 /** 48 * Construct 49 * 50 * @param \tool_log\log\manager $manager 51 */ 52 public function __construct(\tool_log\log\manager $manager) { 53 $this->helper_setup($manager); 54 $this->buffersize = $this->get_config('buffersize', 50); 55 $this->logguests = $this->get_config('logguests', 1); 56 $actions = $this->get_config('includeactions', ''); 57 $levels = $this->get_config('includelevels', ''); 58 $this->includeactions = $actions === '' ? array() : explode(',', $actions); 59 $this->includelevels = $levels === '' ? array() : explode(',', $levels); 60 // JSON writing defaults to false (table format compatibility with older versions). 61 // Note: This variable is defined in the buffered_writer trait. 62 $this->jsonformat = (bool)$this->get_config('jsonformat', false); 63 } 64 65 /** 66 * Setup the Database. 67 * 68 * @return bool 69 */ 70 protected function init() { 71 if (isset($this->extdb)) { 72 return !empty($this->extdb); 73 } 74 75 $dbdriver = $this->get_config('dbdriver'); 76 if (empty($dbdriver)) { 77 $this->extdb = false; 78 return false; 79 } 80 list($dblibrary, $dbtype) = explode('/', $dbdriver); 81 82 if (!$db = \moodle_database::get_driver_instance($dbtype, $dblibrary, true)) { 83 debugging("Unknown driver $dblibrary/$dbtype", DEBUG_DEVELOPER); 84 $this->extdb = false; 85 return false; 86 } 87 88 $dboptions = array(); 89 $dboptions['dbpersist'] = $this->get_config('dbpersist', '0'); 90 $dboptions['dbsocket'] = $this->get_config('dbsocket', ''); 91 $dboptions['dbport'] = $this->get_config('dbport', ''); 92 $dboptions['dbschema'] = $this->get_config('dbschema', ''); 93 $dboptions['dbcollation'] = $this->get_config('dbcollation', ''); 94 $dboptions['dbhandlesoptions'] = $this->get_config('dbhandlesoptions', false); 95 try { 96 $db->connect($this->get_config('dbhost'), $this->get_config('dbuser'), $this->get_config('dbpass'), 97 $this->get_config('dbname'), false, $dboptions); 98 $tables = $db->get_tables(); 99 if (!in_array($this->get_config('dbtable'), $tables)) { 100 debugging('Cannot find the specified table', DEBUG_DEVELOPER); 101 $this->extdb = false; 102 return false; 103 } 104 } catch (\moodle_exception $e) { 105 debugging('Cannot connect to external database: ' . $e->getMessage(), DEBUG_DEVELOPER); 106 $this->extdb = false; 107 return false; 108 } 109 110 $this->extdb = $db; 111 return true; 112 } 113 114 /** 115 * Should the event be ignored (== not logged)? 116 * @param \core\event\base $event 117 * @return bool 118 */ 119 protected function is_event_ignored(\core\event\base $event) { 120 if (!in_array($event->crud, $this->includeactions) && 121 !in_array($event->edulevel, $this->includelevels) 122 ) { 123 // Ignore event if the store settings do not want to store it. 124 return true; 125 } 126 if ((!CLI_SCRIPT or PHPUNIT_TEST) and !$this->logguests) { 127 // Always log inside CLI scripts because we do not login there. 128 if (!isloggedin() or isguestuser()) { 129 return true; 130 } 131 } 132 return false; 133 } 134 135 /** 136 * Insert events in bulk to the database. 137 * 138 * @param array $evententries raw event data 139 */ 140 protected function insert_event_entries($evententries) { 141 if (!$this->init()) { 142 return; 143 } 144 if (!$dbtable = $this->get_config('dbtable')) { 145 return; 146 } 147 try { 148 $this->extdb->insert_records($dbtable, $evententries); 149 } catch (\moodle_exception $e) { 150 debugging('Cannot write to external database: ' . $e->getMessage(), DEBUG_DEVELOPER); 151 } 152 } 153 154 /** 155 * Get an array of events based on the passed on params. 156 * 157 * @param string $selectwhere select conditions. 158 * @param array $params params. 159 * @param string $sort sortorder. 160 * @param int $limitfrom limit constraints. 161 * @param int $limitnum limit constraints. 162 * 163 * @return array|\core\event\base[] array of events. 164 */ 165 public function get_events_select($selectwhere, array $params, $sort, $limitfrom, $limitnum) { 166 if (!$this->init()) { 167 return array(); 168 } 169 170 if (!$dbtable = $this->get_config('dbtable')) { 171 return array(); 172 } 173 174 $sort = self::tweak_sort_by_id($sort); 175 176 $events = array(); 177 $records = $this->extdb->get_records_select($dbtable, $selectwhere, $params, $sort, '*', $limitfrom, $limitnum); 178 179 foreach ($records as $data) { 180 if ($event = $this->get_log_event($data)) { 181 $events[$data->id] = $event; 182 } 183 } 184 185 return $events; 186 } 187 188 /** 189 * Fetch records using given criteria returning a Traversable object. 190 * 191 * Note that the traversable object contains a moodle_recordset, so 192 * remember that is important that you call close() once you finish 193 * using it. 194 * 195 * @param string $selectwhere 196 * @param array $params 197 * @param string $sort 198 * @param int $limitfrom 199 * @param int $limitnum 200 * @return \core\dml\recordset_walk|\core\event\base[] 201 */ 202 public function get_events_select_iterator($selectwhere, array $params, $sort, $limitfrom, $limitnum) { 203 if (!$this->init()) { 204 return array(); 205 } 206 207 if (!$dbtable = $this->get_config('dbtable')) { 208 return array(); 209 } 210 211 $sort = self::tweak_sort_by_id($sort); 212 213 $recordset = $this->extdb->get_recordset_select($dbtable, $selectwhere, $params, $sort, '*', $limitfrom, $limitnum); 214 215 return new \core\dml\recordset_walk($recordset, array($this, 'get_log_event')); 216 } 217 218 /** 219 * Returns an event from the log data. 220 * 221 * @param stdClass $data Log data 222 * @return \core\event\base 223 */ 224 public function get_log_event($data) { 225 226 $extra = array('origin' => $data->origin, 'ip' => $data->ip, 'realuserid' => $data->realuserid); 227 $data = (array)$data; 228 $id = $data['id']; 229 $data['other'] = self::decode_other($data['other']); 230 if ($data['other'] === false) { 231 $data['other'] = array(); 232 } 233 unset($data['origin']); 234 unset($data['ip']); 235 unset($data['realuserid']); 236 unset($data['id']); 237 238 if (!$event = \core\event\base::restore($data, $extra)) { 239 return null; 240 } 241 242 return $event; 243 } 244 245 /** 246 * Get number of events present for the given select clause. 247 * 248 * @param string $selectwhere select conditions. 249 * @param array $params params. 250 * 251 * @return int Number of events available for the given conditions 252 */ 253 public function get_events_select_count($selectwhere, array $params) { 254 if (!$this->init()) { 255 return 0; 256 } 257 258 if (!$dbtable = $this->get_config('dbtable')) { 259 return 0; 260 } 261 262 return $this->extdb->count_records_select($dbtable, $selectwhere, $params); 263 } 264 265 /** 266 * Get a config value for the store. 267 * 268 * @param string $name Config name 269 * @param mixed $default default value 270 * @return mixed config value if set, else the default value. 271 */ 272 public function get_config_value($name, $default = null) { 273 return $this->get_config($name, $default); 274 } 275 276 /** 277 * Get the external database object. 278 * 279 * @return \moodle_database $extdb 280 */ 281 public function get_extdb() { 282 if (!$this->init()) { 283 return false; 284 } 285 286 return $this->extdb; 287 } 288 289 /** 290 * Are the new events appearing in the reader? 291 * 292 * @return bool true means new log events are being added, false means no new data will be added 293 */ 294 public function is_logging() { 295 if (!$this->init()) { 296 return false; 297 } 298 return true; 299 } 300 301 /** 302 * Dispose off database connection after pushing any buffered events to the database. 303 */ 304 public function dispose() { 305 $this->helper_dispose(); 306 if ($this->extdb) { 307 $this->extdb->dispose(); 308 } 309 $this->extdb = null; 310 } 311 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body