Commit a5d404c2b9743fcd541561a591ff7d35f7498736

Authored by Etienne Pallier
1 parent 828525a8
Exists in master and in 1 other branch dev

Grosse refactorisation et simplification de la logique des stats

(UsersController => StatsTable)

v4.106.6-3.7.9
CHANGES.txt
... ... @@ -134,6 +134,10 @@ Outre ces changements, voici d'autres changements importants :
134 134 ======= CHANGES =======
135 135  
136 136 -------
  137 +24/10/2020 v4.106.6-3.7.9
  138 + - (i) Grosse refactorisation et simplification de la logique des stats (UsersController => StatsTable)
  139 +
  140 +-------
137 141 23/10/2020 v4.106.5-3.7.9
138 142 - (b) Bugfix tests (ajout Stats en fixture)
139 143 - (e) Ajout d'un champs "description" à toutes les tables qui en manquent
... ...
README.md
... ... @@ -42,8 +42,8 @@ Logiciel testé et validé sur les configurations suivantes :
42 42  
43 43 --------------------------------------------------------------------------------------------
44 44  
45   -Date: 23/10/2020
46   -Version: 4.106.5-3.7.9
  45 +Date: 24/10/2020
  46 +Version: 4.106.6-3.7.9
47 47  
48 48  
49 49 HISTORIQUE DES CHANGEMENTS DE VERSION : voir le fichier CHANGES.txt (ou la page web /pages/changes)
... ...
src/Controller/StatsController.php
... ... @@ -98,8 +98,10 @@ class StatsController extends AppController
98 98 * @return \Cake\Http\Response|null Redirects to index.
99 99 * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
100 100 */
101   - public function delete($id = null)
  101 + public function delete($year=null,$user_id=null)
  102 + //public function delete($id = null)
