See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 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 /** 18 * class block_recent_activity 19 * 20 * @package block_recent_activity 21 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 require_once($CFG->dirroot.'/course/lib.php'); 26 27 /** 28 * class block_recent_activity 29 * 30 * @package block_recent_activity 31 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} 32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 */ 34 class block_recent_activity extends block_base { 35 36 /** 37 * Use {@link block_recent_activity::get_timestart()} to access 38 * 39 * @var int stores the time since when we want to show recent activity 40 */ 41 protected $timestart = null; 42 43 /** 44 * Initialises the block 45 */ 46 function init() { 47 $this->title = get_string('pluginname', 'block_recent_activity'); 48 } 49 50 /** 51 * Returns the content object 52 * 53 * @return stdObject 54 */ 55 function get_content() { 56 if ($this->content !== NULL) { 57 return $this->content; 58 } 59 60 if (empty($this->instance)) { 61 $this->content = ''; 62 return $this->content; 63 } 64 65 $this->content = new stdClass; 66 $this->content->text = ''; 67 $this->content->footer = ''; 68 69 $renderer = $this->page->get_renderer('block_recent_activity'); 70 $this->content->text = $renderer->recent_activity($this->page->course, 71 $this->get_timestart(), 72 $this->get_recent_enrolments(), 73 $this->get_structural_changes(), 74 $this->get_modules_recent_activity()); 75 76 return $this->content; 77 } 78 79 /** 80 * Returns the time since when we want to show recent activity 81 * 82 * For guest users it is 2 days, for registered users it is the time of last access to the course 83 * 84 * @return int 85 */ 86 protected function get_timestart() { 87 global $USER; 88 if ($this->timestart === null) { 89 $this->timestart = round(time() - COURSE_MAX_RECENT_PERIOD, -2); // better db caching for guests - 100 seconds 90 91 if (!isguestuser()) { 92 if (!empty($USER->lastcourseaccess[$this->page->course->id])) { 93 if ($USER->lastcourseaccess[$this->page->course->id] > $this->timestart) { 94 $this->timestart = $USER->lastcourseaccess[$this->page->course->id]; 95 } 96 } 97 } 98 } 99 return $this->timestart; 100 } 101 102 /** 103 * Returns all recent enrolments. 104 * 105 * This function previously used get_recent_enrolments located in lib/deprecatedlib.php which would 106 * return an empty array which was identified in MDL-36993. The use of this function outside the 107 * deprecated lib was removed in MDL-40649. 108 * 109 * @todo MDL-36993 this function always return empty array 110 * @return array array of entries from {user} table 111 */ 112 protected function get_recent_enrolments() { 113 return array(); 114 } 115 116 /** 117 * Returns list of recent changes in course structure 118 * 119 * It includes adding, editing or deleting of the resources or activities 120 * Excludes changes on modules without a view link (i.e. labels), and also 121 * if activity was both added and deleted 122 * 123 * @return array array of changes. Each element is an array containing attributes: 124 * 'action' - one of: 'add mod', 'update mod', 'delete mod' 125 * 'module' - instance of cm_info (for 'delete mod' it is an object with attributes modname and modfullname) 126 */ 127 protected function get_structural_changes() { 128 global $DB; 129 $course = $this->page->course; 130 $context = context_course::instance($course->id); 131 $canviewdeleted = has_capability('block/recent_activity:viewdeletemodule', $context); 132 $canviewupdated = has_capability('block/recent_activity:viewaddupdatemodule', $context); 133 if (!$canviewdeleted && !$canviewupdated) { 134 return; 135 } 136 137 $timestart = $this->get_timestart(); 138 $changelist = array(); 139 // The following query will retrieve the latest action for each course module in the specified course. 140 // Also the query filters out the modules that were created and then deleted during the given interval. 141 $sql = "SELECT 142 cmid, MIN(action) AS minaction, MAX(action) AS maxaction, MAX(modname) AS modname 143 FROM {block_recent_activity} 144 WHERE timecreated > ? AND courseid = ? 145 GROUP BY cmid 146 ORDER BY MAX(timecreated) DESC"; 147 $params = array($timestart, $course->id); 148 $logs = $DB->get_records_sql($sql, $params); 149 if (isset($logs[0])) { 150 // If special record for this course and cmid=0 is present, migrate logs. 151 self::migrate_logs($course); 152 $logs = $DB->get_records_sql($sql, $params); 153 } 154 if ($logs) { 155 $modinfo = get_fast_modinfo($course); 156 foreach ($logs as $log) { 157 // We used aggregate functions since constants CM_CREATED, CM_UPDATED and CM_DELETED have ascending order (0,1,2). 158 $wasdeleted = ($log->maxaction == block_recent_activity_observer::CM_DELETED); 159 $wascreated = ($log->minaction == block_recent_activity_observer::CM_CREATED); 160 161 if ($wasdeleted && $wascreated) { 162 // Activity was created and deleted within this interval. Do not show it. 163 continue; 164 } else if ($wasdeleted && $canviewdeleted) { 165 if (plugin_supports('mod', $log->modname, FEATURE_NO_VIEW_LINK, false)) { 166 // Better to call cm_info::has_view() because it can be dynamic. 167 // But there is no instance of cm_info now. 168 continue; 169 } 170 // Unfortunately we do not know if the mod was visible. 171 $modnames = get_module_types_names(); 172 $changelist[$log->cmid] = array('action' => 'delete mod', 173 'module' => (object)array( 174 'modname' => $log->modname, 175 'modfullname' => isset($modnames[$log->modname]) ? $modnames[$log->modname] : $log->modname 176 )); 177 178 } else if (!$wasdeleted && isset($modinfo->cms[$log->cmid]) && $canviewupdated) { 179 // Module was either added or updated during this interval and it currently exists. 180 // If module was both added and updated show only "add" action. 181 $cm = $modinfo->cms[$log->cmid]; 182 if ($cm->has_view() && $cm->uservisible) { 183 $changelist[$log->cmid] = array( 184 'action' => $wascreated ? 'add mod' : 'update mod', 185 'module' => $cm 186 ); 187 } 188 } 189 } 190 } 191 return $changelist; 192 } 193 194 /** 195 * Returns list of recent activity within modules 196 * 197 * For each used module type executes callback MODULE_print_recent_activity() 198 * 199 * @return array array of pairs moduletype => content 200 */ 201 protected function get_modules_recent_activity() { 202 $context = context_course::instance($this->page->course->id); 203 $viewfullnames = has_capability('moodle/site:viewfullnames', $context); 204 $hascontent = false; 205 206 $modinfo = get_fast_modinfo($this->page->course); 207 $usedmodules = $modinfo->get_used_module_names(); 208 $recentactivity = array(); 209 foreach ($usedmodules as $modname => $modfullname) { 210 // Each module gets it's own logs and prints them 211 ob_start(); 212 $hascontent = component_callback('mod_'. $modname, 'print_recent_activity', 213 array($this->page->course, $viewfullnames, $this->get_timestart()), false); 214 if ($hascontent) { 215 $recentactivity[$modname] = ob_get_contents(); 216 } 217 ob_end_clean(); 218 } 219 return $recentactivity; 220 } 221 222 /** 223 * Which page types this block may appear on. 224 * 225 * @return array page-type prefix => true/false. 226 */ 227 function applicable_formats() { 228 return array('all' => true, 'my' => false, 'tag' => false); 229 } 230 231 /** 232 * Migrates entries from table {log} into {block_recent_activity} 233 * 234 * We only migrate logs for the courses that actually have recent activity 235 * block and that are being viewed within COURSE_MAX_RECENT_PERIOD time 236 * after the upgrade. 237 * 238 * The presence of entry in {block_recent_activity} with the cmid=0 indicates 239 * that the course needs log migration. Those entries were installed in 240 * db/upgrade.php when the table block_recent_activity was created. 241 * 242 * @param stdClass $course 243 */ 244 protected static function migrate_logs($course) { 245 global $DB; 246 if (!$logstarted = $DB->get_record('block_recent_activity', 247 array('courseid' => $course->id, 'cmid' => 0), 248 'id, timecreated')) { 249 return; 250 } 251 $DB->delete_records('block_recent_activity', array('id' => $logstarted->id)); 252 try { 253 $logs = $DB->get_records_select('log', 254 "time > ? AND time < ? AND course = ? AND 255 module = 'course' AND 256 (action = 'add mod' OR action = 'update mod' OR action = 'delete mod')", 257 array(time()-COURSE_MAX_RECENT_PERIOD, $logstarted->timecreated, $course->id), 258 'id ASC', 'id, time, userid, cmid, action, info'); 259 } catch (Exception $e) { 260 // Probably table {log} was already removed. 261 return; 262 } 263 if (!$logs) { 264 return; 265 } 266 $modinfo = get_fast_modinfo($course); 267 $entries = array(); 268 foreach ($logs as $log) { 269 $info = explode(' ', $log->info); 270 if (count($info) != 2) { 271 continue; 272 } 273 $modname = $info[0]; 274 $instanceid = $info[1]; 275 $entry = array('courseid' => $course->id, 'userid' => $log->userid, 276 'timecreated' => $log->time, 'modname' => $modname); 277 if ($log->action == 'delete mod') { 278 if (!$log->cmid) { 279 continue; 280 } 281 $entry['action'] = 2; 282 $entry['cmid'] = $log->cmid; 283 } else { 284 if (!isset($modinfo->instances[$modname][$instanceid])) { 285 continue; 286 } 287 if ($log->action == 'add mod') { 288 $entry['action'] = 0; 289 } else { 290 $entry['action'] = 1; 291 } 292 $entry['cmid'] = $modinfo->instances[$modname][$instanceid]->id; 293 } 294 $entries[] = $entry; 295 } 296 $DB->insert_records('block_recent_activity', $entries); 297 } 298 } 299
title
Description
Body
title
Description
Body
title
Description
Body
title
Body