[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
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 * Table log for displaying logs. 19 * 20 * @package report_log 21 * @copyright 2014 Rajesh Taneja <[email protected]> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die; 26 27 /** 28 * Table log class for displaying logs. 29 * 30 * @package report_log 31 * @copyright 2014 Rajesh Taneja <[email protected]> 32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 */ 34 class report_log_table_log extends table_sql { 35 36 /** @var array list of user fullnames shown in report */ 37 private $userfullnames = array(); 38 39 /** @var array list of course short names shown in report */ 40 private $courseshortnames = array(); 41 42 /** @var array list of context name shown in report */ 43 private $contextname = array(); 44 45 /** @var stdClass filters parameters */ 46 private $filterparams; 47 48 /** 49 * Sets up the table_log parameters. 50 * 51 * @param string $uniqueid unique id of form. 52 * @param stdClass $filterparams (optional) filter params. 53 * - int courseid: id of course 54 * - int userid: user id 55 * - int|string modid: Module id or "site_errors" to view site errors 56 * - int groupid: Group id 57 * - \core\log\sql_select_reader logreader: reader from which data will be fetched. 58 * - int edulevel: educational level. 59 * - string action: view action 60 * - int date: Date from which logs to be viewed. 61 */ 62 public function __construct($uniqueid, $filterparams = null) { 63 parent::__construct($uniqueid); 64 65 $this->set_attribute('class', 'reportlog generaltable generalbox'); 66 $this->filterparams = $filterparams; 67 // Add course column if logs are displayed for site. 68 $cols = array(); 69 $headers = array(); 70 if (empty($filterparams->courseid)) { 71 $cols = array('course'); 72 $headers = array(get_string('course')); 73 } 74 75 $this->define_columns(array_merge($cols, array('time', 'fullnameuser', 'relatedfullnameuser', 'context', 'component', 76 'eventname', 'description', 'origin', 'ip'))); 77 $this->define_headers(array_merge($headers, array( 78 get_string('time'), 79 get_string('fullnameuser'), 80 get_string('eventrelatedfullnameuser', 'report_log'), 81 get_string('eventcontext', 'report_log'), 82 get_string('eventcomponent', 'report_log'), 83 get_string('eventname'), 84 get_string('description'), 85 get_string('eventorigin', 'report_log'), 86 get_string('ip_address') 87 ) 88 )); 89 $this->collapsible(false); 90 $this->sortable(false); 91 $this->pageable(true); 92 } 93 94 /** 95 * Generate the course column. 96 * 97 * @param stdClass $event event data. 98 * @return string HTML for the course column. 99 */ 100 public function col_course($event) { 101 if (empty($event->courseid) || empty($this->courseshortnames[$event->courseid])) { 102 return '-'; 103 } else { 104 return $this->courseshortnames[$event->courseid]; 105 } 106 } 107 108 /** 109 * Generate the time column. 110 * 111 * @param stdClass $event event data. 112 * @return string HTML for the time column 113 */ 114 public function col_time($event) { 115 $recenttimestr = get_string('strftimerecent', 'core_langconfig'); 116 return userdate($event->timecreated, $recenttimestr); 117 } 118 119 /** 120 * Generate the username column. 121 * 122 * @param stdClass $event event data. 123 * @return string HTML for the username column 124 */ 125 public function col_fullnameuser($event) { 126 // Get extra event data for origin and realuserid. 127 $logextra = $event->get_logextra(); 128 129 // Add username who did the action. 130 if (!empty($logextra['realuserid'])) { 131 $a = new stdClass(); 132 $params = array('id' => $logextra['realuserid']); 133 if ($event->courseid) { 134 $params['course'] = $event->courseid; 135 } 136 $a->realusername = html_writer::link(new moodle_url("/user/view.php", $params), 137 $this->userfullnames[$logextra['realuserid']]); 138 $params['id'] = $event->userid; 139 $a->asusername = html_writer::link(new moodle_url("/user/view.php", $params), 140 $this->userfullnames[$event->userid]); 141 $username = get_string('eventloggedas', 'report_log', $a); 142 } else if (!empty($event->userid) && !empty($this->userfullnames[$event->userid])) { 143 $params = array('id' => $event->userid); 144 if ($event->courseid) { 145 $params['course'] = $event->courseid; 146 } 147 $username = html_writer::link(new moodle_url("/user/view.php", $params), $this->userfullnames[$event->userid]); 148 } else { 149 $username = '-'; 150 } 151 return $username; 152 } 153 154 /** 155 * Generate the related username column. 156 * 157 * @param stdClass $event event data. 158 * @return string HTML for the related username column 159 */ 160 public function col_relatedfullnameuser($event) { 161 // Add affected user. 162 if (!empty($event->relateduserid) && isset($this->userfullnames[$event->relateduserid])) { 163 $params = array('id' => $event->relateduserid); 164 if ($event->courseid) { 165 $params['course'] = $event->courseid; 166 } 167 return html_writer::link(new moodle_url("/user/view.php", $params), $this->userfullnames[$event->relateduserid]); 168 } else { 169 return '-'; 170 } 171 } 172 173 /** 174 * Generate the context column. 175 * 176 * @param stdClass $event event data. 177 * @return string HTML for the context column 178 */ 179 public function col_context($event) { 180 // Add context name. 181 if ($event->contextid) { 182 // If context name was fetched before then return, else get one. 183 if (isset($this->contextname[$event->contextid])) { 184 return $this->contextname[$event->contextid]; 185 } else { 186 $context = context::instance_by_id($event->contextid, IGNORE_MISSING); 187 if ($context) { 188 $contextname = $context->get_context_name(true); 189 if ($url = $context->get_url()) { 190 $contextname = html_writer::link($url, $contextname); 191 } 192 } else { 193 $contextname = get_string('other'); 194 } 195 } 196 } else { 197 $contextname = get_string('other'); 198 } 199 200 $this->contextname[$event->contextid] = $contextname; 201 return $contextname; 202 } 203 204 /** 205 * Generate the component column. 206 * 207 * @param stdClass $event event data. 208 * @return string HTML for the component column 209 */ 210 public function col_component($event) { 211 // Component. 212 $componentname = $event->component; 213 if (($event->component === 'core') || ($event->component === 'legacy')) { 214 return get_string('coresystem'); 215 } else if (get_string_manager()->string_exists('pluginname', $event->component)) { 216 return get_string('pluginname', $event->component); 217 } else { 218 return $componentname; 219 } 220 } 221 222 /** 223 * Generate the event name column. 224 * 225 * @param stdClass $event event data. 226 * @return string HTML for the event name column 227 */ 228 public function col_eventname($event) { 229 // Event name. 230 if ($this->filterparams->logreader instanceof logstore_legacy\log\store) { 231 // Hack for support of logstore_legacy. 232 $eventname = $event->eventname; 233 } else { 234 $eventname = $event->get_name(); 235 } 236 if ($url = $event->get_url()) { 237 $eventname = $this->action_link($url, $eventname, 'action'); 238 } 239 return $eventname; 240 } 241 242 /** 243 * Generate the description column. 244 * 245 * @param stdClass $event event data. 246 * @return string HTML for the description column 247 */ 248 public function col_description($event) { 249 // Description. 250 return $event->get_description(); 251 } 252 253 /** 254 * Generate the origin column. 255 * 256 * @param stdClass $event event data. 257 * @return string HTML for the origin column 258 */ 259 public function col_origin($event) { 260 // Get extra event data for origin and realuserid. 261 $logextra = $event->get_logextra(); 262 263 // Add event origin, normally IP/cron. 264 return $logextra['origin']; 265 } 266 267 /** 268 * Generate the ip column. 269 * 270 * @param stdClass $event event data. 271 * @return string HTML for the ip column 272 */ 273 public function col_ip($event) { 274 // Get extra event data for origin and realuserid. 275 $logextra = $event->get_logextra(); 276 277 $url = new moodle_url("/iplookup/index.php?ip={$logextra['ip']}&user=$event->userid"); 278 return $this->action_link($url, $logextra['ip'], 'ip'); 279 } 280 281 /** 282 * Method to create a link with popup action. 283 * 284 * @param moodle_url $url The url to open. 285 * @param string $text Anchor text for the link. 286 * @param string $name Name of the popup window. 287 * 288 * @return string html to use. 289 */ 290 protected function action_link(moodle_url $url, $text, $name = 'popup') { 291 global $OUTPUT; 292 $link = new action_link($url, $text, new popup_action('click', $url, $name, array('height' => 440, 'width' => 700))); 293 return $OUTPUT->render($link); 294 } 295 296 /** 297 * Helper function to get legacy crud action. 298 * 299 * @param string $crud crud action 300 * @return string legacy action. 301 */ 302 public function get_legacy_crud_action($crud) { 303 $legacyactionmap = array('c' => 'add', 'r' => 'view', 'u' => 'update', 'd' => 'delete'); 304 if (array_key_exists($crud, $legacyactionmap)) { 305 return $legacyactionmap[$crud]; 306 } else { 307 // From old legacy log. 308 return '-view'; 309 } 310 } 311 312 /** 313 * Helper function which is used by build logs to get action sql and param. 314 * 315 * @return array sql and param for action. 316 */ 317 public function get_action_sql() { 318 global $DB; 319 320 // In new logs we have a field to pick, and in legacy try get this from action. 321 if ($this->filterparams->logreader instanceof logstore_legacy\log\store) { 322 $action = $this->get_legacy_crud_action($this->filterparams->action); 323 $firstletter = substr($action, 0, 1); 324 if ($firstletter == '-') { 325 $sql = $DB->sql_like('action', ':action', false, true, true); 326 $params['action'] = '%'.substr($action, 1).'%'; 327 } else { 328 $sql = $DB->sql_like('action', ':action', false); 329 $params['action'] = '%'.$action.'%'; 330 } 331 } else if (!empty($this->filterparams->action)) { 332 $sql = "crud = :crud"; 333 $params['crud'] = $this->filterparams->action; 334 } else { 335 // Add condition for all possible values of crud (to use db index). 336 list($sql, $params) = $DB->get_in_or_equal(array('c', 'r', 'u', 'd'), 337 SQL_PARAMS_NAMED, 'crud'); 338 $sql = "crud ".$sql; 339 } 340 return array($sql, $params); 341 } 342 343 /** 344 * Helper function which is used by build logs to get course module sql and param. 345 * 346 * @return array sql and param for action. 347 */ 348 public function get_cm_sql() { 349 $joins = array(); 350 $params = array(); 351 352 if ($this->filterparams->logreader instanceof logstore_legacy\log\store) { 353 // The legacy store doesn't support context level. 354 $joins[] = "cmid = :cmid"; 355 $params['cmid'] = $this->filterparams->modid; 356 } else { 357 $joins[] = "contextinstanceid = :contextinstanceid"; 358 $joins[] = "contextlevel = :contextmodule"; 359 $params['contextinstanceid'] = $this->filterparams->modid; 360 $params['contextmodule'] = CONTEXT_MODULE; 361 } 362 363 $sql = implode(' AND ', $joins); 364 return array($sql, $params); 365 } 366 367 /** 368 * Query the reader. Store results in the object for use by build_table. 369 * 370 * @param int $pagesize size of page for paginated displayed table. 371 * @param bool $useinitialsbar do you want to use the initials bar. 372 */ 373 public function query_db($pagesize, $useinitialsbar = true) { 374 global $DB; 375 376 $joins = array(); 377 $params = array(); 378 379 // If we filter by userid and module id we also need to filter by crud and edulevel to ensure DB index is engaged. 380 $useextendeddbindex = !($this->filterparams->logreader instanceof logstore_legacy\log\store) 381 && !empty($this->filterparams->userid) && !empty($this->filterparams->modid); 382 383 $groupid = 0; 384 if (!empty($this->filterparams->courseid) && $this->filterparams->courseid != SITEID) { 385 if (!empty($this->filterparams->groupid)) { 386 $groupid = $this->filterparams->groupid; 387 } 388 389 $joins[] = "courseid = :courseid"; 390 $params['courseid'] = $this->filterparams->courseid; 391 } 392 393 if (!empty($this->filterparams->siteerrors)) { 394 $joins[] = "( action='error' OR action='infected' OR action='failed' )"; 395 } 396 397 if (!empty($this->filterparams->modid)) { 398 list($actionsql, $actionparams) = $this->get_cm_sql(); 399 $joins[] = $actionsql; 400 $params = array_merge($params, $actionparams); 401 } 402 403 if (!empty($this->filterparams->action) || $useextendeddbindex) { 404 list($actionsql, $actionparams) = $this->get_action_sql(); 405 $joins[] = $actionsql; 406 $params = array_merge($params, $actionparams); 407 } 408 409 // Getting all members of a group. 410 if ($groupid and empty($this->filterparams->userid)) { 411 if ($gusers = groups_get_members($groupid)) { 412 $gusers = array_keys($gusers); 413 $joins[] = 'userid IN (' . implode(',', $gusers) . ')'; 414 } else { 415 $joins[] = 'userid = 0'; // No users in groups, so we want something that will always be false. 416 } 417 } else if (!empty($this->filterparams->userid)) { 418 $joins[] = "userid = :userid"; 419 $params['userid'] = $this->filterparams->userid; 420 } 421 422 if (!empty($this->filterparams->date)) { 423 $joins[] = "timecreated > :date AND timecreated < :enddate"; 424 $params['date'] = $this->filterparams->date; 425 $params['enddate'] = $this->filterparams->date + DAYSECS; // Show logs only for the selected date. 426 } 427 428 if (isset($this->filterparams->edulevel) && ($this->filterparams->edulevel >= 0)) { 429 $joins[] = "edulevel = :edulevel"; 430 $params['edulevel'] = $this->filterparams->edulevel; 431 } else if ($useextendeddbindex) { 432 list($edulevelsql, $edulevelparams) = $DB->get_in_or_equal(array(\core\event\base::LEVEL_OTHER, 433 \core\event\base::LEVEL_PARTICIPATING, \core\event\base::LEVEL_TEACHING), SQL_PARAMS_NAMED, 'edulevel'); 434 $joins[] = "edulevel ".$edulevelsql; 435 $params = array_merge($params, $edulevelparams); 436 } 437 438 if (!($this->filterparams->logreader instanceof logstore_legacy\log\store)) { 439 // Filter out anonymous actions, this is N/A for legacy log because it never stores them. 440 $joins[] = "anonymous = 0"; 441 } 442 443 $selector = implode(' AND ', $joins); 444 445 if (!$this->is_downloading()) { 446 $total = $this->filterparams->logreader->get_events_select_count($selector, $params); 447 $this->pagesize($pagesize, $total); 448 } else { 449 $this->pageable(false); 450 } 451 452 $this->rawdata = $this->filterparams->logreader->get_events_select($selector, $params, $this->filterparams->orderby, 453 $this->get_page_start(), $this->get_page_size()); 454 455 // Set initial bars. 456 if ($useinitialsbar && !$this->is_downloading()) { 457 $this->initialbars($total > $pagesize); 458 } 459 460 // Update list of users and courses list which will be displayed on log page. 461 $this->update_users_and_courses_used(); 462 } 463 464 /** 465 * Helper function to create list of course shortname and user fullname shown in log report. 466 * This will update $this->userfullnames and $this->courseshortnames array with userfullname and courseshortname (with link), 467 * which will be used to render logs in table. 468 */ 469 public function update_users_and_courses_used() { 470 global $SITE, $DB; 471 472 $this->userfullnames = array(); 473 $this->courseshortnames = array($SITE->id => $SITE->shortname); 474 $userids = array(); 475 $courseids = array(); 476 // For each event cache full username and course. 477 // Get list of userids and courseids which will be shown in log report. 478 foreach ($this->rawdata as $event) { 479 $logextra = $event->get_logextra(); 480 if (!empty($event->userid) && !in_array($event->userid, $userids)) { 481 $userids[] = $event->userid; 482 } 483 if (!empty($logextra['realuserid']) && !in_array($logextra['realuserid'], $userids)) { 484 $userids[] = $logextra['realuserid']; 485 } 486 if (!empty($event->relateduserid) && !in_array($event->relateduserid, $userids)) { 487 $userids[] = $event->relateduserid; 488 } 489 490 if (!empty($event->courseid) && ($event->courseid != $SITE->id) && !in_array($event->courseid, $courseids)) { 491 $courseids[] = $event->courseid; 492 } 493 } 494 495 // Get user fullname and put that in return list. 496 if (!empty($userids)) { 497 list($usql, $uparams) = $DB->get_in_or_equal($userids); 498 $users = $DB->get_records_sql("SELECT id," . get_all_user_name_fields(true) . " FROM {user} WHERE id " . $usql, 499 $uparams); 500 foreach ($users as $userid => $user) { 501 $this->userfullnames[$userid] = fullname($user); 502 } 503 } 504 505 // Get course shortname and put that in return list. 506 if (!empty($courseids)) { // If all logs don't belog to site level then get course info. 507 list($coursesql, $courseparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED); 508 $ccselect = ', ' . context_helper::get_preload_record_columns_sql('ctx'); 509 $ccjoin = "LEFT JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)"; 510 $courseparams['contextlevel'] = CONTEXT_COURSE; 511 $sql = "SELECT c.id,c.shortname $ccselect FROM {course} c 512 $ccjoin 513 WHERE c.id " . $coursesql; 514 515 $courses = $DB->get_records_sql($sql, $courseparams); 516 foreach ($courses as $courseid => $course) { 517 $url = new moodle_url("/course/view.php", array('id' => $courseid)); 518 context_helper::preload_from_record($course); 519 $context = context_course::instance($courseid, IGNORE_MISSING); 520 // Method format_string() takes care of missing contexts. 521 $this->courseshortnames[$courseid] = html_writer::link($url, format_string($course->shortname, true, 522 array('context' => $context))); 523 } 524 } 525 } 526 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |