AutorÃa | Ultima modificación | Ver Log |
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* External database store.
*
* @package logstore_database
* @copyright 2013 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace logstore_database\log;
defined('MOODLE_INTERNAL') || die();
class store implements \tool_log\log\writer, \core\log\sql_reader {
use \tool_log\helper\store,
\tool_log\helper\reader,
\tool_log\helper\buffered_writer {
dispose as helper_dispose;
}
/** @var \moodle_database $extdb */
protected $extdb;
/** @var bool $logguests true if logging guest access */
protected $logguests;
/** @var array $includelevels An array of education levels to include */
protected $includelevels = array();
/** @var array $includeactions An array of actions types to include */
protected $includeactions = array();
/**
* Construct
*
* @param \tool_log\log\manager $manager
*/
public function __construct(\tool_log\log\manager $manager) {
$this->helper_setup($manager);
$this->buffersize = $this->get_config('buffersize', 50);
$this->logguests = $this->get_config('logguests', 1);
$actions = $this->get_config('includeactions', '');
$levels = $this->get_config('includelevels', '');
$this->includeactions = $actions === '' ? array() : explode(',', $actions);
$this->includelevels = $levels === '' ? array() : explode(',', $levels);
// JSON writing defaults to false (table format compatibility with older versions).
// Note: This variable is defined in the buffered_writer trait.
$this->jsonformat = (bool)$this->get_config('jsonformat', false);
}
/**
* Setup the Database.
*
* @return bool
*/
protected function init() {
if (isset($this->extdb)) {
return !empty($this->extdb);
}
$dbdriver = $this->get_config('dbdriver');
if (empty($dbdriver)) {
$this->extdb = false;
return false;
}
list($dblibrary, $dbtype) = explode('/', $dbdriver);
if (!$db = \moodle_database::get_driver_instance($dbtype, $dblibrary, true)) {
debugging("Unknown driver $dblibrary/$dbtype", DEBUG_DEVELOPER);
$this->extdb = false;
return false;
}
$dboptions = array();
$dboptions['dbpersist'] = $this->get_config('dbpersist', '0');
$dboptions['dbsocket'] = $this->get_config('dbsocket', '');
$dboptions['dbport'] = $this->get_config('dbport', '');
$dboptions['dbschema'] = $this->get_config('dbschema', '');
$dboptions['dbcollation'] = $this->get_config('dbcollation', '');
$dboptions['dbhandlesoptions'] = $this->get_config('dbhandlesoptions', false);
try {
$db->connect($this->get_config('dbhost'), $this->get_config('dbuser'), $this->get_config('dbpass'),
$this->get_config('dbname'), false, $dboptions);
$tables = $db->get_tables();
if (!in_array($this->get_config('dbtable'), $tables)) {
debugging('Cannot find the specified table', DEBUG_DEVELOPER);
$this->extdb = false;
return false;
}
} catch (\moodle_exception $e) {
debugging('Cannot connect to external database: ' . $e->getMessage(), DEBUG_DEVELOPER);
$this->extdb = false;
return false;
}
$this->extdb = $db;
return true;
}
/**
* Should the event be ignored (== not logged)?
* @param \core\event\base $event
* @return bool
*/
protected function is_event_ignored(\core\event\base $event) {
if (!in_array($event->crud, $this->includeactions) &&
!in_array($event->edulevel, $this->includelevels)
) {
// Ignore event if the store settings do not want to store it.
return true;
}
if ((!CLI_SCRIPT or PHPUNIT_TEST) and !$this->logguests) {
// Always log inside CLI scripts because we do not login there.
if (!isloggedin() or isguestuser()) {
return true;
}
}
return false;
}
/**
* Insert events in bulk to the database.
*
* @param array $evententries raw event data
*/
protected function insert_event_entries($evententries) {
if (!$this->init()) {
return;
}
if (!$dbtable = $this->get_config('dbtable')) {
return;
}
try {
$this->extdb->insert_records($dbtable, $evententries);
} catch (\moodle_exception $e) {
debugging('Cannot write to external database: ' . $e->getMessage(), DEBUG_DEVELOPER);
}
}
/**
* Get an array of events based on the passed on params.
*
* @param string $selectwhere select conditions.
* @param array $params params.
* @param string $sort sortorder.
* @param int $limitfrom limit constraints.
* @param int $limitnum limit constraints.
*
* @return array|\core\event\base[] array of events.
*/
public function get_events_select($selectwhere, array $params, $sort, $limitfrom, $limitnum) {
if (!$this->init()) {
return array();
}
if (!$dbtable = $this->get_config('dbtable')) {
return array();
}
$sort = self::tweak_sort_by_id($sort);
$events = array();
$records = $this->extdb->get_records_select($dbtable, $selectwhere, $params, $sort, '*', $limitfrom, $limitnum);
foreach ($records as $data) {
if ($event = $this->get_log_event($data)) {
$events[$data->id] = $event;
}
}
return $events;
}
/**
* Fetch records using given criteria returning a Traversable object.
*
* 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 \core\dml\recordset_walk|\core\event\base[]
*/
public function get_events_select_iterator($selectwhere, array $params, $sort, $limitfrom, $limitnum) {
if (!$this->init()) {
return array();
}
if (!$dbtable = $this->get_config('dbtable')) {
return array();
}
$sort = self::tweak_sort_by_id($sort);
$recordset = $this->extdb->get_recordset_select($dbtable, $selectwhere, $params, $sort, '*', $limitfrom, $limitnum);
return new \core\dml\recordset_walk($recordset, array($this, 'get_log_event'));
}
/**
* Returns an event from the log data.
*
* @param stdClass $data Log data
* @return \core\event\base
*/
public function get_log_event($data) {
$extra = array('origin' => $data->origin, 'ip' => $data->ip, 'realuserid' => $data->realuserid);
$data = (array)$data;
$id = $data['id'];
$data['other'] = self::decode_other($data['other']);
if ($data['other'] === false) {
$data['other'] = array();
}
unset($data['origin']);
unset($data['ip']);
unset($data['realuserid']);
unset($data['id']);
if (!$event = \core\event\base::restore($data, $extra)) {
return null;
}
return $event;
}
/**
* Get number of events present for the given select clause.
*
* @param string $selectwhere select conditions.
* @param array $params params.
*
* @return int Number of events available for the given conditions
*/
public function get_events_select_count($selectwhere, array $params) {
if (!$this->init()) {
return 0;
}
if (!$dbtable = $this->get_config('dbtable')) {
return 0;
}
return $this->extdb->count_records_select($dbtable, $selectwhere, $params);
}
/**
* Get whether events are present for the given select clause.
*
* @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 {
if (!$this->init()) {
return false;
}
if (!$dbtable = $this->get_config('dbtable')) {
return false;
}
return $this->extdb->record_exists_select($dbtable, $selectwhere, $params);
}
/**
* Get a config value for the store.
*
* @param string $name Config name
* @param mixed $default default value
* @return mixed config value if set, else the default value.
*/
public function get_config_value($name, $default = null) {
return $this->get_config($name, $default);
}
/**
* Get the external database object.
*
* @return \moodle_database $extdb
*/
public function get_extdb() {
if (!$this->init()) {
return false;
}
return $this->extdb;
}
/**
* Are the new events appearing in the reader?
*
* @return bool true means new log events are being added, false means no new data will be added
*/
public function is_logging() {
if (!$this->init()) {
return false;
}
return true;
}
/**
* Dispose off database connection after pushing any buffered events to the database.
*/
public function dispose() {
$this->helper_dispose();
if ($this->extdb) {
$this->extdb->dispose();
}
$this->extdb = null;
}
}