Commit | Line | Data |
---|---|---|
bf2692e3 | 1 | <?php |
2 | /*************************************************************************** | |
8d84c630 | 3 | * Copyright (C) 2003-2009 Polytechnique.org * |
bf2692e3 | 4 | * http://opensource.polytechnique.org/ * |
5 | * * | |
6 | * This program is free software; you can redistribute it and/or modify * | |
7 | * it under the terms of the GNU General Public License as published by * | |
8 | * the Free Software Foundation; either version 2 of the License, or * | |
9 | * (at your option) any later version. * | |
10 | * * | |
11 | * This program is distributed in the hope that it will be useful, * | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
14 | * GNU General Public License for more details. * | |
15 | * * | |
16 | * You should have received a copy of the GNU General Public License * | |
17 | * along with this program; if not, write to the Free Software * | |
18 | * Foundation, Inc., * | |
19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * | |
20 | ***************************************************************************/ | |
21 | ||
22 | function serv_to_str($params) { | |
23 | $flags = explode(',',$params); | |
24 | $trad = Array('web' => 'site web', 'mail'=> 'redirection mail', | |
a7de4ef7 | 25 | 'smtp' => 'serveur sécurisé d\'envoi de mails', |
bf2692e3 | 26 | 'nntp' => 'serveur des forums de discussion'); |
27 | $ret = Array(); | |
28 | foreach ($flags as $flag) { | |
29 | $ret[] = $trad[$flag]; | |
30 | } | |
31 | return implode(', ',$ret); | |
32 | } | |
33 | ||
34 | class StatsModule extends PLModule | |
35 | { | |
36 | function handlers() | |
37 | { | |
38 | return array( | |
39 | 'stats' => $this->make_hook('stats', AUTH_COOKIE), | |
40 | 'stats/evolution' => $this->make_hook('evolution', AUTH_COOKIE), | |
41 | 'stats/graph' => $this->make_hook('graph', AUTH_COOKIE), | |
42 | 'stats/graph/evolution' | |
43 | => $this->make_hook('graph_evo', AUTH_COOKIE), | |
44 | 'stats/promos' => $this->make_hook('promos', AUTH_COOKIE), | |
b0239324 | 45 | 'stats/profile' => $this->make_hook('profile', AUTH_COOKIE), |
bf2692e3 | 46 | |
47 | 'stats/coupures' => $this->make_hook('coupures', AUTH_PUBLIC), | |
48 | ); | |
49 | } | |
50 | ||
51 | function handler_stats(&$page) | |
52 | { | |
53 | $page->changeTpl('stats/index.tpl'); | |
bf2692e3 | 54 | } |
55 | ||
56 | function handler_evolution(&$page, $jours = 365) | |
57 | { | |
58 | $page->changeTpl('stats/evolution_inscrits.tpl'); | |
59 | $page->assign('jours', $jours); | |
bf2692e3 | 60 | } |
61 | ||
62 | function handler_graph_evo(&$page, $jours = 365) | |
63 | { | |
b1be6d17 | 64 | define('DUREEJOUR', 24 * 3600); |
bf2692e3 | 65 | |
a7de4ef7 | 66 | //recupere le nombre d'inscriptions par jour sur la plage concernée |
b1be6d17 FB |
67 | $res = XDB::iterRow('SELECT IF(registration_date > DATE_SUB(NOW(), INTERVAL {?} DAY), |
68 | TO_DAYS(registration_date) - TO_DAYS(NOW()), | |
69 | -{?}) AS jour, | |
70 | COUNT(uid) AS nb | |
f476ca60 FB |
71 | FROM accounts AS a |
72 | LEFT JOIN account_profiles AS ap ON(ap.uid = a.uid AND FIND_IN_SET(\'owner\', ap.flags)) | |
73 | LEFT JOIN profiles AS p ON (ap.pid = p.pid) | |
74 | WHERE state = \'active\' AND p.deathdate IS NULL | |
b1be6d17 | 75 | GROUP BY jour', (int)$jours, 1 + (int)$jours); |
bf2692e3 | 76 | |
77 | //genere des donnees compatibles avec GNUPLOT | |
78 | $inscrits=''; | |
79 | ||
a7de4ef7 | 80 | // la première ligne contient le total des inscrits avant la date de départ (J - $jours) |
bf2692e3 | 81 | list(,$init_nb) = $res->next(); |
0521940c | 82 | $total = $init_nb; |
83 | $numjour = - $jours - 1; | |
bf2692e3 | 84 | |
85 | for ($i = -$jours; $i<=0; $i++) { | |
86 | if ($numjour<$i) { | |
87 | if(!list($numjour, $nb) = $res->next()) { | |
88 | $numjour = 0; | |
89 | $nb = 0; | |
90 | } | |
91 | } | |
92 | if ($numjour==$i) $total+=$nb; | |
93 | $inscrits .= date('d/m/y',$i*DUREEJOUR+time())." ".$total."\n"; | |
94 | } | |
95 | ||
a7de4ef7 | 96 | //Genere le graphique à la volée avec GNUPLOT |
bf2692e3 | 97 | header( "Content-type: image/png"); |
98 | ||
99 | $delt = ($total - $init_nb)/10; | |
0521940c | 100 | $delt = $delt ? $delt : 5; |
bf2692e3 | 101 | $ymin = round($init_nb - $delt,0); |
102 | $ymax = round($total + $delt,0); | |
103 | ||
104 | $gnuplot = <<<EOF2 | |
105 | gnuplot <<EOF | |
106 | ||
107 | set term png small color | |
108 | set size 640/480 | |
109 | set xdata time | |
110 | set timefmt "%d/%m/%y" | |
111 | ||
112 | set format x "%m/%y" | |
113 | set yr [$ymin:$ymax] | |
114 | ||
115 | set title "Nombre d'inscrits" | |
116 | ||
117 | plot "-" using 1:2 title 'inscrits' with lines; | |
118 | {$inscrits} | |
119 | EOF | |
120 | EOF2; | |
121 | ||
122 | passthru($gnuplot); | |
123 | exit; | |
124 | } | |
125 | ||
126 | function handler_graph(&$page, $promo = null) | |
127 | { | |
bf2692e3 | 128 | if ($promo == 'all') { |
a7de4ef7 | 129 | // date de départ |
203bc766 | 130 | $depart = 1930; |
bf2692e3 | 131 | |
a7de4ef7 | 132 | //recupere le nombre d'inscriptions par jour sur la plage concernée |
b1be6d17 FB |
133 | $res = XDB::iterRow("SELECT pe.entry_year AS promo, SUM(state = 'active') / COUNT(*) * 100 |
134 | FROM accounts AS a | |
135 | INNER JOIN account_profiles AS ap ON (ap.uid = a.uid AND FIND_IN_SET('owner', ap.perms)) | |
f476ca60 | 136 | INNER JOIN profiles AS p ON (p.pid = ap.pid) |
b1be6d17 | 137 | INNER JOIN profile_education AS pe ON (pe.uid = ap.pid AND FIND_IN_SET('primary', pe.flags)) |
f476ca60 | 138 | WHERE pe.entry_year >= {?} AND p.deathdate IS NULL |
b1be6d17 | 139 | GROUP BY promo", $depart); |
bf2692e3 | 140 | |
141 | //genere des donnees compatibles avec GNUPLOT | |
142 | $inscrits=''; | |
143 | ||
a7de4ef7 | 144 | // la première ligne contient le total des inscrits avant la date de départ |
bf2692e3 | 145 | list($annee, $nb) = $res->next(); |
146 | ||
147 | for ($i = $depart; $i <= date("Y"); $i++) { | |
148 | if ($annee < $i) { | |
149 | if(!list($annee, $nb) = $res->next()) { | |
150 | $annee = 0; | |
151 | $nb = 0; | |
152 | } | |
153 | } | |
154 | if ($nb > 0 || $i < date('Y')) | |
155 | $inscrits .= $i.' '.$nb."\n"; | |
156 | } | |
157 | ||
a7de4ef7 | 158 | //Genere le graphique à la volée avec GNUPLOT |
bf2692e3 | 159 | $fin = $i+2; |
160 | ||
161 | $gnuplot = <<<EOF2 | |
162 | gnuplot <<EOF | |
163 | ||
164 | set term png small color | |
165 | set size 640/480 | |
166 | set timefmt "%d/%m/%y" | |
167 | ||
168 | set xr [$depart:$fin] | |
169 | set yr [0:100] | |
170 | ||
203bc766 | 171 | set title "Proportion d'inscrits par promotion depuis $depart, en %." |
bf2692e3 | 172 | |
173 | plot "-" using 1:2 title 'inscrits' with boxes; | |
174 | {$inscrits} | |
175 | EOF | |
176 | EOF2; | |
177 | ||
178 | } else { | |
179 | //nombre de jours sur le graph | |
180 | $jours = 365; | |
b1be6d17 FB |
181 | define('DUREEJOUR', 24 * 3600); |
182 | ||
b1be6d17 FB |
183 | $res = XDB::query("SELECT MIN(TO_DAYS(a.registration_date) - TO_DAYS(NOW())) |
184 | FROM accounts AS a | |
185 | INNER JOIN account_profiles AS ap ON (ap.uid = a.uid AND FIND_IN_SET('owner', ap.perms)) | |
186 | INNER JOIN profile_education AS pe ON (pe.uid = ap.pid AND FIND_IN_SET('primary', pe.flags)) | |
187 | WHERE pe.entry_year = {?} AND a.state = 'active'", (int)$promo); | |
bf2692e3 | 188 | $jours = -$res->fetchOneCell(); |
189 | ||
a7de4ef7 | 190 | //recupere le nombre d'inscriptions par jour sur la plage concernée |
b1be6d17 FB |
191 | $res = XDB::iterRow("SELECT IF(a.registration_date > DATE_SUB(NOW(), INTERVAL {?} DAY), |
192 | TO_DAYS(a.registration_date) - TO_DAYS(NOW()), | |
193 | -{?}) AS jour, | |
194 | COUNT(a.uid) AS nb | |
195 | FROM accounts AS a | |
196 | INNER JOIN account_profiles AS ap ON (ap.uid = a.uid AND FIND_IN_SET('owner', ap.perms)) | |
197 | INNER JOIN profile_education AS pe ON (pe.uid = ap.pid AND FIND_IN_SET('primary', pe.flags)) | |
198 | WHERE pe.entry_year = {?} AND a.state = 'active' | |
199 | GROUP BY jour", (int)$jours, 1 + (int)$jours, (int)$promo); | |
bf2692e3 | 200 | |
201 | //genere des donnees compatibles avec GNUPLOT | |
202 | $inscrits=''; | |
203 | ||
a7de4ef7 | 204 | // la première ligne contient le total des inscrits avant la date de départ (J - $jours) |
bf2692e3 | 205 | list(,$init_nb) = $res->next(); |
206 | $total = $init_nb; | |
207 | ||
208 | list($numjour, $nb) = $res->next(); | |
209 | ||
210 | for ($i = -$jours;$i<=0;$i++) { | |
211 | if ($numjour<$i) { | |
212 | if(!list($numjour, $nb) = $res->next()) { | |
213 | $numjour = 0; | |
214 | $nb = 0; | |
215 | } | |
216 | } | |
217 | if ($numjour==$i) $total+=$nb; | |
218 | $inscrits .= date('d/m/y',$i*DUREEJOUR+time())." ".$total."\n"; | |
219 | } | |
220 | ||
a7de4ef7 | 221 | //Genere le graphique à la volée avec GNUPLOT |
bf2692e3 | 222 | $delt = ($total - $init_nb) / 10; |
223 | $delt += ($delt < 1); | |
224 | $ymin = round($init_nb - $delt,0); | |
225 | $ymax = round($total + $delt,0); | |
226 | ||
227 | $gnuplot = <<<EOF2 | |
228 | gnuplot <<EOF | |
229 | ||
230 | set term png small color | |
231 | set size 640/480 | |
232 | set xdata time | |
233 | set timefmt "%d/%m/%y" | |
234 | ||
235 | set format x "%m/%y" | |
236 | set yr [$ymin:$ymax] | |
237 | ||
238 | set title "Nombre d'inscrits de la promotion $promo." | |
239 | ||
240 | plot "-" using 1:2 title 'inscrits' with lines; | |
241 | {$inscrits}e | |
242 | EOF | |
243 | EOF2; | |
244 | } | |
245 | ||
246 | header('Content-type: image/png'); | |
247 | passthru($gnuplot); | |
248 | exit; | |
249 | } | |
250 | ||
251 | function handler_promos(&$page, $promo = null) | |
252 | { | |
bf2692e3 | 253 | $page->changeTpl('stats/nb_by_promo.tpl'); |
254 | ||
b1be6d17 FB |
255 | $res = XDB::iterRow('SELECT pe.entry_year AS promo, COUNT(*) |
256 | FROM accounts AS a | |
257 | INNER JOIN account_profiles AS ap ON (ap.uid = a.uid AND FIND_IN_SET(\'owner\', ap.perms)) | |
258 | INNER JOIN profile_education AS pe ON (pe.uid = ap.pid AND FIND_IN_SET(\'primary\', pe.flags)) | |
259 | WHERE pe.entry_year >= 1900 AND a.state = \'active\' | |
260 | GROUP BY promo | |
261 | ORDER BY promo'); | |
bf2692e3 | 262 | $max=0; $min=3000; |
263 | ||
264 | while (list($p,$nb) = $res->next()) { | |
265 | $p = intval($p); | |
266 | if(!isset($nbpromo[$p/10])) { | |
267 | $nbpromo[$p/10] = Array('','','','','','','','','',''); // tableau de 10 cases vides | |
268 | } | |
269 | $nbpromo[$p/10][$p%10]=Array('promo' => $p, 'nb' => $nb); | |
270 | } | |
271 | ||
272 | $page->assign_by_ref('nbs', $nbpromo); | |
273 | $page->assign('min', $min-$min % 10); | |
274 | $page->assign('max', $max+10-$max%10); | |
275 | $page->assign('promo', $promo); | |
bf2692e3 | 276 | } |
277 | ||
278 | function handler_coupures(&$page, $cp_id = null) | |
279 | { | |
bf2692e3 | 280 | $page->changeTpl('stats/coupure.tpl'); |
281 | ||
282 | if (!is_null($cp_id)) { | |
da398501 | 283 | $res = XDB::query("SELECT debut, |
284 | TIME_FORMAT(duree,'%kh%i') AS duree, | |
285 | resume, description, services | |
286 | FROM coupures | |
287 | WHERE id = {?}", $cp_id); | |
bf2692e3 | 288 | $cp = $res->fetchOneAssoc(); |
289 | } | |
290 | ||
ccdbc270 | 291 | if(@$cp) { |
bf2692e3 | 292 | $cp['lg_services'] = serv_to_str($cp['services']); |
293 | $page->assign_by_ref('cp',$cp); | |
294 | } else { | |
295 | $beginning_date = date("Ymd", time() - 3600*24*21) . "000000"; | |
da398501 | 296 | $sql = "SELECT id, debut, resume, services |
bf2692e3 | 297 | FROM coupures where debut > '$beginning_date' order by debut desc"; |
08cce2ff | 298 | $page->assign('coupures', XDB::iterator($sql)); |
ccdbc270 | 299 | $res = XDB::iterator("SELECT host, text |
300 | FROM mx_watch | |
301 | WHERE state != 'ok'"); | |
302 | $page->assign('mxs', $res); | |
bf2692e3 | 303 | } |
bf2692e3 | 304 | } |
b0239324 FB |
305 | |
306 | function handler_profile(&$page, $period = 'overall') | |
307 | { | |
308 | $page->changeTpl('stats/profile.tpl'); | |
309 | ||
310 | $time = ''; | |
311 | switch ($period) { | |
312 | case 'week': case 'month': case 'year': | |
313 | $time = ' AND e.stamp > DATE_SUB(CURDATE(), INTERVAL 1 ' . strtoupper($period) . ')'; | |
314 | break; | |
315 | } | |
f476ca60 FB |
316 | $rows = XDB::fetchAllAssoc("SELECT p.pid AS profile, COUNT(*) AS count |
317 | FROM logger.events AS e | |
318 | INNER JOIN logger.actions AS act ON (e.action = act.id) | |
319 | INNER JOIN profiles AS p ON (p.hrpid = e.data) | |
320 | WHERE act.text = 'view_profile' $time | |
321 | GROUP BY e.data | |
322 | ORDER BY count DESC | |
323 | LIMIT 10"); | |
324 | foreach ($rows as $key=>$row) { | |
325 | $rows[$key]['profile'] = Profile::get($rows[$key]['profile']); | |
326 | } | |
b0239324 FB |
327 | $page->assign('profiles', $rows); |
328 | $page->assign('period', $period); | |
329 | } | |
bf2692e3 | 330 | } |
331 | ||
a7de4ef7 | 332 | // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: |
bf2692e3 | 333 | ?> |