102 103 {
  104 + $id = [$year,$user_id];
103 105 $this->request->allowMethod(['post', 'delete']);
104 106 $stat = $this->Stats->get($id);
105 107 if ($this->Stats->delete($stat)) {
... ...
src/Controller/UsersController.php
... ... @@ -208,7 +208,8 @@ class UsersController extends AppController
208 208 ]
209 209 */
210 210  
211   - $this->_updateStatsForCurrentUserOnLogin();
  211 + $this->statsUpdateForCurrentUserWhen(null, 'sur login');
  212 + //$this->statsUpdateForCurrentUserOnLogin();
212 213 //exit;
213 214  
214 215 // On va maintenant à la page qui etait demandée
... ... @@ -223,7 +224,8 @@ class UsersController extends AppController
223 224 public function logout() {
224 225 //debug("LOGOUT !");
225 226 //debug($this->u);
226   - $this->_updateStatsForCurrentUserOnLogout();
  227 + $this->statsUpdateForCurrentUserWhen(null,'sur logout');
  228 + //$this->statsUpdateForCurrentUserOnLogout();
227 229 //$this->Flash->success('You are now logged out.');
228 230 return $this->redirect($this->LdapAuth->logout());
229 231 // Puis ça va sur /users/login
... ... @@ -270,183 +272,15 @@ class UsersController extends AppController
270 272 }
271 273  
272 274  
273   - /*
274   - * Mise à jour des stats pour ce user (et pour l'année courante) au moment du login
275   - * => on enregistre son heure de connexion
276   - * => on incrémente le nombre de connexions
277   - */
278   - public function _updateStatsForCurrentUserOnLogin($user_infos = null) {
279   -
280   - $user_id = $this->_getCurrentUserEntityFromSession($user_infos)->id;
281   - //debug($user);
282   -
283   - $now = new FrozenTime();
284   - //debug($last_login_time);
285   - $year = $now->format('yy');
286   - //debug($year);
287   -
288   - // On recup la Stat du user courant
289   - $table_stats = $this->Users->Stats;
290   - $stat_id = [$year,$user_id];
291   - $current_user_stat = null;
292   - try {
293   - // Si un enregistrement existe pour ce user (et cette année) => on le récupère
294   - $current_user_stat = $table_stats->get($stat_id);
295   - //debug("exists");
296   - //$current_user_stat->last_logout_time = null;
297   - } catch (\Cake\Datasource\Exception\RecordNotFoundException $e) {
298   - //echo 'Exception reçue : ', $e->getMessage(), "\n";
299   - // Pas d'enregistrement pour ce user (et cette année) => on le crée
300   - //debug("new");
301   - /*
302   - $stat = [
303   - //['year','user_id'] => [$year,$user->id],
304   - //'(year,user_id)' => [$year,$user->id],
305   - 'year' => $year,
306   - 'user_id' => $user->id,
307   - 'last_login_time' => $last_login_time,
308   - ];
309   - debug($stat);
310   - */
311   - //$stat_entity = $table_stats->newEntity($stat);
312   - $current_user_stat = $table_stats->newEntity();
313   - $current_user_stat->year = $year;
314   - $current_user_stat->user_id = $user_id;
315   - }
316   - $last_login_time = $current_user_stat->last_login_time;
317   - $last_logout_time = $current_user_stat->last_logout_time;
318   -
319   - /*
320   - * Check le cas où le logout n'a pas été enregistré
321   - * (le user n'a pas fait logout, ça s'est fait tout seul par timeout)
322   - * => Dans ce cas, on ajoute à la durée totale le dernier temps de connexion last_connex_dur
323   - */
324   - if ($last_logout_time < $last_login_time) {
325   - $last_connex_dur = $current_user_stat->last_connex_dur;
326   - /*
327   - * (Optimisation): Si la dernière session a été très courte (<10s), on ne le comptabilise pas
328   - * => on décrémente le nb de connexions (passées)
329   - */
330   - if ($current_user_stat->connex_nb>0 && $last_connex_dur<10)
331   - $current_user_stat->connex_nb--;
332   - else
333   - $current_user_stat->connex_dur_tot += $last_connex_dur;
334   - }
335   -
336   - // On met à jour le champs last_login_time, RAZ last_connex_dur, et incrémente le nb de connexions
337   - $current_user_stat->last_login_time = $now;
338   - $current_user_stat->last_connex_dur = 0;
339   - // et 1 NOUVELLE connexion de plus, 1 !
340   - $current_user_stat->connex_nb++;
341   - //debug($current_user_stat);
342   - // On sauvegarde en table
343   - if (! $table_stats->save($current_user_stat)) {
344   - echo "Impossible de sauvegarder une stat sur login !";
345   - debug($current_user_stat->getErrors());
346   - debug($current_user_stat);
347   - exit;
348   - }
349   - /*
350   - $query = $table_stats->findById($stat_id);
351   - if ($query->isEmpty()) {
352   - debug("no");
353   - // record doesn't exist
354   - }
355   - else {
356   - debug("yes");
357   - }
358   - */
359   - } // _updateStatsForCurrentUserOnLogin()
360   -
361 275 /*
362   - * Mise à jour des stats pour ce user (et pour l'année courante) durant la session, à chaque action
363   - * => on met à jour son temps de connexion
  276 + * Mise à jour des stats pour le user courant ($user_infos) (et pour l'année courante)
  277 + * au moment de l'événement $event_name
364 278 */
365   - public function updateStatsForCurrentUserDuringSession($session_user = null) {
366   -
367   - //debug("ici");
368   - //exit;
369   - // Current user
370   - //$user_id = $this->u->id;
371   - //debug($session_user);
372   - $user_id = $this->_getCurrentUserEntityFromSession($session_user)->id;
373   - //debug($user_id);
374   -
375   - // On récupère la Stat de ce user
376   - $now = new FrozenTime();
377   - //debug($last_login_time);
378   - $year = $now->format('yy');
379   - //debug($year);
380   - $table_stats = $this->Users->Stats;
381   - $stat_id = [$year,$user_id];
382   - //debug($stat_id);
383   - $current_user_stat = $table_stats->get($stat_id);
384   -
385   - // On met à jour le temps de connexion
386   - $connex_duration = $now->diff($current_user_stat->last_login_time);
387   - //debug($connex_duration);
388   - //exit;
389   - $current_user_stat->last_connex_dur = $connex_duration->h*3600 + $connex_duration->i*60 + $connex_duration->s;
390   - //debug($current_user_stat->last_connex_dur);
391   -
392   - // On sauvegarde en table
393   - if (! $table_stats->save($current_user_stat)) {
394   - echo "Impossible de sauvegarder une stat durant la session !";
395   - debug($current_user_stat->getErrors());
396   - debug($current_user_stat);
397   - exit;
398   - }
399   -
400   - } // updateStatsForCurrentUserDuringSession()
401   -
402   - /*
403   - * Mise à jour des stats pour ce user (et pour l'année courante) au moment du logout
404   - * => on enregistre son heure de dé-connexion
405   - * => on calcule son temps de connexion et on l'ajoute au champ qui totalise le temps de connexion : connex_dur_tot
406   - */
407   - private function _updateStatsForCurrentUserOnLogout() {
408   -
409   - // Current user
410   - $user_id = $this->u->id;
411   -
412   - $last_logout_time = new FrozenTime();
413   - //debug($last_login_time);
414   - $year = $last_logout_time->format('yy');
415   - //debug($year);
416   -
417   - // On récup la stat de ce user (pour cette année)
418   - // Normalement, elle doit exister puisque il y a déjà eu login !
419   - // TODO: Cas particulier où le login se fait le 31 décembre, et le logout l'année suivante => BUG !!!
420   - $table_stats = $this->Users->Stats;
421   - $stat_id = [$year,$user_id];
422   - $current_user_stat = $table_stats->get($stat_id);
423   - $last_login_time = $current_user_stat->last_login_time;
424   -
425   - // 1) On met à jour le champ last_logout_time
426   - $current_user_stat->last_logout_time = $last_logout_time;
427   -
428   - // 2) On met à jour le temps de connexion total (cumulé)
429   - // - on calcule le temps de connexion
430   - $connex_duration = $last_logout_time->diff($last_login_time);
431   - $connex_duration = $connex_duration->h*3600 + $connex_duration->i*60 + $connex_duration->s;
432   - //debug($last_login_time);
433   - //debug($last_logout_time);
434   - //debug($connex_dur_totation);
435   - // - on cumule ce temps au temps total
436   - //debug($current_user_stat->connex_dur_tot);
437   - //debug($connex_dur_totation);
438   - $current_user_stat->connex_dur_tot += $connex_duration;
439   - //debug($current_user_stat->connex_dur_tot);
440   -
441   - // On sauvegarde en table
442   - if (! $table_stats->save($current_user_stat)) {
443   - echo "Impossible de sauvegarder une stat sur logout !";
444   - debug($current_user_stat->getErrors());
445   - debug($current_user_stat);
446   - exit;
447   - }
448   - } // _updateStatsForCurrentUserOnLogout()
449   -
  279 + public function statsUpdateForCurrentUserWhen($session_user=null, $event_name) {
  280 + $user_id = ($event_name=='sur logout') ? $this->u->id : $this->_getCurrentUserEntityFromSession($session_user)->id;
  281 + //debug($user);
  282 + $this->Users->Stats->updateForUserWhen($user_id, $event_name);
  283 + }
450 284  
451 285  
452 286 /**
... ...
src/Model/Table/StatsTable.php
... ... @@ -5,6 +5,7 @@ use Cake\ORM\Query;
5 5 use Cake\ORM\RulesChecker;
6 6 use Cake\ORM\Table;
7 7 use Cake\Validation\Validator;
  8 +use Cake\I18n\FrozenTime;
8 9  
9 10 /**
10 11 * Stats Model
... ... @@ -96,4 +97,147 @@ class StatsTable extends Table
96 97  
97 98 return $rules;
98 99 }
  100 +
  101 +
  102 + private function getEntityForUser($user_id, $now) {
  103 + //$now = new FrozenTime();
  104 + //debug($last_login_time);
  105 + $year = $now->format('yy');
  106 + //debug($year);
  107 +
  108 + // On recup la Stat du user courant
  109 + //$table_stats = $this->Users->Stats;
  110 + $table_stats = $this;
  111 + $stat_id = [$year,$user_id];
  112 + $current_user_stat = null;
  113 + try {
  114 + // Si un enregistrement existe pour ce user (et cette année) => on le récupère
  115 + $current_user_stat = $table_stats->get($stat_id);
  116 + //debug("exists");
  117 + //$current_user_stat->last_logout_time = null;
  118 + } catch (\Cake\Datasource\Exception\RecordNotFoundException $e) {
  119 + //echo 'Exception reçue : ', $e->getMessage(), "\n";
  120 + // Pas d'enregistrement pour ce user (et cette année) => on le crée
  121 + //debug("new");
  122 + /*
  123 + $stat = [
  124 + //['year','user_id'] => [$year,$user->id],
  125 + //'(year,user_id)' => [$year,$user->id],
  126 + 'year' => $year,
  127 + 'user_id' => $user->id,
  128 + 'last_login_time' => $last_login_time,
  129 + ];
  130 + debug($stat);
  131 + */
  132 + //$stat_entity = $table_stats->newEntity($stat);
  133 + $current_user_stat = $table_stats->newEntity();
  134 + $current_user_stat->year = $year;
  135 + $current_user_stat->user_id = $user_id;
  136 + }
  137 + return $current_user_stat;
  138 + }
  139 +
  140 + private function saveStat($stat, $event_name) {
  141 + if (! $this->save($stat)) {
  142 + echo "Impossible de sauvegarder une stat $event_name !";
  143 + debug($stat->getErrors());
  144 + debug($stat);
  145 + exit;
  146 + }
  147 + }
  148 +
  149 + /*
  150 + * Mise à jour des stats pour le user courant (et pour l'année courante)
  151 + * au moment de l'événement $event_name qui peut être de 3 types :
  152 + * - 'sur login'
  153 + * - 'durant la session'
  154 + * - 'sur logout'
  155 + */
  156 + public function updateForUserWhen($user_id, $event_name) {
  157 +
  158 + // 1) Get (or create) stat for user $user_id
  159 + $now = new FrozenTime();
  160 + $current_user_stat = $this->getEntityForUser($user_id, $now);
  161 +
  162 + // 2) TT selon event $event_name
  163 +
  164 + /*
  165 + * - au LOGIN ( == 'sur login')
  166 + *
  167 + * => on enregistre son heure de connexion
  168 + * => on incrémente le nombre de connexions
  169 + *
  170 + */
  171 + if ($event_name == 'sur login') {
  172 + $last_login_time = $current_user_stat->last_login_time;
  173 + $last_logout_time = $current_user_stat->last_logout_time;
  174 + /*
  175 + * Check le cas où le logout n'a pas été enregistré
  176 + * (le user n'a pas fait logout, ça s'est fait tout seul par timeout)
  177 + * => Dans ce cas, on ajoute à la durée totale le dernier temps de connexion last_connex_dur
  178 + */
  179 + if ($last_logout_time < $last_login_time) {
  180 + $last_connex_dur = $current_user_stat->last_connex_dur;
  181 + /*
  182 + * (Optimisation): Si la dernière session a été très courte (<20s), on ne le comptabilise pas
  183 + * => on décrémente le nb de connexions (passées)
  184 + */
  185 + if ($current_user_stat->connex_nb>0 && $last_connex_dur<20)
  186 + $current_user_stat->connex_nb--;
  187 + else
  188 + $current_user_stat->connex_dur_tot += $last_connex_dur;
  189 + }
  190 + // On met à jour le champs last_login_time, RAZ last_connex_dur, et incrémente le nb de connexions
  191 + $current_user_stat->last_login_time = $now;
  192 + $current_user_stat->last_connex_dur = 0;
  193 + // et 1 NOUVELLE connexion de plus, 1 !
  194 + $current_user_stat->connex_nb++;
  195 + }
  196 +
  197 + /*
  198 + * - PENDANT la session (à chaque action) ( == 'durant la session')
  199 + *
  200 + * => on met à jour son temps de connexion
  201 + *
  202 + */
  203 + elseif ($event_name == 'durant la session') {
  204 + // On met à jour le temps de connexion
  205 + $connex_duration = $now->diff($current_user_stat->last_login_time);
  206 + //debug($connex_duration);
  207 + //exit;
  208 + $current_user_stat->last_connex_dur = $connex_duration->h*3600 + $connex_duration->i*60 + $connex_duration->s;
  209 + //debug($current_user_stat->last_connex_dur);
  210 + }
  211 +
  212 + /*
  213 + * - au LOGOUT ( == 'sur logout')
  214 + *
  215 + * => on enregistre son heure de dé-connexion
  216 + * => on calcule son temps de connexion et on l'ajoute au champ qui totalise le temps de connexion : connex_dur_tot
  217 + *
  218 + */
  219 + else {
  220 + $last_login_time = $current_user_stat->last_login_time;
  221 + // 1) On met à jour le champ last_logout_time
  222 + $current_user_stat->last_logout_time = $now;
  223 + // 2) On met à jour le temps de connexion total (cumulé)
  224 + // - on calcule le temps de connexion
  225 + $connex_duration = $now->diff($last_login_time);
  226 + $connex_duration = $connex_duration->h*3600 + $connex_duration->i*60 + $connex_duration->s;
  227 + //debug($last_login_time);
  228 + //debug($last_logout_time);
  229 + //debug($connex_dur_totation);
  230 + // - on cumule ce temps au temps total
  231 + //debug($current_user_stat->connex_dur_tot);
  232 + //debug($connex_dur_totation);
  233 + $current_user_stat->connex_dur_tot += $connex_duration;
  234 + //debug($current_user_stat->connex_dur_tot);
  235 + }
  236 +
  237 + // 3) On sauvegarde en table
  238 + $this->saveStat($current_user_stat, $event_name);
  239 +
  240 + } // updateForUserWhen()
  241 +
  242 +
