getElementParDefaut($param); } else { $methode = self::PREFIXE.$type; if (method_exists($this, $methode)) { array_shift($param); $info = $this->$methode($param); } else { $this->messages[] = "Le type d'information demandé '$type' n'est pas disponible."; } } $this->envoyer($info,$this->type_mime); } public function getExportStationJson() { $donnees = $this->getExportStation(); $donnees_formatees = $this->formaterListeStationPourExportJson($donnees); $this->type_mime = 'application/json'; return $donnees_formatees; } public function getExportEvolutionPhenologiqueJson() { $evenements = explode(',', $_GET['evenements']); $condition_evenements = ''; $sous_condition_evenements = []; foreach($evenements as $evenement) { $sous_condition_evenements[] = 'oo_ce_evenement = '.$this->proteger($evenement); } $condition_evenements .= '('.implode(' OR ', $sous_condition_evenements).')'; $condition_espece = 'oi_ce_espece = '.$this->proteger($_GET['espece']); $formule_moyenne_date = 'FROM_UNIXTIME(AVG(UNIX_TIMESTAMP((oo_date))))'; $requete = 'SELECT '.$formule_moyenne_date.' as date_moyenne, oo_ce_evenement FROM ods_observations oo '. 'LEFT JOIN ods_individus oi ON oi_id_individu = oo_ce_individu '. 'INNER JOIN ods_especes oe ON oe.oe_espece_active = 1 '. 'AND oe.oe_id_espece = oi_ce_espece '. 'WHERE oo_date != "0000-00-00" AND DAY(oo_date) != "00" '. 'AND '.$condition_espece.' '. 'AND '.$condition_evenements.' '. 'AND oo_ce_participant != "4" AND oo_ce_participant != 1 AND oo_absence_evenement = "0" '. 'GROUP BY YEAR(oo_date), oo_ce_evenement '. 'ORDER BY oo_date DESC'; $donnees = $this->executerRequete($requete); $donnees_formatees = []; foreach($donnees as $donnee) { $stade = $donnee['oo_ce_evenement']; if(empty($donnees_formatees[$stade])) { $donnees_formatees[$stade] = ['x' => [], 'y' => []]; } $date_time = strtotime($donnee['date_moyenne']); // on ramène grossièrement la date de l'année à une valeur numérique // ex: le 15 janvier devient 1.5 $nb_jours_dans_mois = date(' t ', strtotime($date_time)); $jour_mois_num = (date('d', $date_time)/$nb_jours_dans_mois)+date('m', $date_time); $donnees_formatees[$stade]['x'][] = $donnee['date_moyenne']; $donnees_formatees[$stade]['y'][] = $jour_mois_num; $donnees_formatees[$stade]['text'][] = date('d/m/Y', strtotime($donnee['date_moyenne'])); } $this->type_mime = 'application/json'; return $donnees_formatees; } public function getExportPhasesPhenologiquesJson() { $evenements = $this->obtenirValeursListeParAbreviation(self::ABBR_LISTE_EVENEMENTS); $evenements_a_regrouper = []; foreach($evenements as $evenement) { $nom_evenement = $evenement['ot_cle']; $nom_evenement_tab = explode('_', $nom_evenement); // évènement à plusieurs stades (evenement_floraison_stade_11 par exemple) if(count($nom_evenement_tab) == 4) { // on fait pointer la clé de l'évènement vers sont groupe (dans l'exemple floraison) $evenements_a_regrouper[$evenement['ot_id_triple']] = $nom_evenement_tab[1]; } else { // sinon ce sont des evènements à un seul stade (comme premiere_apparition) // auquel cas on supprime juste le suffixe evenement_ $evenements_a_regrouper[$evenement['ot_id_triple']] = str_replace('evenement_', '',$nom_evenement); } } $requete = 'SELECT oo_date, oo_ce_evenement FROM ods_observations oo '. 'LEFT JOIN ods_individus oi ON oi_id_individu = oo_ce_individu '. 'INNER JOIN ods_especes oe ON oe.oe_espece_active = 1 '. 'AND oe.oe_id_espece = oi_ce_espece '; // si on indique zéro on peut obtenir toutes les années if(isset($_GET['annee']) && $_GET['annee'] != 0) { $requete .= 'AND YEAR(oo_date) = '.$this->proteger($_GET['annee']).' '; } $requete .= 'WHERE oo_date != "0000-00-00" AND DAY(oo_date) != "00" '. 'AND oi_ce_espece = '.$this->proteger($_GET['espece']).' '. 'AND oo_ce_participant != "4" AND oo_ce_participant != 1 AND oo_absence_evenement = "0" '. 'ORDER BY oo_date DESC'; $donnees = $this->executerRequete($requete); $donnees_formatees = []; // Regroupement d'évenements allant ensemble (ex.: début et fin de floraison) foreach($donnees as $donnee) { $cle_groupe_evenements = $evenements_a_regrouper[$donnee['oo_ce_evenement']]; if(empty($donnees_formatees[$cle_groupe_evenements])) { $donnees_formatees[$cle_groupe_evenements] = []; } $date_time = strtotime($donnee['oo_date']); // on ramène la date de l'année à une valeur numérique // ex: le 15 janvier devient 1.5 pour pouvoir afficher ça plus simplement // sur le graphique d'arrivée qui n'aura à travailler qu'avec des nombres $nb_jours_dans_mois = date(' t ', strtotime($date_time)); $jour_mois_num = (date('d', $date_time)/$nb_jours_dans_mois)+date('m', $date_time); // on garde 7 chiffres après la virgule car côté client on a besoin de s'assurer d'une largeur // suffisante lors du calcul de la légende de chaque point. // En fait la largeur du nombre détermine la largeur de son conteneur affiché lorsdu hover sur le point, // or il est nécessaire de remplacer cette légende lors de l'affichage (qui contient un nombre) par une vraie date. // ceci est une limitation plot.ly (côté client) qui n'offre pas de fonction de formatage $jour_mois_num = number_format($jour_mois_num, 7); $donnees_formatees[$cle_groupe_evenements]['x'][] = $jour_mois_num; $donnees_formatees[$cle_groupe_evenements]['text'][] = date('d/m/Y', strtotime($donnee['oo_date'])); $donnees_formatees[$cle_groupe_evenements]['text_index']["'".$jour_mois_num."'"] = date('d/m/Y', strtotime($donnee['oo_date'])); } $this->type_mime = 'application/json'; return $donnees_formatees; } public function getExportStation($start = null,$limit = null, $order_by = 'oo_date') { $id_demo = $this->config['appli']['id_participant_demo']; $requete_selection_stations = 'SELECT * FROM ods_stations WHERE os_ce_participant != '.$this->proteger($id_demo); $res_selection_stations = $this->executerRequete($requete_selection_stations); return $res_selection_stations; } public function getExportUtilisateurCsv() { $controle = new ControleUtilisateur($this->config); $controle->authentifierAdmin(); $gestionnaire_utilisateurs = new OdsUtilisateur($this->config); $utilisateurs = $gestionnaire_utilisateurs->getListeUtilisateurAvecInfosComplementairesFormateeId(); $utilisateurs_formates = array(); $premiere_annee = 2006; $nb_obs = $this->compterObservationsParUtilisateur(); $annees = array(); foreach ($utilisateurs as $id => $utilisateur) { $utilisateur_formate = array( 'id' => isset($utilisateur['uid']) ? $utilisateur['uid'] : '', 'pseudo' => isset($utilisateur['name']) ? $utilisateur['name'] : '', 'mail' => isset($utilisateur['mail']) ? $utilisateur['mail'] : '', 'nom' => isset($utilisateur['profile_nom']) ? $utilisateur['profile_nom'] : '', 'prenom' => isset($utilisateur['profile_prenom']) ? $utilisateur['profile_prenom'] : '', 'code postal' => isset($utilisateur['profile_code_postal']) ? $utilisateur['profile_code_postal'] : '', 'ville' => isset($utilisateur['profile_ville']) ? $utilisateur['profile_ville'] : '', 'type' => isset($utilisateur['profile_type']) ? $utilisateur['profile_type'] : '', 'date inscription' => isset($utilisateur['created']) ? date('d/m/Y', $utilisateur['created']) : '', ); for($i = $premiere_annee; $i <= date('Y'); $i++) { $annees['annee '.$i] += isset($nb_obs[$utilisateur['uid']]) && isset($nb_obs[$utilisateur['uid']][$i]) ? $nb_obs[$utilisateur['uid']][$i] : '0'; $utilisateur_formate['annee '.$i] = isset($nb_obs[$utilisateur['uid']]) && isset($nb_obs[$utilisateur['uid']][$i]) ? $nb_obs[$utilisateur['uid']][$i] : '0'; } $utilisateurs_formates[] = $utilisateur_formate; } $ligne_total_obs = array( 'id' => '', 'pseudo' => '', 'mail' => '', 'nom' => '', 'prenom' => '', 'code postal' => '', 'ville' => '', 'type' => '', 'date inscription' => '' ); $ligne_total_obs = array_merge($ligne_total_obs, $annees); $utilisateurs_formates[] = $ligne_total_obs; $csv = $this->convertirTableauAssocVersCSV($utilisateurs_formates); $this->envoyerFichier($csv, 'utilisateurs'); } private function compterObservationsParUtilisateur() { $requete = 'SELECT COUNT(*) as nb_obs, oo_ce_participant as participant, YEAR(oo_date) as annee '. 'FROM `ods_observations` WHERE oo_date != "0000-00-00" GROUP BY oo_ce_participant, YEAR(oo_date)'; $res_selection_obs = $this->executerRequete($requete); $stats = array(); foreach ($res_selection_obs as $obs_nb) { $stats[$obs_nb['participant']][$obs_nb['annee']] = $obs_nb['nb_obs']; } return $stats; } public function formaterListeStationPourExportJson($tableau_stations_infos) { $gestionnaire_especes = new OdsEspece($this->config); $gestionnaire_communes = new OdsCommune($this->config); $gestionnaire_utilisateurs = new OdsUtilisateur($this->config); $especes = $gestionnaire_especes->getToutesEspeces(); $evenements = $this->obtenirValeursListeParAbreviation(self::ABBR_LISTE_EVENEMENTS); $milieux = $this->obtenirValeursListeParAbreviation(self::ABBR_LISTE_MILIEUX); $utilisateurs = $gestionnaire_utilisateurs->getListeUtilisateurAvecInfosComplementairesFormateeId(); $communes = $gestionnaire_communes->obtenirCommunesLieesAStationIndexeesCodeInsee(); $resultats_formates = array(); $stats = array('total' => count($tableau_stations_infos)); foreach($tableau_stations_infos as $stations_infos) { $commune = isset($communes[$stations_infos['os_ce_commune']]['oc_nom']) ? $communes[$stations_infos['os_ce_commune']]['oc_nom'] : ''; $id_station = $stations_infos['os_id_station']; $resultats_formates[$id_station]['nom'] = $stations_infos['os_nom']; $resultats_formates[$id_station]['code_commune'] = is_numeric($stations_infos['os_ce_commune']) ? substr($stations_infos['os_ce_commune'], 0, 2) : ''; $resultats_formates[$id_station]['nom_commune'] = $commune; $resultats_formates[$id_station]['latitude'] = $stations_infos['os_latitude']; $resultats_formates[$id_station]['longitude'] = $stations_infos['os_longitude']; $resultats_formates[$id_station]['altitude'] = $stations_infos['os_altitude']; $resultats_formates[$id_station]['type_participant'] = 'Particulier'; if(isset($utilisateurs[$stations_infos['os_ce_participant']])) { $participant = $utilisateurs[$stations_infos['os_ce_participant']]; $resultats_formates[$id_station]['participant']['id'] = $participant['uid']; $resultats_formates[$id_station]['participant']['nom'] = $participant['name']; $resultats_formates[$id_station]['type_participant'] = isset($participant['profile_type']) ? $participant['profile_type'] : 'Particulier'; } else { $resultats_formates[$id_station]['participant']['id'] = null; $resultats_formates[$id_station]['participant']['nom'] = 'Anonyme'; $resultats_formates[$id_station]['type_participant'] = 'Particulier'; } if(isset($stats[$resultats_formates[$id_station]['type_participant']])) { $stats[$resultats_formates[$id_station]['type_participant']]++; } else { $stats[$resultats_formates[$id_station]['type_participant']] = 1; } } $resultat = array('stats' => $stats, 'stations' => $resultats_formates); return $resultat; } public function getExportObservation($start = null,$limit = null, $order_by = 'oo_date') { $requete_selection_observations = 'SELECT oo.*, oi.*, os.*, oc.* FROM ods_observations oo'. ' LEFT JOIN ods_individus oi'. ' ON oi_id_individu = oo_ce_individu'. ' INNER JOIN ods_especes oe'. ' ON oe.oe_espece_active = 1 '. ' AND oe.oe_id_espece = oi_ce_espece '. ' LEFT JOIN ods_stations os'. ' ON oi_ce_station = os_id_station '. ' LEFT JOIN ods_communes oc'. ' ON os_ce_commune = oc_code_insee '; $requete_selection_observations .= $this->construireConditionRequete(); $requete_selection_observations .= ' ORDER BY oo_date DESC'; $res_selection_observations = $this->executerRequete($requete_selection_observations); return $res_selection_observations; } private function creerFiltreIdZoneGeo($valeurMasque) { $masque = ''; $dept = $valeurMasque; $dept = sprintf('%02s', $dept); $dept = sprintf("%-'_5s", $dept); $masque = " oc_code_insee LIKE ".$this->proteger($dept); return $masque; } public function construireConditionRequete() { $condition = ' WHERE oo_date != "0000-00-00" AND DAY(oo_date) != "00" AND '; foreach($_GET as $cle => $valeur) { switch($cle) { case 'type_espece': $condition .= 'oi_ce_espece IN (SELECT oe_id_espece FROM ods_especes WHERE oe_ce_type = '.$this->proteger($valeur).')'; break; case 'annee': if($this->anneesMultiplesDemandees($valeur)) { $valeur = rtrim($valeur,','); $condition .= 'YEAR(oo_date) IN ('.$valeur.')'; } else { $condition .= 'YEAR(oo_date) '; $condition .= ' = '.$this->proteger($valeur); } break; case 'mois': $condition .= 'MONTH(oo_date) <= '.$this->proteger($valeur); break; case 'espece': $condition .= 'oi_ce_espece IN ('.$valeur.') '; break; case 'evenement': $condition .= 'oo_ce_evenement = '.$this->proteger($valeur); break; case 'evenements': //$condition .= 'oo_ce_evenement IN ('.$this->proteger($valeur).')'; $evenements = explode(',', $valeur); $sous_condition_evenements = []; foreach($evenements as $evenement) { $sous_condition_evenements[] = 'oo_ce_evenement = '.$this->proteger($evenement); } $condition .= '('.implode(' OR ', $sous_condition_evenements).')'; break; case 'utilisateur': $condition .= 'oo_ce_participant = '.$this->proteger($valeur); break; case 'departement' : $condition .= $this->creerFiltreIdZoneGeo($valeur); break; case 'region' : $requete_association_region = 'SELECT * FROM ods_triples WHERE ot_ce_parent = 36 AND ot_valeur = '.$valeur; $listeAssociationRegions = $this->executerRequete($requete_association_region); $departements = array(); foreach ($listeAssociationRegions as $associationRegion) { $departements[] = $this->creerFiltreIdZoneGeo($associationRegion['ot_cle']); } $condition .= ' ('. implode(' OR ', $departements).')'; break; } $condition .= ' AND '; } $condition = rtrim($condition,'AND '); $id_demo = $this->config['appli']['id_participant_demo']; $id_admin = $this->config['appli']['id_participant_admin']; $condition .= ' AND oo_ce_participant != '.$id_demo; $condition .= ' AND oo_ce_participant != '.$id_admin; // par défaut les observations d'absence d'évènement ne sont pas incluses // sauf si on le demande explicitement if(empty($_GET['inclure-absences']) || $_GET['inclure-absences'] == 0) { $condition .= ' AND oo_absence_evenement = 0'; } return $condition; } private function anneesMultiplesDemandees($annee) { // un ensemble d'identifiants est une suite d'identifiants séparés par des virgules // sans virgule terminale $reg_exp = "/^(([0-9])+,)*([0-9])+$/"; return preg_match($reg_exp, $annee); } public function getExportObservationPlat() { // dans le csv les observations d'absence sont inclues par contre $_GET['inclure-absences'] = 1; $donnees = $this->getExportObservation(); $donnees_formatees = $this->formaterListeObservationPourExportCSV($donnees); return $donnees_formatees ; } public function getExportObservationJson() { $donnees = $this->getExportObservation(); $donnees_formatees = $this->formaterListeObservationPourExportJson($donnees); $this->type_mime = 'application/json'; return $donnees_formatees; } public function formaterListeObservationPourExportJson($tableau_observations_infos) { $gestionnaire_especes = new OdsEspece($this->config); $gestionnaire_communes = new OdsCommune($this->config); $especes = $gestionnaire_especes->getToutesEspeces(); $evenements = $this->obtenirValeursListeParAbreviation(self::ABBR_LISTE_EVENEMENTS); $milieux = $this->obtenirValeursListeParAbreviation(self::ABBR_LISTE_MILIEUX); $resultats_formates = array(); foreach($tableau_observations_infos as $observations_infos) { $id_espece = $observations_infos['oi_ce_espece']; if($id_espece == 0) { continue; } $nom_espece = $especes[$id_espece]['nom_scientifique']; $id_evenement = $observations_infos['oo_ce_evenement']; $chaine_evenement = $evenements[$id_evenement]['ot_cle']; $infos_evenement = $this->renvoyerInformationStadeAPartirChaineTriple($chaine_evenement); $date_observation_formatee = date($this->config['appli']['format_date'], strtotime($observations_infos['oo_date'])); $id_observation = $observations_infos['oo_id_observation']; $infos_formatees = array( 'date' => $date_observation_formatee, 'evenenement' => $infos_evenement['nom'], 'code_bbch' => $infos_evenement['numero'], 'nom_scientifique' => $nom_espece, 'id_espece' => $id_espece, 'participant' => $observations_infos['os_ce_participant'] ); $id_station = $observations_infos['oi_ce_station']; if(!isset($resultats_formates[$id_station])) { $resultats_formates[$id_station]['station'] = $observations_infos['os_nom']; $resultats_formates[$id_station]['code_commune'] = $observations_infos['os_ce_commune']; //$resultats_formates[$id_station]['nom_commune'] = $gestionnaire_communes->obtenirNomCommuneParCodeInsee($observations_infos['os_ce_commune']); $resultats_formates[$id_station]['latitude'] = $observations_infos['os_latitude']; $resultats_formates[$id_station]['longitude'] = $observations_infos['os_longitude']; $resultats_formates[$id_station]['altitude'] = $observations_infos['os_altitude']; if(isset($milieux[$observations_infos['os_ce_environnement']]['ot_valeur'])) { $resultats_formates[$id_station]['milieu'] = $milieux[$observations_infos['os_ce_environnement']]['ot_valeur']; } else { $resultats_formates[$id_station]['milieu'] = ''; } $resultats_formates[$id_station]['participant'] = $observations_infos['os_ce_participant']; } $resultats_formates[$id_station]['obs'][$id_observation] = $infos_formatees; } return $resultats_formates; } public function getFichierExportObservationCsv() { // dans le csv les observations d'absence sont inclues par contre $_GET['inclure-absences'] = 1; $donnees = $this->getExportObservation(); $donnees_formatees = $this->formaterListeObservationPourExportCSV($donnees); $chaine_csv = $this->convertirTableauAssocVersCSV($donnees_formatees); $this->envoyerFichier($chaine_csv); } public function formaterListeObservationPourExportCSV($tableau_observations_infos) { $gestionnaire_especes = new OdsEspece($this->config); $gestionnaire_communes = new OdsCommune($this->config); $gestionnaire_utilisateurs = new OdsUtilisateur($this->config); $especes = $gestionnaire_especes->getToutesEspeces(); $evenements = $this->obtenirValeursListeParAbreviation(self::ABBR_LISTE_EVENEMENTS); $milieux = $this->obtenirValeursListeParAbreviation(self::ABBR_LISTE_MILIEUX); $codes_insee_communes = array(); $resultats_formates = array(); foreach($tableau_observations_infos as $observations_infos) { $id_espece = $observations_infos['oi_ce_espece']; $nom_espece = $especes[$id_espece]['nom_scientifique']; $id_evenement = $observations_infos['oo_ce_evenement']; $chaine_evenement = $evenements[$id_evenement]['ot_cle']; $infos_evenement = $this->renvoyerInformationStadeAPartirChaineTriple($chaine_evenement); $date_observation_formatee = date($this->config['appli']['format_date'], strtotime($observations_infos['oo_date'])); $id_observation = $observations_infos['oo_id_observation']; $milieu = isset($milieux[$observations_infos['os_ce_environnement']]['ot_valeur']) ? $milieux[$observations_infos['os_ce_environnement']]['ot_valeur'] : ''; $infos_formatees = array( 'id_observation' => $id_observation, 'id_individu' => $observations_infos['oo_ce_individu'], 'commentaire_individu' => $observations_infos['oi_commentaire'], 'presence_evenement' => $observations_infos['oo_absence_evenement'] == 1 ? 'Absence' : 'Présence', 'date' => $date_observation_formatee, 'evenenement' => $infos_evenement['nom'], 'code_bbch' => $infos_evenement['numero'], 'nom_scientifique' => $nom_espece, 'station' => $observations_infos['os_nom'], 'code_commune' => $observations_infos['os_ce_commune'], 'nom_commune' => '', 'latitude' => $observations_infos['os_latitude'], 'longitude' => $observations_infos['os_longitude'], 'altitude' => $observations_infos['os_altitude'], 'milieu' => $milieu, 'id_participant' => $observations_infos['os_ce_participant'], 'pseudo_participant' => '', 'mail_participant' => '' ); $resultats_formates[] = $infos_formatees; if(is_numeric($observations_infos['os_ce_commune'])) { $codes_insee_communes[] = $observations_infos['os_ce_commune']; } } $correspondance_codes_insee_noms = $gestionnaire_communes->obtenirTableauNomsCommunesParTableauCodesInsee($codes_insee_communes); $correspondance_id_utilisateur = $gestionnaire_utilisateurs->getListeUtilisateurFormateeId(); foreach($resultats_formates as &$resultat) { if(isset($correspondance_codes_insee_noms[$resultat['code_commune']]) && trim($correspondance_codes_insee_noms[$resultat['code_commune']]) != '') { $resultat['nom_commune'] = $correspondance_codes_insee_noms[$resultat['code_commune']]; } $resultat['pseudo_participant'] = isset($correspondance_id_utilisateur[$resultat['id_participant']]) ? $correspondance_id_utilisateur[$resultat['id_participant']]['name'] : ''; $resultat['mail_participant'] = isset($correspondance_id_utilisateur[$resultat['id_participant']]) ? $correspondance_id_utilisateur[$resultat['id_participant']]['mail'] : ''; } return $resultats_formates; } public function convertirTableauAssocVersCSV($tableau) { $csv = ''; $colonnes = array_keys($tableau[0]); $csv .= implode(';',$colonnes).";\n"; foreach($tableau as $elements) { $ligne = ""; // parcours des cases de chaque ligne nécessaire car si on utilise implode // les valeurs vides ne sont pas prises et ça décale les colonnes foreach ($elements as $element) { $ligne .= '"'.$element.'";'; } $csv .= $ligne."\n"; } return $csv; } public function envoyerFichier($contenu, $nom = 'observations_export') { $nom_fichier = $nom.".csv"; $chemin_fichier = $this->config['appli']['chemin_fichiers_temp'].'/'.$nom_fichier; file_put_contents($chemin_fichier, $contenu); $contenu = file_get_contents($chemin_fichier); $taille_fichier = filesize($chemin_fichier); unlink($chemin_fichier); ini_set('zlib.output_compression','Off'); header('Pragma: public'); header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); header('Cache-Control: must-revalidate, pre-check=0, post-check=0, max-age=0'); header('Content-Tranfer-Encoding: none'); header('Content-Type: application/octetstream; name="'.$nom_fichier.'"'); header('Content-Disposition: attachement; filename="'.$nom_fichier.'"'); header('Content-Length: '.$taille_fichier); echo $contenu; exit(); } private function formaterInformationPourEnvoi($tableauinfos) { } } ?>