setTable('stats'); $this->setDisplayField('year'); $this->setPrimaryKey(['year', 'user_id']); $this->belongsTo('Users', [ 'foreignKey' => 'user_id', 'joinType' => 'INNER' ]); /* FK composite possible aussi, ex : $this->belongsTo('Students', [ 'foreignKey' => ['program_id', 'location_id', 'course_id'], ]); */ } /** * Default validation rules. * * @param \Cake\Validation\Validator $validator Validator instance. * @return \Cake\Validation\Validator */ public function validationDefault(Validator $validator) { $validator ->scalar('year') ->allowEmptyString('year', 'create'); $validator ->dateTime('last_login_time') ->allowEmptyDateTime('last_login_time'); $validator ->dateTime('last_logout_time') ->allowEmptyDateTime('last_logout_time'); $validator ->integer('connex_nb') ->allowEmptyString('connex_nb', false); $validator ->integer('connex_dur') ->allowEmptyString('connex_dur', false); return $validator; } /** * Returns a rules checker object that will be used for validating * application integrity. * * @param \Cake\ORM\RulesChecker $rules The rules object to be modified. * @return \Cake\ORM\RulesChecker */ public function buildRules(RulesChecker $rules) { $rules->add($rules->existsIn(['user_id'], 'Users')); /* Rule avec composite key : $rules->add($rules->existsIn([’site_id’, ’article_id’], ’articles’)) */ return $rules; } private function getEntityForUser($user_id, $now) { //$now = new FrozenTime(); //debug($last_login_time); $year = $now->format('Y'); // 2021 //debug("year");debug($year); // On recup la Stat du user courant //$table_stats = $this->Users->Stats; $table_stats = $this; $stat_id = [$year,$user_id]; $current_user_stat = null; try { // Si un enregistrement existe pour ce user (et cette année) => on le récupère $current_user_stat = $table_stats->get($stat_id); //debug("exists"); //$current_user_stat->last_logout_time = null; } catch (\Cake\Datasource\Exception\RecordNotFoundException $e) { //echo 'Exception reçue : ', $e->getMessage(), "\n"; // Pas d'enregistrement pour ce user (et cette année) => on le crée //debug("new"); /* $stat = [ //['year','user_id'] => [$year,$user->id], //'(year,user_id)' => [$year,$user->id], 'year' => $year, 'user_id' => $user->id, 'last_login_time' => $last_login_time, ]; debug($stat); */ //$stat_entity = $table_stats->newEntity($stat); $current_user_stat = $table_stats->newEntity(); $current_user_stat->year = $year; $current_user_stat->user_id = $user_id; } return $current_user_stat; } private function saveStat($stat, $event_name) { if (! $this->save($stat)) { echo "Impossible de sauvegarder une stat $event_name !"; debug($stat->getErrors()); debug($stat); exit; } } /* * Mise à jour des stats pour le user courant (et pour l'année courante) * au moment de l'événement $event_name qui peut être de 3 types : * - 'sur login' * - 'durant la session' * - 'sur logout' */ public function updateForUserWhen($user_id, $event_name) { // 1) Get (or create) stat for user $user_id $now = new FrozenTime(); //debug("now");debug($now); $current_user_stat = $this->getEntityForUser($user_id, $now); // 2) TT selon event $event_name /* * - au LOGIN ( == 'sur login') * * => on enregistre son heure de connexion * => on incrémente le nombre de connexions * */ if ($event_name == 'sur login') { $last_login_time = $current_user_stat->last_login_time; $last_logout_time = $current_user_stat->last_logout_time; /* * Check le cas où le logout n'a pas été enregistré * (le user n'a pas fait logout, ça s'est fait tout seul par timeout) * => Dans ce cas, on ajoute à la durée totale le dernier temps de connexion last_connex_dur */ if ($last_logout_time < $last_login_time) { $last_connex_dur = $current_user_stat->last_connex_dur; /* * (Optimisation): Si la dernière session a été très courte (<20s), on ne le comptabilise pas * => on décrémente le nb de connexions (passées) */ if ($current_user_stat->connex_nb>0 && $last_connex_dur<20) $current_user_stat->connex_nb--; else $current_user_stat->connex_dur_tot += $last_connex_dur; } // On met à jour le champs last_login_time, RAZ last_connex_dur, et incrémente le nb de connexions $current_user_stat->last_login_time = $now; $current_user_stat->last_connex_dur = 0; // et 1 NOUVELLE connexion de plus, 1 ! $current_user_stat->connex_nb++; } /* * - Pendant la session OU BIEN au logout * * => on met à jour son temps de connexion last_connex_dur * * Si logout : * => on ajoute son temps de connexion (last_connex_dur) au champ qui totalise ce temps (connex_dur_tot) * => on enregistre son heure de dé-connexion (last_logout_time) * */ else { // - On met à jour le temps de connexion $last_login_time = $current_user_stat->last_login_time; $connex_duration = $now->diff($last_login_time); $connex_duration = $connex_duration->h*3600 + $connex_duration->i*60 + $connex_duration->s; $current_user_stat->last_connex_dur = $connex_duration; if ($event_name == 'sur logout') { // 1) On met à jour le champ last_logout_time $current_user_stat->last_logout_time = $now; // 2) On met à jour le temps de connexion total (cumulé) $current_user_stat->connex_dur_tot += $connex_duration; } } // Pendant la session OU BIEN au logout // 3) Sauvegarde en table $this->saveStat($current_user_stat, $event_name); } // updateForUserWhen() }