99 243 }
... ...
src/Routing/Filter/SessionTimeoutFilter.php
... ... @@ -34,8 +34,9 @@ class SessionTimeoutFilter extends DispatcherFilter
34 34 //debug("iciii2");
35 35  
36 36 // Sinon, on met à jour les stats de connexion
  37 + (new UsersController())->statsUpdateForCurrentUserWhen($session_user, 'durant la session');
  38 + //(new UsersController())->statsUpdateForCurrentUserDuringSession($session_user);
37 39 //(new UsersController())->updateStatsForCurrentUserDuringSession();
38   - (new UsersController())->updateStatsForCurrentUserDuringSession($session_user);
39 40 //exit;
40 41  
41 42  
... ...
src/Template/Stats/index.ctp
... ... @@ -20,17 +20,34 @@ function getHourMnSecForDuration($duration_sec) {
20 20 }
21 21  
22 22  
23   -echo "<b>Temps de connexion moyen (sur tous les utilisateurs et toutes les années) : </b>";
  23 +// Moyenne générale pour le nombre de connexions et le temps de connexion
  24 +
24 25 $connex_nb_tot = 0;
25 26 $connex_dur_tot_tot = 0;
26 27 foreach ($stats as $stat) {
27 28 $connex_nb_tot += $stat->connex_nb;
28 29 $connex_dur_tot_tot += $stat->connex_dur_tot;
29 30 }
  31 +$connex_nb_year_avg = $connex_nb_tot / $stats->count();
