userHasRoleAtLeast('Utilisateur')) { * return false; * } * } * return true; * } */ /* * Toute première méthode appelée, * * AVANT authentification * */ public function initialize() { $this->myDebug("step 0A (specific): PagesController.initialize()"); parent::initialize(); $this->modelClass = false; // On autorise l'action add SANS authentification (unauthenticated) //$this->Auth->allow(['add']); //$this->LdapAuth->allow(['display']); } // (20200424 EP) public function beforeFilter(\Cake\Event\Event $event) { $this->myDebug("step 1A (specific): PagesController.beforeFilter()"); // On donne d'abord les autorisations par défaut de AppController parent::beforeFilter($event); // Puis on ajoute les autorisations spécifiques /* $path = func_get_args(); pr($path); $page = null; if (! empty($path[0])) $page = $path[0]; */ $pages_authorized_without_connexion = ['about', 'acls', 'changes', 'stats', 'notifications']; $this->action = $this->getActionPassed(); if ($this->action == "display") { $this->page = $this->request->getParam('pass.0'); // On autorise l'action display SANS connexion // mais seulement pour la page 'about' //if (in_array($path[0], ['about', 'tools'])) echo "yes"; else echo "no"; //if ( $this->page == 'about' ) $this->LdapAuth->allow(['display']); if ( in_array($this->page, $pages_authorized_without_connexion) ) $this->LdapAuth->allow(['display']); } } /* * @Override * * Initialisation des autorisations pour les actions spécifiques à ce controleur * */ protected function setAuthorizations() { // On supprime les autres actions par défaut (add, view, index, find) //foreach (array_keys($this->is_authorized_action[]) as $a) if ($a != 'display') unset($this->is_authorized_action[$a]); $this->is_authorized_action = []; // Action display 'about' (affichage de la page 'A propos') $this->setAuthorizationsForAction('display/about', 0); // Pages autorisées à tout le monde SANS connexion // - Autorisations $this->setAuthorizationsForAction('display/acls', 0); // - Nouveautés $this->setAuthorizationsForAction('display/changes', 0); // - Stats $this->setAuthorizationsForAction('display/stats', 0); // - Notifications $this->setAuthorizationsForAction('display/notifications', 0); // Action display 'home' (affichage de la page 'Accueil') $this->setAuthorizationsForAction('display/home', 0); // Action display 'tools' (affichage de la page 'menu Outils') // admin (+) only $this->setAuthorizationsForAction('display/tools', -1, ['admin'=>0, 'super'=>0]); $this->setAuthorizationsForAction('display/tools-sm', -1, ['admin'=>0, 'super'=>0]); //$this->setAuthorizationsForAction('display/tools', 0); //$this->setAuthorizationsForAction('display/tools-sm', 0); $this->setAuthorizationsForAction('display/printers', 0); // Superadmin only : // - Action display 'infos' (affichage de la page 'Informations techniques sur le serveur') $this->setAuthorizationsForAction('display/infos', -1, ['super'=>0]); // - Action display 'logs' (affichage des messages de log') $this->setAuthorizationsForAction('display/logs', -1, ['super'=>0]); } /* public function isAuthorized($user, $action=null, $id=null, $role=null, $userCname=null) { $this->myDebug("step 2A (specific): PagesController.isAuthorized(user)"); $this->myDebug("- user is:", $user); if ($this->action == 'display') { //$page = $this->request->getParam('pass.0'); // Action display SANS nom de page => on redirige sur '/' // (c'est à dire sur /pages/home, c'est à dire /pages/display/home) // cf config/routes.php qui définit l'action "display" par défaut pour tout ce qui commence par pages/ if (! $this->page) { $this->redirect('/'); return false; } switch ($this->page) { // Page d'accueil autorisée à tous les profils (roles) case 'home': return true; // Page 'tools' seulement à partir de ADMIN // if (! $this->userHasRoleAtLeast('Administration')) { case 'tools': return $this->USER_IS_ADMIN_AT_LEAST(); //case 'tools': return $this->USER_IS_USER(); // Page 'infos' seulement pour SUPERADMIN //if (! $this->USER_IS_SUPERADMIN()) return $this->redirect('/'); case 'infos': return $this->USER_IS_SUPERADMIN(); } } // display // sinon, règle par défaut donnée par AppController return parent::isAuthorized($user); } */ /** * Displays a view * * @return void|\Cake\Network\Response * @throws \Cake\Network\Exception\NotFoundException When the view file could not * be found or \Cake\View\Exception\MissingTemplateException in debug mode. */ public function display() { // (EP 21/5/19) // On ne voit ce message que sur la page "about" // En effet, les autres pages nécessitant un login, // on est redirigé sur la page login et donc la methode login() du controleur UsersController // Du coup, il faut décommenter la ligne "exit" juste après pour voir ce message (évite la redirection). $this->myDebug("step 2: PagesController.display()"); $configuration = $this->confLabinvent; // Action display SANS nom de page => on redirige sur '/' // (c'est à dire sur /pages/home, c'est à dire /pages/display/home) // cf config/routes.php qui définit l'action "display" par défaut pour tout ce qui commence par pages/ ///$page = $this->request->getParam('pass.0'); /* if (! $page) $this->redirect('/'); */ $subpage = $this->request->getParam('pass.1'); //if (!$subpage) $subpage = null; /* $path = func_get_args(); if (! count($path)) return $this->redirect('/'); if ($path[0] === null) $path[0] = ''; $this->myDebug("- path is:"); $this->myDebug($path); $page = $subpage = null; if (! empty($path[0])) $page = $path[0]; if (! empty($path[1])) $subpage = $path[1]; */ $this->myDebug("- page is:"); $this->myDebug($this->page); $this->myDebug("- subpage is:"); $this->myDebug($subpage); /* // @todo : faire plus proprement, dans isAuthorized() // Si l'utilisateur n'est pas connecté, on le redirige vers la page login.ctp // sauf si l'action demandée est 'about' ou si le mode install est activé //if (in_array($path[0], ['about', 'tools'])) echo "yes"; else echo "no"; if ( $page != 'about' ) { // ! in_array($page, ['about', 'tools']) if ( // pas logged (pas authentifié) ! $this->LdapAuth->user($configuration->ldap_authenticationType)[0] //&& $path[0]!='about' //&& ! in_array($path[0], ['about', 'tools']) // et pas mode install && ! $configuration->mode_install ) { return $this->redirect([ 'controller' => 'users', 'action' => 'login' ]); } } */ /* // @todo : faire plus proprement, avec isAuthorized() // Page 'tools' seulement à partir de ADMIN if ($page == 'tools') { // if (! $this->userHasRoleAtLeast('Administration')) { if (! $this->USER_IS_ADMIN_AT_LEAST()) return false; //return $this->redirect('/'); } // Page 'infos' seulement pour SUPERADMIN if ($page == 'infos') { //if (! $this->USER_IS_SUPERADMIN()) return $this->redirect('/'); if (! $this->USER_IS_SUPERADMIN()) return false; } */ // Finalement, on affiche la $page demandée (avec render()) $this->set('page', $this->page); $this->set(compact('subpage')); // - Page d'ACCUEIL if ($this->page=='home') { $this->set('HAS_ORDER_BUTTON',self::hasOrderButton()); } // - Page des LOGS // /pages/logs?level=info if ($this->page=='logs') { $info_levels = ['info','debug','notice']; $error_levels = ['warning', 'error', 'critical', 'alert', 'emergency']; // Paar défaut, level = INFO $level = 'Info'; $level_arg = $this->request->getQuery('level'); if ($level_arg!==null && in_array($level_arg, array_merge($info_levels,$error_levels))) $level=$level_arg; //debug($level); $this->set(compact('level', 'info_levels', 'error_levels')); } // - Page des AUTORISATIONS et NOTIFICATIONS if ($this->page=='acls' || $this->page=='notifications') { $lab_name = $this->confLabinvent->labNameShort; if (!$lab_name) $lab_name = 'NOM_DU_LABO'; $this->set(compact('lab_name')); $this->set(compact('configuration')); } // - Page des STATISTIQUES if ($this->page=='stats') $this->page_stats_set_variables(); // - Page des OUTILS if ($this->page=='tools') { // Mode 'SA a tous les droits' $no_limit_mode = $this->confLabinvent->mode_nolimit; $this->set(compact('no_limit_mode')); } //debug(implode('/', $path)); //debug(implode('/', array($page,$subpage))); try { //$this->render(implode('/', $path)); //$this->render("$page/$subpage"); $this->render($subpage ? $this->page.'/'.$subpage : $this->page); //$this->render(implode('/', array($page,$subpage))); } catch (MissingTemplateException $e) { if (Configure::read('debug')) throw $e; throw new NotFoundException(); } } // display() private function page_stats_set_variables() { // créer des FAKE DATA pour tester la fonctionnalité ? $TEST = true; $TEST = false; // Nb années demandées par l'utilisateur $nbyears = $this->request->getQuery('nbyears'); // Initialisation des variables nécessaires // - Données Totales (complètes) (tronquées à $nbyears) $tot = [ 'CREATED' => (int) 1, 'VALIDATED' => (int) 0, 'TOBEARCHIVED' => (int) 0, 'ARCHIVED' => (int) 0, 'suivis' => (int) 0, 'prets' => (int) 0 ]; // - Donées Moyennes $avg = [ 'CREATED' => (int) 1, 'VALIDATED' => (int) 0, 'TOBEARCHIVED' => (int) 0, 'ARCHIVED' => (int) 0, 'suivis' => (int) 0, 'prets' => (int) 0 ]; // - Année en cours $now = new \DateTime('now'); //debug($now); // 2020 en 2020 $current_year = (int) $now->format('Y'); // - Données par Année $years = [ $current_year => [ 'CREATED' => (int) 1, 'VALIDATED' => (int) 0, 'TOBEARCHIVED' => (int) 0, 'ARCHIVED' => (int) 0, 'suivis' => (int) 0, 'prets' => (int) 0 ] ]; // Tables $materiels = TableRegistry::getTableLocator()->get('Materiels'); $suivis = TableRegistry::getTableLocator()->get('Suivis'); $prets = TableRegistry::getTableLocator()->get('Emprunts'); $associated_entities = ['suivis','prets']; $fk = 'materiel_id'; // Tous les matos qui ont une date d'achat non nulle $all_matos = $materiels->find()->where(['year(date_acquisition) >' => 0]); // On ne fait pas de stats s'il n'y a aucun matériel dans la BD if ($all_matos->count() == 0) { $year_min = $current_year; //$nbyears = 0; $this->set(compact('current_year', 'year_min', 'nbyears', 'tot', 'avg', 'years')); return; } // - Année min //$year_min = $materiels->find()->min(['year(date_acquisition)']); //$matos_year_min = $materiels->find()->where(['year(date_acquisition) >' => 0]) $matos_year_min = $all_matos->cleanCopy()->min(function($matos) { return $matos->date_acquisition->format('Y'); }); $year_min = (int) $matos_year_min->date_acquisition->format('Y'); // - Nb années au total : au moins 1 $nbyears_max = $current_year - $year_min + 1; // $nbyears demandé par l'utilisateur, par défaut TOUTES $nbyears = ( is_numeric($nbyears) && $nbyears>0 ) ? round($nbyears) : $nbyears_max; //debug($nbyears); // - Nb annnées à traiter (entre 1 et $nbyears_max) // ($nbyears=null si pas passé en paramètre) // ($nbyears='' si passé en paramètre mais sans valeur '?nbyears=') //$nbyears = $nbyears ? abs((int)$nbyears) : $nbyears_max; //debug($nbyears); $nbyears = min($nbyears,$nbyears_max); //debug($nbyears); //debug($nbyears); // Si on est au max (avec max>2), on enlève la 1ère et la dernière années (car a priori incomplètes) //sif ($nbyears==$nbyears_max && $nbyears>2) $nbyears -= 2; // Nouvelle année min $year_min = $current_year-$nbyears + 1; // Nouveau $all_matos, en tronquant à $nbyears $all_matos = $materiels->find() ->where(['year(date_acquisition) <=' => $current_year]) ->where(['year(date_acquisition) >=' => $year_min]); $all_matos_ids = $all_matos->cleanCopy()->select(['id']); /* $statuses = [ 'CREATED' => 'created', 'VALIDATED' => 'date_validated', 'ARCHIVED' => 'date_archived' ]; */ $statuses = [ 'CREATED', 'VALIDATED', 'TOBEARCHIVED', 'ARCHIVED' ]; // - tot : Données Totales (complètes) (tronquées à $nbyears) foreach ($statuses as $status) { $all_matos_copy = $all_matos->cleanCopy(); // Tous les matos qui ont une date d'achat non nulle if ($status != 'CREATED') $all_matos_copy->where(['status' => $status]); $tot[$status] = $all_matos_copy->count(); } // Suivis et Prets // Nb materiels qui ont des suivis (i.e. qui ont au moins 1 suivi) foreach ($associated_entities as $e) { //$nb_matos_suivis = $suivis->find() $tot[$e] = $$e->find() // materiel_id not null ->where(["$fk >" => 0]) ->select([$fk]) ->distinct([$fk]) ->where(["$fk IN" => $all_matos_ids]) ->count(); } /* // - tot2 : Données Totales Partielles (= tot sauf 1ère et dernière années) $all_matos2 = $materiels ->find() ->where(['year(date_acquisition) <' => $current_year]) ->where(['year(date_acquisition) >' => $current_year-$nbyears]); $all_matos_ids2 = $all_matos2->cleanCopy()->select(['id']); $tot2 = []; foreach ($statuses as $status) { $all_matos_copy = $all_matos2->cleanCopy(); // Tous les matos qui ont une date d'achat non nulle if ($status != 'CREATED') $all_matos_copy->where(['status' => $status]); $tot2[$status] = $all_matos_copy->count(); } // Suivis et Prets // Nb materiels qui sont suivis (i.e. qui ont au moins 1 suivi) foreach ($associated_entities as $e) { //$nb_matos_suivis = $suivis->find() $tot2[$e] = $$e->find() // materiel_id not null ->where(["$fk >" => 0]) ->select([$fk]) ->distinct([$fk]) ->where(["$fk IN" => $all_matos_ids2]) ->count(); } */ // - Donées Moyennes (avg) /* $avg['CREATED'] = 10; $avg['VALIDATED'] = 7; $avg['TOBEARCHIVED'] = 1; $avg['ARCHIVED'] = 1; */ foreach ($statuses as $status) { $avg[$status] = round($tot[$status]/$nbyears, 1); /* * (EP) * J'obtiens pas le meme resultat avec cette methode... * Peut-être que ca compte pas les années où il n'y a rien (0) */ /* //$all_matos = $materiels->find(); //$all_matos = $materiels->find()->where(['year(date_acquisition) >' => 0]); //->groupBy('year(date_acquisition)'); $all_matos_copy = $all_matos->cleanCopy(); if ($status != 'CREATED') $all_matos_copy->where(['status' => $status]); $avg[$status] = $all_matos_copy //->groupBy('year(date_acquisition)'); ->countBy(function($matos) { return $matos->date_acquisition->format('Y'); }) ->avg(); //->toList(); //->toArray(); //->count(); $avg[$status] = round($avg[$status]); */ } // Suivis et Prets // Nb materiels qui sont suivis (i.e. qui ont au moins 1 suivi) foreach ($associated_entities as $e) { $avg[$e] = round($tot[$e]/$nbyears, 1); /* $nb_matos_having_entity = $$e->find() // materiel_id not null ->where(["$fk >" => 0]) ->select([ 'year' => 'YEAR(created)' ]) ->group('year') ->toArray(); //->groupBy(function($entity) { ->group(function($entity) { return $entity->created->format('Y'); }) ->distinct([$fk]) ->count() ->avg(); $avg[$e] = $nb_matos_having_entity; */ //debug($nb_matos_having_entity); } // - Données par Année $all_matos = $materiels->find(); for ($y=$current_year ; $y>=$year_min ; $y--) { ////debug($y); $all_matos_for_year = $all_matos->cleanCopy()->where(['year(date_acquisition)' => $y]); ////debug($all_matos_for_year->count()); // - statut par année try { foreach ($statuses as $status) { /* $all_matos_for_year = $materiels->find(); ->where(['year(date_acquisition)' => $y]); $all_matos_for_year = $all_matos->cleanCopy()->where(['year(date_acquisition)' => $y]); */ $all_matos_for_year_and_status = $all_matos_for_year->cleanCopy(); if ($status != 'CREATED') $all_matos_for_year_and_status->where(['status' => $status]); $years[$y][$status] = $all_matos_for_year_and_status->count(); } } catch (\PDOException $e) { debug("Mauvais format de requete SQL (PagesController/stats statuses), Exception PDO générée !"); exit; } ////debug($years); // Suivis et Prets, par année $all_matos_suivis_for_year = $all_matos_for_year->cleanCopy(); foreach ($associated_entities as $e) try { ////debug($e); //debug($$e->find()->count()); /* * SQL equivalent : à tester... * * SELECT COUNT(DISTINCT(suivis.materiel_id)) FROM suivis LEFT JOIN materiels * ON suivis.materiel_id = materiels.id * WHERE YEAR(materiels.date_acquisition) = $y * * $years[$y]['suivis'] = $suivis->find()... * puis * $years[$y]['prets'] = $prets->find()... */ $years[$y][$e] = $$e // Tous les suivis/emprunts... ->find() // ... et leur materiel associé... ->leftJoinWith('Materiels') // ... LEFT JOIN ON (suivis.materiel_id = materiels.id) ... // ou emprunts.materiel_id //->enableAutoFields(true) // ... (uniquement les materiels de l'année $y) ... ->where(['year(date_acquisition)' => $y]) // ... en ne gardant qu'1 seul suivi/emprunt par materiel (meme si ce materiel en a plusieurs) ... ->distinct(['materiel_id']) // ... et enfin, on compte le nombre de suivis/emprunts (total pour l'année $y) ->count(); //->toArray(); //$all_matos_for_year //->contain(['Suivis']) //->select(['id', 'count_suivis => count(suivis)']) //->where(['count_suivis >' => 0]) //->count(); } catch (\PDOException $ex) { debug("Mauvais format de requete SQL (PagesController/stats suivis/prets), Exception PDO générée !"); debug($ex); exit; } //debug($years[$y]['suivis']); //$years[$y]['suivis'] = 3; //$years[$y]['prets'] = 4; } // foreach year //debug($years); // Set all variables pour la vue //$this->set(compact('current_year', 'year_min', 'tot', 'avg', 'years', 'suivis', 'prets')); //$this->set(compact('current_year', 'year_min', 'nbyears', 'tot', 'tot2', 'avg', 'years')); // FAKE DATA POUR TEST LOCAL if ($TEST) { $current_year = 2021; $test_nb_years = 0; $test_nb_years = 1; $test_nb_years = 2; $test_nb_years = 3; $i_year = $current_year; $i_nbyears = 0; $years = []; /* $years[2019] = [ 'CREATED' => (int) 27, 'VALIDATED' => (int) 8, 'TOBEARCHIVED' => (int) 1, 'ARCHIVED' => (int) 1, 'suivis' => (int) 2, 'prets' => (int) 2 ]; */ // 1 year if ($test_nb_years > $i_nbyears) $years[$i_year] = [ 'CREATED' => (int) 27, 'VALIDATED' => (int) 8, 'TOBEARCHIVED' => (int) 1, 'ARCHIVED' => (int) 1, 'suivis' => (int) 2, 'prets' => (int) 2 ]; // 2 years if ($test_nb_years > $i_nbyears++) $years[--$i_year] = [ 'CREATED' => (int) 0, 'VALIDATED' => (int) 0, 'TOBEARCHIVED' => (int) 0, 'ARCHIVED' => (int) 0, 'suivis' => (int) 0, 'prets' => (int) 0 ]; // 3 years if ($test_nb_years > $i_nbyears++) $years[--$i_year] = [ 'CREATED' => (int) 27, 'VALIDATED' => (int) 8, 'TOBEARCHIVED' => (int) 1, 'ARCHIVED' => (int) 1, 'suivis' => (int) 2, 'prets' => (int) 2 ]; if ($test_nb_years > $i_nbyears++) $years[--$i_year] = [ 'CREATED' => (int) 27, 'VALIDATED' => (int) 8, 'TOBEARCHIVED' => (int) 1, 'ARCHIVED' => (int) 1, 'suivis' => (int) 2, 'prets' => (int) 2 ]; $nbyears = count($years); $year_min = $nbyears>0 ? min(array_keys($years)) : $current_year; $tot = [ 'CREATED' => (int) 27, 'VALIDATED' => (int) 8, 'TOBEARCHIVED' => (int) 1, 'ARCHIVED' => (int) 1, 'suivis' => (int) 2, 'prets' => (int) 2 ]; $avg = [ 'CREATED' => (float) 27, 'VALIDATED' => (float) 8, 'TOBEARCHIVED' => (float) 1, 'ARCHIVED' => (float) 1, 'suivis' => (float) 2, 'prets' => (float) 2 ]; debug($current_year); debug($year_min); debug($years); } // TEST DATA $this->set(compact('current_year', 'year_min', 'nbyears', 'tot', 'avg', 'years')); /* debug($tot); //echo json_encode($avg); debug($avg); debug($years); */ } // set_variables_for_page_stats() }