MDL-45985 cli: add new cli tool for validation of database structure
[moodle.git] / report / stats / locallib.php
blob0a0b6f1e414026122e36b73be18b6725e6e43b8f
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.
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/>.
17 /**
18 * Reports implementation
20 * @package report
21 * @subpackage stats
22 * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') || die;
28 require_once(dirname(__FILE__).'/lib.php');
29 require_once($CFG->dirroot.'/lib/statslib.php');
31 function report_stats_mode_menu($course, $mode, $time, $url) {
32 global $CFG, $OUTPUT;
34 $reportoptions = stats_get_report_options($course->id, $mode);
35 $timeoptions = report_stats_timeoptions($mode);
36 if (empty($timeoptions)) {
37 print_error('nostatstodisplay', '', $CFG->wwwroot.'/course/view.php?id='.$course->id);
41 $options = array();
42 $options[STATS_MODE_GENERAL] = get_string('statsmodegeneral');
43 $options[STATS_MODE_DETAILED] = get_string('statsmodedetailed');
44 if (has_capability('report/stats:view', context_system::instance())) {
45 $options[STATS_MODE_RANKED] = get_string('reports');
47 $popupurl = $url."?course=$course->id&time=$time";
48 $select = new single_select(new moodle_url($popupurl), 'mode', $options, $mode, null);
49 $select->set_label(get_string('reports'), array('class' => 'accesshide'));
50 $select->formid = 'switchmode';
51 return $OUTPUT->render($select);
54 function report_stats_timeoptions($mode) {
55 global $CFG, $DB;
57 if ($mode == STATS_MODE_DETAILED) {
58 $earliestday = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_user_daily}');
59 $earliestweek = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_user_weekly}');
60 $earliestmonth = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_user_monthly}');
61 } else {
62 $earliestday = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_daily}');
63 $earliestweek = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_weekly}');
64 $earliestmonth = $DB->get_field_sql('SELECT MIN(timeend) FROM {stats_monthly}');
68 if (empty($earliestday)) $earliestday = time();
69 if (empty($earliestweek)) $earliestweek = time();
70 if (empty($earliestmonth)) $earliestmonth = time();
72 $now = stats_get_base_daily();
73 $lastweekend = stats_get_base_weekly();
74 $lastmonthend = stats_get_base_monthly();
76 return stats_get_time_options($now,$lastweekend,$lastmonthend,$earliestday,$earliestweek,$earliestmonth);
79 function report_stats_report($course, $report, $mode, $user, $roleid, $time) {
80 global $CFG, $DB, $OUTPUT;
82 if ($user) {
83 $userid = $user->id;
84 } else {
85 $userid = 0;
88 $courses = get_courses('all','c.shortname','c.id,c.shortname,c.fullname');
89 $courseoptions = array();
91 foreach ($courses as $c) {
92 $context = context_course::instance($c->id);
94 if (has_capability('report/stats:view', $context)) {
95 $courseoptions[$c->id] = format_string($c->shortname, true, array('context' => $context));
99 $reportoptions = stats_get_report_options($course->id, $mode);
100 $timeoptions = report_stats_timeoptions($mode);
101 if (empty($timeoptions)) {
102 print_error('nostatstodisplay', '', $CFG->wwwroot.'/course/view.php?id='.$course->id);
105 $users = array();
106 $table = new html_table();
107 $table->width = 'auto';
109 if ($mode == STATS_MODE_DETAILED) {
110 $param = stats_get_parameters($time, null, $course->id, $mode); // we only care about the table and the time string (if we have time)
112 list($sort, $moreparams) = users_order_by_sql('u');
113 $moreparams['courseid'] = $course->id;
114 $sql = "SELECT DISTINCT u.id, u.firstname, u.lastname, u.idnumber
115 FROM {stats_user_{$param->table}} s
116 JOIN {user} u ON u.id = s.userid
117 WHERE courseid = :courseid";
118 if (!empty($param->stattype)) {
119 $sql .= " AND stattype = :stattype";
120 $moreparams['stattype'] = $param->stattype;
122 if (!empty($time)) {
123 $sql .= " AND timeend >= :timeafter";
124 $moreparams['timeafter'] = $param->timeafter;
126 $sql .= " ORDER BY {$sort}";
128 if (!$us = $DB->get_records_sql($sql, array_merge($param->params, $moreparams))) {
129 print_error('nousers');
132 foreach ($us as $u) {
133 $users[$u->userid] = fullname($u, true);
136 $table->align = array('left','left','left','left','left','left','left','left');
137 $table->data[] = array(html_writer::label(get_string('course'), 'menucourse'), html_writer::select($courseoptions, 'course', $course->id, false),
138 html_writer::label(get_string('users'), 'menuuserid'), html_writer::select($users, 'userid', $userid, false),
139 html_writer::label(get_string('statsreporttype'), 'menureport'), html_writer::select($reportoptions, 'report', ($report == 5) ? $report.$roleid : $report, false),
140 html_writer::label(get_string('statstimeperiod'), 'menutime'), html_writer::select($timeoptions, 'time', $time, false),
141 '<input type="submit" value="'.get_string('view').'" />') ;
142 } else if ($mode == STATS_MODE_RANKED) {
143 $table->align = array('left','left','left','left','left','left');
144 $table->data[] = array(html_writer::label(get_string('statsreporttype'), 'menureport'), html_writer::select($reportoptions, 'report', ($report == 5) ? $report.$roleid : $report, false),
145 html_writer::label(get_string('statstimeperiod'), 'menutime'), html_writer::select($timeoptions, 'time', $time, false),
146 '<input type="submit" value="'.get_string('view').'" />') ;
147 } else if ($mode == STATS_MODE_GENERAL) {
148 $table->align = array('left','left','left','left','left','left','left');
149 $table->data[] = array(html_writer::label(get_string('course'), 'menucourse'), html_writer::select($courseoptions, 'course', $course->id, false),
150 html_writer::label(get_string('statsreporttype'), 'menureport'), html_writer::select($reportoptions, 'report', ($report == 5) ? $report.$roleid : $report, false),
151 html_writer::label(get_string('statstimeperiod'), 'menutime'), html_writer::select($timeoptions, 'time', $time, false),
152 '<input type="submit" value="'.get_string('view').'" />') ;
155 echo '<form action="index.php" method="post">'."\n"
156 .'<div>'."\n"
157 .'<input type="hidden" name="mode" value="'.$mode.'" />'."\n";
159 echo html_writer::table($table);
161 echo '</div>';
162 echo '</form>';
164 if (!empty($report) && !empty($time)) {
165 if ($report == STATS_REPORT_LOGINS && $course->id != SITEID) {
166 print_error('reportnotavailable');
169 $param = stats_get_parameters($time,$report,$course->id,$mode);
171 if ($mode == STATS_MODE_DETAILED) {
172 $param->table = 'user_'.$param->table;
175 if (!empty($param->sql)) {
176 $sql = $param->sql;
177 } else {
178 //TODO: lceanup this ugly mess
179 $sql = 'SELECT '.((empty($param->fieldscomplete)) ? 'id,roleid,timeend,' : '').$param->fields
180 .' FROM {stats_'.$param->table.'} WHERE '
181 .(($course->id == SITEID) ? '' : ' courseid = '.$course->id.' AND ')
182 .((!empty($userid)) ? ' userid = '.$userid.' AND ' : '')
183 .((!empty($roleid)) ? ' roleid = '.$roleid.' AND ' : '')
184 . ((!empty($param->stattype)) ? ' stattype = \''.$param->stattype.'\' AND ' : '')
185 .' timeend >= '.$param->timeafter
186 .' '.$param->extras
187 .' ORDER BY timeend DESC';
190 $stats = $DB->get_records_sql($sql);
192 if (empty($stats)) {
193 echo $OUTPUT->notification(get_string('statsnodata'));
195 } else {
197 $stats = stats_fix_zeros($stats,$param->timeafter,$param->table,(!empty($param->line2)));
199 echo $OUTPUT->heading(format_string($course->shortname).' - '.get_string('statsreport'.$report)
200 .((!empty($user)) ? ' '.get_string('statsreportforuser').' ' .fullname($user,true) : '')
201 .((!empty($roleid)) ? ' '.$DB->get_field('role','name', array('id'=>$roleid)) : ''));
204 if ($mode == STATS_MODE_DETAILED) {
205 echo '<div class="graph"><img src="'.$CFG->wwwroot.'/report/stats/graph.php?mode='.$mode.'&amp;course='.$course->id.'&amp;time='.$time.'&amp;report='.$report.'&amp;userid='.$userid.'" alt="'.get_string('statisticsgraph').'" /></div>';
206 } else {
207 echo '<div class="graph"><img src="'.$CFG->wwwroot.'/report/stats/graph.php?mode='.$mode.'&amp;course='.$course->id.'&amp;time='.$time.'&amp;report='.$report.'&amp;roleid='.$roleid.'" alt="'.get_string('statisticsgraph').'" /></div>';
210 $table = new html_table();
211 $table->align = array('left','center','center','center');
212 $param->table = str_replace('user_','',$param->table);
213 switch ($param->table) {
214 case 'daily' : $period = get_string('day'); break;
215 case 'weekly' : $period = get_string('week'); break;
216 case 'monthly': $period = get_string('month', 'form'); break;
217 default : $period = '';
219 $table->head = array(get_string('periodending','moodle',$period));
220 if (empty($param->crosstab)) {
221 $table->head[] = $param->line1;
222 if (!empty($param->line2)) {
223 $table->head[] = $param->line2;
226 if (!file_exists($CFG->dirroot.'/report/log/index.php')) {
227 // bad luck, we can not link other report
228 } else if (empty($param->crosstab)) {
229 foreach ($stats as $stat) {
230 $a = array(userdate($stat->timeend-(60*60*24),get_string('strftimedate'),$CFG->timezone),$stat->line1);
231 if (isset($stat->line2)) {
232 $a[] = $stat->line2;
234 if (empty($CFG->loglifetime) || ($stat->timeend-(60*60*24)) >= (time()-60*60*24*$CFG->loglifetime)) {
235 if (has_capability('report/log:view', context_course::instance($course->id))) {
236 $a[] = '<a href="'.$CFG->wwwroot.'/report/log/index.php?id='.
237 $course->id.'&amp;chooselog=1&amp;showusers=1&amp;showcourses=1&amp;user='
238 .$userid.'&amp;date='.usergetmidnight($stat->timeend-(60*60*24)).'">'
239 .get_string('course').' ' .get_string('logs').'</a>&nbsp;';
240 } else {
241 $a[] = '';
244 $table->data[] = $a;
246 } else {
247 $data = array();
248 $roles = array();
249 $times = array();
250 $missedlines = array();
251 $coursecontext = context_course::instance($course->id);
252 $rolenames = role_fix_names(get_all_roles($coursecontext), $coursecontext, ROLENAME_ALIAS, true);
253 foreach ($stats as $stat) {
254 if (!empty($stat->zerofixed)) {
255 $missedlines[] = $stat->timeend;
257 $data[$stat->timeend][$stat->roleid] = $stat->line1;
258 if ($stat->roleid != 0) {
259 if (!array_key_exists($stat->roleid,$roles)) {
260 $roles[$stat->roleid] = $rolenames[$stat->roleid];
262 } else {
263 if (!array_key_exists($stat->roleid,$roles)) {
264 $roles[$stat->roleid] = get_string('all');
267 if (!array_key_exists($stat->timeend,$times)) {
268 $times[$stat->timeend] = userdate($stat->timeend,get_string('strftimedate'),$CFG->timezone);
272 foreach ($data as $time => $rolesdata) {
273 if (in_array($time,$missedlines)) {
274 $rolesdata = array();
275 foreach ($roles as $roleid => $guff) {
276 $rolesdata[$roleid] = 0;
279 else {
280 foreach (array_keys($roles) as $r) {
281 if (!array_key_exists($r, $rolesdata)) {
282 $rolesdata[$r] = 0;
286 krsort($rolesdata);
287 $row = array_merge(array($times[$time]),$rolesdata);
288 if (empty($CFG->loglifetime) || ($stat->timeend-(60*60*24)) >= (time()-60*60*24*$CFG->loglifetime)) {
289 if (has_capability('report/log:view', context_course::instance($course->id))) {
290 $row[] = '<a href="'.$CFG->wwwroot.'/report/log/index.php?id='
291 .$course->id.'&amp;chooselog=1&amp;showusers=1&amp;showcourses=1&amp;user='.$userid
292 .'&amp;date='.usergetmidnight($time-(60*60*24)).'">'
293 .get_string('course').' ' .get_string('logs').'</a>&nbsp;';
294 } else {
295 $row[] = '';
298 $table->data[] = $row;
300 krsort($roles);
301 $table->head = array_merge($table->head,$roles);
303 $table->head[] = get_string('logs');
304 //if (!empty($lastrecord)) {
305 //$lastrecord[] = $lastlink;
306 //$table->data[] = $lastrecord;
308 echo html_writer::table($table);