30 32 $connex_dur_tot_avg = round($connex_dur_tot_tot / $connex_nb_tot);
31 33 //$connex_dur_tot_avg = intdiv($connex_dur_tot_tot , $connex_nb_tot);
32 34 //echo $connex_dur_tot_avg;
33 35 list($h,$m,$s) = getHourMnSecForDuration($connex_dur_tot_avg);
  36 +
  37 +//TODO: corriger ce calcul qui est faux (il faut ramener au nombre de mois effectifs de toutes les années incomplètes, assez compliqué...)
  38 +echo '<br>';
  39 +echo "<b>Nombre moyen de connexions d'un utilisateur par an (sur tous les utilisateurs et toutes les années) (approximatif si années incomplètes) : </b>";
  40 +echo round($connex_nb_year_avg, 0);
  41 +
  42 +//TODO: corriger ce calcul qui est faux (il faut ramener au nombre de mois effectifs de toutes les années incomplètes, assez compliqué...)
  43 +/*
  44 +echo '<br>';
  45 +echo "<b>Nombre moyen de connexions d'un utilisateur par mois (sur tous les utilisateurs et toutes les années) : </b>";
  46 +echo round($connex_nb_year_avg/12, 1);
  47 +*/
  48 +
  49 +echo '<br>';
  50 +echo "<b>Temps de connexion moyen d'un utilisateur (sur tous les utilisateurs et toutes les années) : </b>";
34 51 echo "$h h $m mn $s sec";
35 52 echo "<br>";echo "<br>";
36 53  
... ...
tests/TestCase/Controller/General.php
... ... @@ -443,7 +443,7 @@ class General extends TestCase {
443 443 ];
444 444 $this->session($authType);
445 445 //$this->request->getSession()->write($authType);
446   - (new UsersController())->_updateStatsForCurrentUserOnLogin($user['Auth']['User']);
  446 + (new UsersController())->statsUpdateForCurrentUserOnLogin($user['Auth']['User']);
447 447  
448 448  
449 449 }
... ...