Subversion Repositories eFlore/Applications.cel

Compare Revisions

No changes between revisions

Ignore whitespace Rev 2220 → Rev 2221

/branches/v2.3-faux/jrest/services/LicenceUtilisateur.php
New file
0,0 → 1,52
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* Classe gérant l'acceptation de la licence utilisateur
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright © 2010, Aurélien Peronnet
*/
class LicenceUtilisateur extends Cel {
 
/**
* Fonction appelée sur un POST
*
* Accepte ou refuse la licence utilisateur, en mettant à jour la base de données pour
* l'utilisateur indiqué
*
* @param array $uid
* @param array $pairs
*/
function updateElement($uid,$pairs) {
if(!isset($uid[0]) && is_numeric($uid[0])) {
return;
}
if(!isset($pairs['licence'])) {
return;
}
$requete_acceptation_licence = 'UPDATE cel_utilisateurs_infos '.
'SET licence_acceptee = '.Cel::db()->proteger($pairs['licence']).
'WHERE id_utilisateur = '.Cel::db()->proteger($uid[0]);
$resultat_acceptation_licence = Cel::db()->executer($requete_acceptation_licence);
$resultat = false;
if($resultat_acceptation_licence) {
$resultat = "OK";
}
 
echo $resultat;
exit;
}
}
 
?>
/branches/v2.3-faux/jrest/services/ImageProvider.php
New file
0,0 → 1,69
<?php
/**
* PHP Version 5
*
* @category PHP
* @package papyrus_bp
* @author aurelien <aurelien@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/papyrus_bp/
*/
 
/**
* Classe fournissant des images au format demandé ou bien aux dimensions demandées
*
* in=utf8
* out=utf8
*
*/
class ImageProvider extends Cel {
function getElement($uid){
if(!isset($uid[0])) {
return;
}
$id_image = $uid[0];
$format = 'temp';
if(isset($_GET['format'])) {
$format = $_GET['format'];
}
if(isset($_GET['dimensions'])) {
$dimensions = $_GET['dimensions'];
} else {
if(isset($this->config['cel']['format_'.$format])) {
$dimensions = $this->config['cel']['format_'.$format];
}
}
$this->config['cel']['format_'.$format] = $dimensions;
$generateur_image = new ImageRecreation($this->config);
$infos_image = $generateur_image->obtenirImageEtInfosPourId($id_image);
if(!$infos_image) {
header('HTTP/1.0 404 Not Found');
exit;
}
$image_generee = $generateur_image->creerMiniatureImageSelonFormat($infos_image, $format);
header('Content-type: image/jpeg');
imagejpeg($image_generee);
exit;
}
private function estUneImageALaDemande() {
}
}
?>
/branches/v2.3-faux/jrest/services/InventoryExport.php
New file
0,0 → 1,167
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author David Delon <david@tela-botania.org>
* @author Aurélien Peronnet <aurelien@tela-botania.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
 
/**
* in:utf8
* out:iso8859
*
* Export vers feuille de calcul d'une selection de releves
*
*/
 
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(realpath(__FILE__))) . '/lib');
// la sortie est binaire (xls), mais OLE n'est pas compatible E_ALL en PHP-5.4
error_reporting(error_reporting() ^ E_STRICT);
require_once("lib/OLE.php");
require_once("lib/Spreadsheet/Excel/Writer.php");
 
class InventoryExport extends Cel {
 
private $extendSpreadsheetProductor;
 
function InventoryExport($config) {
 
parent::__construct($config);
 
$this->extendSpreadsheetProductor = new SpreadsheetProductor();
$this->extendSpreadsheetProductor->initSpreadsheet();
}
 
function getElement($uid){
 
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
$criteres = $_GET;
$chercheur_observations = new RechercheObservation($this->config);
 
// Creating a workbook
$workbook = new Spreadsheet_Excel_Writer();
$workbook->setVersion(8);
 
$workbook->send('liste.xls');
 
// Creating a worksheet
$worksheet = $workbook->addWorksheet('Liste');
$worksheet->setInputEncoding('utf-8');
$worksheet->write(0,0,'Espece');
$worksheet->write(0,1,'Numero nomenclatural');
$worksheet->write(0,2,'Nom retenu');
$worksheet->write(0,3,'Numero nomenclatural nom retenu');
$worksheet->write(0,4,'Numero taxonomique');
$worksheet->write(0,5,'Famille');
$worksheet->write(0,6,'Referentiel taxonomique');
$worksheet->write(0,7,'Commune');
$worksheet->write(0,8,'Identifiant Commune');
$worksheet->write(0,9,'Date');
$worksheet->write(0,10,'Lieu-dit');
$worksheet->write(0,11,'Station');
$worksheet->write(0,12,'Milieu');
$worksheet->write(0,13,'Notes');
$worksheet->write(0,14,'Latitude');
$worksheet->write(0,15,'Longitude');
$worksheet->write(0,16,'Referentiel Geographique');
$worksheet->write(0,17,'Ordre');
$worksheet->write(0,18,'Identifiant');
$numero_page = isset($criteres['numero_page']) ? $criteres['numero_page'] : 0;
$limite = isset($criteres['limite']) ? $criteres['limite'] : 0;
 
$observations = $chercheur_observations->rechercherObservations($uid[0], $criteres, $numero_page, $limite)->get();
if(!$observations) {
header('HTTP/1.0 204 No Content');
exit;
}
 
$ids_obs = array();
$indices_lignes_obs = array();
$i=1;
foreach ($observations as &$obs) {
 
$obs = $this->denullifierTableauValeurCel($obs);
$ids_obs[] = $obs['id_observation'];
$indices_lignes_obs[$obs['id_observation']] = $i;
if ($obs['date_observation'] != "0000-00-00 00:00:00") {
$obs['date_observation'] = $this->formaterDate($obs['date_observation']);
}
else {
$obs['date_observation']="00/00/0000";
}
 
$worksheet->write($i,0,$obs['nom_sel']);
$worksheet->write($i,1,$obs['nom_sel_nn']);
$worksheet->write($i,2,$obs['nom_ret']);
$worksheet->write($i,3,$obs['nom_ret_nn']);
$worksheet->write($i,4,$obs['nt']);
$worksheet->write($i,5,$obs['famille']);
$worksheet->write($i,6,$obs['nom_referentiel']);
$worksheet->write($i,7,$obs['zone_geo']);
$worksheet->write($i,8,$this->convertirCodeZoneGeoVersDepartement($obs['ce_zone_geo']));
$worksheet->write($i,9,$obs['date_observation']);
$worksheet->write($i,10,$obs['lieudit']);
$worksheet->write($i,11,$obs['station']);
$worksheet->write($i,12,$obs['milieu']);
$worksheet->write($i,13,$obs['commentaire']);
$worksheet->write($i,14,$obs['latitude']);
$worksheet->write($i,15,$obs['longitude']);
$worksheet->write($i,16,$obs['geodatum']);
$worksheet->write($i,17,$obs['ordre']);
$worksheet->write($i,18,$obs['id_observation']);
$i++;
}
$indice_dernier_champ_supp = 19;
$indices_champs_supp = array();
$gestion_champs_etendus = new GestionChampsEtendus($this->config, 'obs');
$champs_supp_par_obs = $gestion_champs_etendus->consulterParLots($ids_obs);
foreach($champs_supp_par_obs as $id_obs => &$champs_supp) {
foreach($champs_supp as &$champ_etendu) {
$cle = $champ_etendu->cle;
$label = $champ_etendu->label;
$valeur = $champ_etendu->valeur;
if(!isset($indices_champs_supp[$cle])) {
$indices_champs_supp[$cle] = $indice_dernier_champ_supp;
$worksheet->write(0, $indice_dernier_champ_supp, utf8_decode($label));
$indice_dernier_champ_supp++;
}
$num_ligne_obs = $indices_lignes_obs[$id_obs];
$worksheet->write($num_ligne_obs,$indices_champs_supp[$cle],utf8_decode($valeur));
}
}
$workbook->close();
exit();
}
}
/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log$
* Revision 1.7 2008-11-13 11:29:12 ddelon
* Reecriture gwt-ext
*
* Revision 1.6 2008-01-30 08:57:28 ddelon
* fin mise en place mygwt
*
* Revision 1.5 2007-06-06 13:31:16 ddelon
* v0.09
*
* Revision 1.4 2007-05-22 12:54:09 ddelon
* Securisation acces utilisateur
*/
?>
/branches/v2.3-faux/jrest/services/InventoryImage.php
New file
0,0 → 1,165
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author Aurelien Peronnet <aurelien@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
 
/**
* Service recherche et ajout d'image a partir de divers critères
* in=utf8
* out=utf8
*
*/
class InventoryImage extends Cel {
 
/**
* Méthode appelée avec une requête de type GET.
* Renvoie les infos sur l'image correspondant à l'id passé en parametre
* @param int uid[0] : utilisateur obligatoire
* @param int uid[1] : identifiant image obligatoire
*/
public function getElement($uid)
{
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
if(!isset($uid[0]) || !isset($uid[1])) {
return;
}
 
$chercheur_image = new RechercheImage($this->config);
 
$parametres = array('ordre' => $uid[1]);
 
$retour = null;
$image_recherchee = $chercheur_image->rechercherImages($uid[0], $parametres, 0, 1);
if(count($image_recherchee) > 0) {
$retour = $image_recherchee[0];
}
 
$this->envoyerJson($retour);
return true;
}
 
/**
* Méthode appelée avec une requête de type POST avec un identifiant d'image.
* Met a jour l'image correspondant à l'id passé en paramètre avec les valeurs passées dans le post
*
* @param int $uid[0] identifiant utilisateur
* @param int $uid[1] ordre de l'image relatif à l'utilisateur
* @param pairs array tableau contenant les valeurs de metadonnées à modifier
*/
public function updateElement($uid,$pairs)
{
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
if(count($pairs) == 0 || !isset($uid[1])) {
return false;
}
 
$gestionnaire_image = new GestionImage($this->config);
$resultat_mise_a_jour = $gestionnaire_image->modifierImage($uid[0],$uid[1],$pairs);
 
$retour = false;
$ok = false;
if ($resultat_mise_a_jour) {
$retour = 'OK';
$ok = true;
}
 
$this->envoyer($retour);
return $ok;
}
 
/**
* Méthode appelée avec une requête de type PUT.
* Stocke une image, crée ses miniatures et enregistre ses informations
* Renvoie l'identifiant d'image nouvellement crée en cas de succès
*
* @param $pairs array tableau contenant les valeurs de metadonnées à ajouter
*/
function createElement($pairs)
{
 
if(self::ARRET_SERVICE) {
header('Status: 503 Service Temporarily Unavailable');
echo "L'envoi d'images au cel est temporairement désactivé";
exit;
}
// Controle detournement utilisateur
$this->controleUtilisateur($pairs['ce_utilisateur']);
 
foreach ($_FILES as $file) {
$infos_fichier = $file ;
}
 
$gestionnaire_image = new GestionImage($this->config);
$id_utilisateur = $pairs['ce_utilisateur'];
 
if ($gestionnaire_image->ajouterImage($id_utilisateur, $infos_fichier)) {
 
// l'upload demande de court-circuiter le fonctionnement normal de JREST
// en quittant directement après l'envoi
$this->envoyerMessageCreationEffectuee();
exit;
}
}
 
private function envoyerMessageCreationEffectuee() {
 
header('HTTP/1.0 200 Created');
echo 'OK';
exit() ;
}
 
/**
* Méthode appelée avec une requête de type DELETE.
* Supprime les infos sur l'image et le fichier correspondant à l'ordre passé en parametre
* Supporte la suppression multiple en passant plusieurs numéros séparés par des virgules
*
* @param int uid[0] id utilisateur
* @param string uid[1] : ordre(s) image(s) obligatoire(s) séparés par des virgules
*
*/
function deleteElement($uid){
 
if(self::ARRET_SERVICE) {
header('Status: 503 Service Temporarily Unavailable');
echo "L'envoi d'images au cel est temporairement désactivé";
exit;
}
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
if (!isset($uid[1]) || !$this->EstUneSuiteIdentifiantsImage($uid[1])) {
return;
}
 
$ids_images = explode(',',$uid[1]);
 
$gestionnaire_image = new GestionImage($this->config);
$suppression_image = $gestionnaire_image->supprimerImage($ids_images);
 
$this->envoyer('OK');
}
 
private function estUneSuiteIdentifiantsImage($chaine) {
 
// 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, $chaine);
}
}
?>
/branches/v2.3-faux/jrest/services/CelRestClient.php
New file
0,0 → 1,157
<?php
// declare(encoding='UTF-8');
/**
* Classe modèle spécifique à l'application, donc d'accés au données, elle ne devrait pas être appelée de l'extérieur.
*
* @category php5
* @package Cel
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version SVN: $Id$
*/
// TODO : remplacer les trigger_error par des exceptions qui pourrait être attrapées...
class CelRestClient {
const HTTP_URL_REQUETE_SEPARATEUR = '&';
const HTTP_URL_REQUETE_CLE_VALEUR_SEPARATEUR = '=';
private $http_methodes = array('GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS', 'CONNECT', 'TRACE');
protected $parametres = null;
private $url = null;
private $reponse_entetes = null;
//+----------------------------------------------------------------------------------------------------------------+
// ACCESSEURS
public function getReponseEntetes($cle) {
return $this->reponse_entetes;
}
public function getParametre($cle) {
$valeur = (isset($this->parametres[$cle])) ? $this->parametres[$cle] : null;
return $valeur;
}
public function ajouterParametre($cle, $valeur) {
$this->parametres[$cle] = $valeur;
}
public function supprimerParametre($cle) {
unset($this->parametres[$cle]);
}
public function nettoyerParametres() {
$this->parametres = null;
}
//+----------------------------------------------------------------------------------------------------------------+
// MÉTHODES
public function consulter($url) {
$retour = $this->envoyerRequete($url, 'GET');
return $retour;
}
public function ajouter($url, Array $donnees) {
$retour = $this->envoyerRequete($url, 'PUT', $donnees);
return $retour;
}
public function modifier($url, Array $donnees) {
$retour = $this->envoyerRequete($url, 'POST', $donnees);
return $retour;
}
public function supprimer($url) {
$retour = $this->envoyerRequete($url, 'DELETE');
return $retour;
}
public function envoyerRequete($url, $mode, Array $donnees = array()) {
$this->url = $url;
$contenu = false;
if (! in_array($mode, $this->http_methodes)) {
$e = "Le mode de requête '$mode' n'est pas accepté!";
trigger_error($e, E_USER_WARNING);
} else {
if ($mode == 'GET') {
$this->traiterUrlParametres();
}
$contexte = stream_context_create(array(
'http' => array(
'method' => $mode,
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'content' => http_build_query($donnees, null, self::HTTP_URL_REQUETE_SEPARATEUR))));
$flux = @fopen($this->url, 'r', false, $contexte);
if (!$flux) {
$this->reponse_entetes = $http_response_header;
$e = "L'ouverture de l'url '{$this->url}' par la méthode HTTP '$mode' a échoué!";
trigger_error($e, E_USER_WARNING);
} else {
// Informations sur les en-têtes et métadonnées du flux
$this->reponse_entetes = stream_get_meta_data($flux);
// Contenu actuel de $url
$contenu = stream_get_contents($flux);
fclose($flux);
}
$this->traiterEntete();
}
$this->reinitialiser();
return $contenu;
}
private function traiterUrlParametres() {
$parametres = array();
if (count($this->parametres) > 0) {
foreach ($this->parametres as $cle => $valeur) {
$cle = rawurlencode($cle);
$valeur = rawurlencode($valeur);
$parametres[] = $cle.self::HTTP_URL_REQUETE_CLE_VALEUR_SEPARATEUR.$valeur;
}
$url_parametres = implode(self::HTTP_URL_REQUETE_SEPARATEUR, $parametres);
$this->url = $this->url.'?'.$url_parametres;
}
}
private function traiterEntete() {
$infos = $this->analyserEntete();
$this->traiterEnteteDebogage($infos);
}
private function analyserEntete() {
$entetes = $this->reponse_entetes;
$infos = array('date' => null, 'uri' => $this->url, 'debogages' => null);
if (isset($entetes)) {
if (isset($entetes['wrapper_data'])) {
$entetes = $entetes['wrapper_data'];
}
foreach ($entetes as $entete) {
if (preg_match('/^X_REST_DEBOGAGE_MESSAGES: (.+)$/', $entete, $match)) {
$infos['debogages'] = json_decode($match[1]);
}
if (preg_match('/^Date: .+ ([012][0-9]:[012345][0-9]:[012345][0-9]) .*$/', $entete, $match)) {
$infos['date'] = $match[1];
}
}
}
return $infos;
}
private function traiterEnteteDebogage($entetes_analyses) {
if (isset($entetes['debogages'])) {
$date = $entetes['date'];
$uri = $entetes['uri'];
$debogages = $entetes['debogages'];
foreach ($debogages as $debogage) {
$e = "DEBOGAGE : $date - $uri :\n$debogage";
trigger_error($e, E_USER_NOTICE);
}
}
}
private function reinitialiser() {
$this->nettoyerParametres();
}
}
/branches/v2.3-faux/jrest/services/CelWidgetMap.php
New file
0,0 → 1,829
<?php
// declare(encoding='UTF-8');
/**
* Service fournissant une carte dynamique des obsertions publiques du CEL.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* Cas d'utilisation :
* /CelWidgetMap/Carte/Utilisateur : carte des observations publiques d'un utilisateur.
* /CelWidgetMap/Carte/Utilisateur/Projet : carte des observations publiques d'un utilisateur pour un projet.
* /CelWidgetMap/Carte/Utilisateur/Projet/dept : carte des observations publiques d'un utilisateur pour un projet sur un département.
* /CelWidgetMap/Carte/Utilisateur/Projet/dept/num_taxon : carte des observations publiques d'un utilisateur pour un projet sur un département pour un taxon.
*
* Carte = Type de carte. Valeurs possible : defaut,
* Utilisateur = identifiant (= courriel) de l'utilisateur ou * pour tous les utilisateurs.
* Projet = mot-clé du projet
*
* @author Jean-Pascal MILCENT <jpm@clapas.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright © 2010, Jean-Pascal MILCENT
*/
// TODO : supprimer le TRIM quand les obs seront reliées correctements aux localisations (sur le code INSEE par exemple)
class CelWidgetMap extends Cel {
 
/**
* Méthode appelée avec une requête de type GET.
*/
public function getElement($ressources) {
$retour = null;
extract($this->parametres);
 
$action = array_shift($ressources);
if (isset($action)) {
$methode = $this->traiterNomMethodeGet($action);
if (method_exists($this, $methode)) {
$retour = $this->$methode($ressources);
} else {
$this->messages[] = "Ce type de ressource '$methode' n'est pas disponible.";
}
} else {
$this->messages[] = "Vous devez indiquer le type de ressource.";
}
 
if (is_null($retour)) {
$info = 'Un problème est survenu : '.print_r($this->messages, true);
$this->envoyer($info);
} else if (isset($retour['type']) && $retour['type'] == 'jsonVar') {
 
$this->envoyerJsonVar($retour['variable_js'], $retour['donnees']);
} else if (isset($retour['type']) && $retour['type'] == 'jsonP') {
$this->envoyerJsonp($retour['donnees']);
} else {
$this->envoyerJson($retour);
}
}
 
/**
* Les stations de la carte par défaut
*/
public function getStations($params) {
$json = null;
$requete = 'SELECT utm_secteur, utm_x, utm_y, wgs84_latitude AS latitude, wgs84_longitude AS longitude '.
'FROM cel_obs AS co '.
' LEFT JOIN cel_zones_geo AS l '.
' ON (l.id_zone_geo = co.ce_zone_geo) '.
"WHERE transmission = '1' ".
$this->construireWhereDept().
$this->construireWhereCommune().
$this->construireWherePhotosSeulement().
$this->construireWhereUtilisateur().
$this->construireWhereNumTaxon().
$this->construireWhereNomTaxon().
$this->construireWhereDate().
$this->construireWhereCommentaire().
$this->construireWhereProjet().
$this->construireWhereTag();
//die($requete);
$resultats = Cel::db()->requeter($requete);
 
// Traitement des résultats
$obs_nbre = $this->traiterNbreObs($resultats);
$stations = $this->traiterStations($resultats);
 
// Création des infos du widget
$json['donnees']['points'] = $stations;
$json['donnees']['stats']['communes'] = count($stations);
$json['donnees']['stats']['observations'] = $obs_nbre;
 
$json['type'] = (isset($this->formatRetour)) ? $this->formatRetour : 'jsonVar';
$json['variable_js'] = 'stations';
 
return $json;
}
 
private function traiterNbreObs($resultats) {
$obs_nbre = 0;
if ($resultats !== false) {
$obs_nbre = count($resultats);
}
return $obs_nbre;
}
 
private function traiterStations($resultats) {
$stations = array();
if ($resultats !== false) {
foreach ($resultats as $enrg) {
if ($enrg['latitude'] != null && $enrg['longitude'] != null) {
$id = $enrg['latitude'].'-'.$enrg['longitude'];
if (!isset($stations[$id])) {
$enrg['id'] = 'UTM:'.$enrg['utm_x'].'-'.$enrg['utm_y'].'-'.$enrg['utm_secteur'];
unset($enrg['utm_x']);
unset($enrg['utm_y']);
unset($enrg['utm_secteur']);
$stations[$id] = $enrg;
$stations[$id]['nbre'] = 1;
} else {
$stations[$id]['nbre']++;
}
}
}
$stations = array_values($stations);
}
return $stations;
}
 
/**
* Données pour l'affichage des obs d'une station
*/
public function getObservations($params) {
$resultats = array();
$total = 0;
if (!$this->etreNull($this->parametres['station'])) {
$requete = 'SELECT SQL_CALC_FOUND_ROWS id_observation, ce_utilisateur, courriel_utilisateur, '.
' nom_sel, nom_ret, nom_sel_nn, nom_ret_nn, nt, famille, '.
' lieudit, zone_geo, date_observation, milieu, commentaire, '.
' utm_secteur, utm_x, utm_y, id_zone_geo, date_transmission, nom_referentiel '.
'FROM cel_obs AS co '.
' LEFT JOIN cel_zones_geo AS l '.
" ON (l.id_zone_geo = co.ce_zone_geo) ".
"WHERE transmission = '1' ".
$this->construireWhereCoordonnees().
$this->construireWherePhotosSeulement().
$this->construireWhereUtilisateur().
$this->construireWhereNumTaxon().
$this->construireWhereNomTaxon().
$this->construireWhereDate().
$this->construireWhereCommentaire().
$this->construireWhereProjet().
$this->construireWhereTag().
'ORDER BY nom_sel ASC '.
"LIMIT {$this->start},{$this->limit} ";
//die($requete);
$resultats = Cel::db()->requeter($requete, self::SQL_RETOUR_COMPLET, self::SQL_MODE_OBJET);
 
$requete = 'SELECT FOUND_ROWS()';
$total = (int) Cel::db()->requeter($requete, self::SQL_RETOUR_COLONNE);
}
 
// Post-traitement
$observations = $this->traiterObservations($resultats, $total);
$observations = $this->ajouterImagesAuxObs($observations);
$observations = $this->ajouterAuteursAuxObs($observations);
$observations = $this->supprimerIdDesObs($observations);
return $observations;
}
 
private function traiterObservations($donnees, $total) {
$observations = array('commune' => '', 'observations' => array(), 'observateurs' => array());
$observations['total'] = (isset($total)) ? $total : 0;
if (is_array($donnees) && count($donnees) > 0) {
foreach ($donnees as $donnee) {
$observation = array();
$observation['idObs'] = $donnee->id_observation;
$observation['nn'] = $this->etreNull($donnee->nom_sel_nn) ? null : $donnee->nom_sel_nn;
$observation['nomSci'] = $this->nettoyerTexte($donnee->nom_sel);
$observation['date'] = $this->formaterDate($donnee->date_observation, '%d/%m/%Y');
$observation['datePubli'] = $this->formaterDate($donnee->date_transmission);
$observation['lieu'] = $this->traiterLieu($donnee);
$observation['observateur'] = $donnee->courriel_utilisateur;
$observation['observateurId'] = $donnee->ce_utilisateur;
$observation['referentiel'] = $this->supprimerVersionDuReferentiel($donnee->nom_referentiel);
$observation['urlEflore'] = $this->getUrlEflore($donnee->nom_referentiel, $donnee->nom_sel_nn);
 
if (isset($donnee->zone_geo)) {
$observations['commune'] = $this->nettoyerTexte($donnee->zone_geo);
}
$observations['observations'][$donnee->id_observation] = $observation;
if (! array_key_exists($donnee->courriel_utilisateur, $observations['observateurs'])) {
$observations['observateurs'][$donnee->courriel_utilisateur] = $donnee->courriel_utilisateur;
}
}
}
return $observations;
}
 
private function traiterLieu($donnee) {
$lieu = array();
if (!$this->etreNull($donnee->lieudit)) {
$lieu[] = $donnee->lieudit;
}
if (!$this->etreNull($donnee->milieu)) {
$lieu[] = $donnee->milieu;
}
return implode(', ', $lieu);
}
 
private function chargerImages(Array $obs_ids) {
// Récupération des données au format Json
$service = 'CelImage/liste-ids?obsId='.implode(',', $obs_ids);
$url = sprintf($this->config['settings']['baseURLServicesCelTpl'], $service);
$json = $this->getRestClient()->consulter($url);
$donnees = json_decode($json);
 
// Post-traitement des données
$images = $this->traiterImages($donnees);
 
return $images;
}
 
private function traiterImages($donnees) {
$images = array();
if (count($donnees) > 0) {
foreach ($donnees as $id_obs => $id_images) {
foreach ($id_images as $id_img) {
$urls['idImg'] = $id_img;
$urls['guid'] = sprintf($this->config['settings']['guidImgTpl'], $id_img);
$urls['miniature'] = $this->getUrlImage($id_img, 'CXS');
$urls['normale'] = $this->getUrlImage($id_img, 'XL');
$images[$id_obs][] = $urls;
}
}
}
return $images;
}
 
private function ajouterImagesAuxObs($observations) {
$images = $this->chargerImages(array_keys($observations['observations']));
foreach ($observations['observations'] as $id => $infos) {
if(isset($images[$id])) {
$infos['images'] = $images[$id];
}
$observations['observations'][$id] = $infos;
}
return $observations;
}
 
private function ajouterAuteursAuxObs($observations) {
$observateurs = $this->recupererUtilisateursIdentite(array_keys($observations['observateurs']));
unset($observations['observateurs']);
foreach ($observations['observations'] as $id => $infos) {
$courriel = strtolower($infos['observateur']);
$infos['observateur'] = $observateurs[$courriel]['intitule'];
$infos['observateurId'] = $observateurs[$courriel]['id'];
$observations['observations'][$id] = $infos;
}
return $observations;
}
 
private function supprimerIdDesObs($observations) {
// Le tableau de sortie ne doit pas avoir les id des obs en clé car sinon Jquery Template ne fonctionne pas
$observationSansId = $observations;
unset($observationSansId['observations']);
foreach ($observations['observations'] as $id => $infos) {
$observationSansId['observations'][] = $infos;
}
return $observationSansId;
}
 
/**
* Liste des taxons présents sur la carte
*/
public function getTaxons($params) {
$json = null;
 
$requete = 'SELECT SQL_CALC_FOUND_ROWS DISTINCT nom_ret, nom_ret_nn, nt, famille '.
'FROM cel_obs AS co '.
' LEFT JOIN cel_zones_geo AS l '.
' ON (l.id_zone_geo = co.ce_zone_geo) '.
"WHERE transmission = '1' ".
" AND nom_ret != '' ".
$this->construireWhereDept().
$this->construireWhereCommune().
$this->construireWherePhotosSeulement().
$this->construireWhereUtilisateur().
$this->construireWhereNumTaxon().
$this->construireWhereNomTaxon().
$this->construireWhereDate().
$this->construireWhereCommentaire().
$this->construireWhereProjet().
$this->construireWhereTag();
'ORDER BY nom_ret ASC '.
"LIMIT {$this->start},{$this->limit} ";
//$this->debug[] = $requete;
//die($requete);
$resultats = Cel::db()->requeter($requete, self::SQL_RETOUR_COMPLET, self::SQL_MODE_OBJET);
 
$requete = 'SELECT FOUND_ROWS()';
$taxons['total'] = (int) Cel::db()->requeter($requete, self::SQL_RETOUR_COLONNE);
 
// Post-traitement
$taxons['taxons'] = $this->traiterTaxons($resultats);
 
return $taxons;
}
 
private function traiterTaxons($donnees) {
$taxons = array();
if (is_array($donnees) && count($donnees) > 0) {
foreach ($donnees as $donnee) {
if (!isset($taxons[$donnee->nt]) && ! $this->etreNull($donnee->nom_ret)) {
$taxon = array();
$taxon['nn'] = $donnee->nom_ret_nn;
$taxon['nt'] = $donnee->nt;
$taxon['nom'] = $this->nettoyerTexte($donnee->nom_ret);
$taxon['famille'] = $this->nettoyerTexte($donnee->famille);
$taxons[$donnee->nt] = $taxon;
}
}
}
$taxons = array_values($taxons);
return $taxons;
}
 
private function construireWhereCoordonnees() {
$sql = '';
// Récupération des coordonnées depuis l'id station
extract($this->decomposerParametreStation());
if (isset($type)) {
if ($type == 'UTM') {
$secteur = Cel::db()->proteger($secteur);
$utm_x = Cel::db()->proteger($utm_x);
$utm_y = Cel::db()->proteger($utm_y);
 
$sql = " AND (utm_secteur = $secteur AND utm_x = $utm_x AND utm_y = $utm_y ) ";
} else if ($type == 'LngLat') {
$latitude = Cel::db()->proteger($latitude);
$longitude = Cel::db()->proteger($longitude);
 
$sql = " AND (latitude = $latitude AND longitude = $longitude ) ";
}
}
return $sql;
}
 
private function construireWhereCommentaire() {
$sql = '';
list($type, $commentaire) = $this->decomposerParametreCommentaire();
if (!$this->etreNull($commentaire)) {
$commentaire = Cel::db()->proteger('%'.$commentaire.'%');
switch ($type) {
case '*' :
$sql = $this->obtenirConditionPourCommentaires($commentaire);
$sql = " AND (commentaire LIKE $commentaire OR ($sql)) ";
break;
case 'observation' :
$sql = " AND co.commentaire LIKE $commentaire ";
break;
case 'photo' :
$sql = ' AND '.$this->obtenirConditionPourCommentaires($commentaire).' ';
break;
case 'photo.meta' :
$sql = ' AND '.$this->obtenirConditionPourCommentaireMeta($commentaire).' ';
break;
case 'photo.utilisateur' :
$sql = ' AND '.$this->obtenirConditionPourCommentaireUtilisateur($commentaire).' ';
break;
default:
$sql = " AND co.commentaire LIKE $commentaire ";
}
}
return $sql;
}
 
 
private function construireWhereNomTaxon() {
$sql = '';
list($type, $nom) = $this->decomposerParametreTaxon();
if (!$this->etreNull($nom)) {
$nom = Cel::db()->proteger($nom.'%');
switch ($type) {
case '*' :
$sql = " AND (nom_ret LIKE $nom OR nom_sel LIKE $nom OR famille LIKE $nom) ";
break;
case 'retenu' :
$sql = " AND nom_ret LIKE $nom ";
break;
case 'selectionne' :
$sql = " AND nom_sel LIKE $nom ";
break;
case 'famille' :
$sql = " AND famille LIKE $nom ";
break;
default:
$sql = " AND nom_ret LIKE $nom ";
}
}
return $sql;
}
 
private function construireWhereDate() {
$sql = '';
// Récupération des coordonnées depuis l'id station
list($type, $date) = $this->decomposerParametreDate();
 
if (!$this->etreNull($date)) {
$date = Cel::db()->proteger($date.'%');
switch ($type) {
case '*' :
$sql = " AND (
date_observation LIKE $date
OR date_creation LIKE $date
OR date_modification LIKE $date
OR date_transmission LIKE $date) ";
break;
case 'observation' :
$sql = " AND date_observation LIKE $date ";
break;
case 'creation' :
$sql = " AND date_creation LIKE $date ";
break;
case 'modification' :
$sql = " AND date_modification LIKE $date ";
break;
case 'transmission' :
$sql = " AND date_transmission LIKE $date ";
break;
case 'photo' :
$sql = $this->obtenirConditionPourDatePhoto($date);
break;
case 'ajout' :
$sql = $this->obtenirConditionPourDateAjout($date);
break;
case 'liaison' :
$sql = $this->obtenirConditionPourDateLiaison($date);
break;
default:
$sql = " AND date_observation LIKE $date ";
}
}
return $sql;
}
 
private function obtenirConditionPourDatePhoto($date) {
$observations = $this->obtenirObsLieesImg('date.photo', $date);
if (is_null($observations)) {
$this->debug[] = "Aucune observation n'est liée à une photo prise à la date : $date";
}
$sql = $this->assemblerObsEnConditionSql($observations);
return $sql;
}
 
private function obtenirConditionPourDateLiaison($date) {
$observations = $this->obtenirObsLieesImg('date.liaison', $date);
if (is_null($observations)) {
$this->debug[] = "Aucune observation n'a été liée à une image à à la date : $date";
}
$sql = $this->assemblerObsEnConditionSql($observations);
return $sql;
}
 
private function obtenirConditionPourDateAjout($date) {
$observations = $this->obtenirObsLieesImg('date.ajout', $date);
if (is_null($observations)) {
$this->debug[] = "Aucune observation n'est liée à une image ajoutée à la date : $date";
}
$sql = $this->assemblerObsEnConditionSql($observations);
return $sql;
}
 
private function obtenirConditionPourCommentaireMeta($commentaire) {
$observations = $this->obtenirObsLieesImg('commentaire.meta', $commentaire);
if (is_null($observations)) {
$this->debug[] = "Aucune observation n'est liée à une image dont le commentaire des méta-données correspond à : $commmentaire";
}
$operateur = '';
$sql = $this->assemblerObsEnConditionSql($observations, $operateur);
return $sql;
}
 
private function obtenirConditionPourCommentaireUtilisateur($commentaire) {
$observations = $this->obtenirObsLieesImg('commentaire.utilisateur', $commentaire);
if (is_null($observations)) {
$this->debug[] = "Aucune observation n'est liée à une image dont le commentaire des utilisateur correspond à : $commmentaire";
}
$operateur = '';
$sql = $this->assemblerObsEnConditionSql($observations, $operateur);
return $sql;
}
 
private function obtenirConditionPourCommentaires($commentaire) {
$observations = $this->obtenirObsLieesImg('commentaire.*', $commentaire);
if (is_null($observations)) {
$this->debug[] = "Aucune observation n'est liée à une image dont un des commentaires correspond à : $commmentaire";
}
$operateur = '';
$sql = $this->assemblerObsEnConditionSql($observations, $operateur);
return $sql;
}
 
/**
* Récupération des identifiant d'utilisateur et des ordres des observations correspondant à une date.
* Retour sous forme de tableau : array[identifiant] = array(ordre, ordre...);
*/
private function obtenirObsLieesImg($type, $param) {
// Construction de la requête
$requete = 'SELECT DISTINCT id_observation AS id_obs, ce_utilisateur AS utilisateur '.
'FROM cel_images ci'.
' LEFT JOIN cel_obs_images coi '.
' ON (coi.id_image = ci.id_image) '.
' LEFT JOIN cel_obs AS co '.
' ON coi.id_observation = co.id_observation '.
' LEFT JOIN locations AS l '.
' ON (l.id_zone_geo = co.ce_zone_geo) '.
"WHERE transmission = '1' ".
($type == 'date.photo' ? " AND (date_prise_de_vue LIKE ".str_replace('-', ':', $param).") " : '').
($type == 'date.ajout' ? " AND date_creation LIKE $param " : '').
($type == 'date.liaison' ? " AND date_liaison LIKE $param " : '').
// TODO: recherche sur le xml
//($type == 'commentaire.meta' ? " AND ci.commentaire LIKE $param " : '').
($type == 'commentaire.utilisateur' ? " AND ci.commentaire LIKE $param " : '').
($type == 'commentaire.*' ? " AND (ci.commentaire LIKE $param) " : '').
$this->construireWhereCoordonnees().
$this->construireWhereDept().
$this->construireWhereCommune().
$this->construireWhereUtilisateur().
$this->construireWhereNumTaxon().
$this->construireWhereNomTaxon().
$this->construireWhereProjet().
$this->construireWhereTag().
'ORDER BY utilisateur ASC, ordre ASC';
//$this->debug[] = $requete;
//die($requete);
$resultats = Cel::db()->requeter($requete);
 
$observations = null;
if ($resultats != false) {
$observations = array();
foreach ($resultats as $occurence) {
$utilisateur = $occurence['utilisateur'];
$id_obs = $occurence['id_obs'];
if (!array_key_exists($utilisateur, $observations)) {
$observations[$utilisateur] = array();
}
if (!array_key_exists($id_obs, $observations[$utilisateur])) {
$observations[$utilisateur][$id_obs] = $id_obs;
}
}
}
return $observations;
}
 
private function assemblerObsEnConditionSql($observations, $operateur = 'AND') {
$sql = '';
if ($observations != null) {
// Pré-construction du where de la requête
$tpl_where = "(id_observation IN (%s))";
foreach ($observations as $utilisateur => $ids_obs) {
$morceaux_requete[] = sprintf($tpl_where, implode(',', $ids_obs));
}
if (count($morceaux_requete) > 0) {
$sql = implode(" \nOR ", $morceaux_requete);
}
} else {
// Nous voulons que la requête ne retourne rien
$sql = "id_observation = ''";
}
$sql = " $operateur ($sql) ";
return $sql;
}
 
private function construireWhereDept() {
$sql = '';
// Récupération des coordonnées depuis l'id station
extract($this->parametres);
if (isset($dept) && !$this->etreNull($dept)) {
$valeurs_a_proteger = explode(',',trim($dept));
foreach ($valeurs_a_proteger as $valeur) {
$valeurs_protegees[] = '(ce_zone_geo LIKE '.Cel::db()->quote('INSEE-C:'.$valeur.'%').') ';
}
$valeurs = implode(' OR ', $valeurs_protegees);
$sql = " AND ($valeurs) ";
}
return $sql;
}
 
private function construireWhereCommune() {
$sql = '';
// Récupération des coordonnées depuis l'id station
extract($this->parametres);
if (isset($commune) && !$this->etreNull($commune)) {
$commune = Cel::db()->proteger($commune);
$sql = " AND zone_geo LIKE $commune ";
}
return $sql;
}
 
private function construireWherePhotosSeulement() {
$sql = '';
if (isset($this->parametres['photos']) && $this->parametres['photos'] == 1) {
$sql = 'AND co.id_observation IN (SELECT DISTINCT id_observation FROM cel_obs_images) ';
}
return $sql;
}
 
 
private function construireWhereUtilisateur() {
$sql = '';
// Récupération des coordonnées depuis l'id station
extract($this->parametres);
if (isset($utilisateur) && !$this->etreNull($utilisateur)) {
$utilisateur = Cel::db()->proteger($utilisateur);
$sql = " AND courriel_utilisateur = $utilisateur ";
}
return $sql;
}
 
private function construireWhereNumTaxon() {
$sql = '';
// Récupération des coordonnées depuis l'id station
extract($this->parametres);
if (isset($num_taxon) && !$this->etreNull($num_taxon)) {
$num_taxon = Cel::db()->proteger($num_taxon);
$sql = " AND nt = $num_taxon ";
}
return $sql;
}
 
private function construireWhereProjet() {
$sql = '';
// Récupération des coordonnées depuis l'id station
extract($this->parametres);
$projet_sql = isset($projet) ? $this->getSqlWhereProjet($projet) : null;
if (!$this->etreNull($projet_sql)) {
$sql = " AND ($projet_sql) ";
}
return $sql;
}
 
/**
* Traitement de $projet pour construction du filtre dans la requête
*/
private function getSqlWhereProjet($projet) {
$sql = null;
if (isset($projet) && !$this->etreNull($projet)) {
$sql = 'co.mots_cles_texte LIKE '.Cel::db()->proteger($projet);
}
return $sql;
}
 
private function construireWhereTag() {
$sql = '';
extract($this->parametres);
$tag_sql = isset($tag) ? $this->getSqlWhereObsAvecImagesTaguees($tag) : null;
if (!$this->etreNull($tag_sql)) {
$sql = " AND ($tag_sql) ";
}
return $sql;
}
 
/**
* Traitement de $tag pour construction du filtre dans la requête
*/
private function getSqlWhereObsAvecImagesTaguees($tag) {
$sql = null;
if (isset($tag) && !$this->etreNull($tag)) {
$tag_sql = $this->getSqlWhereMotsCles($tag);
// Construction de la requête
$requete = 'SELECT DISTINCT coi.id_observation AS id_obs, ci.ce_utilisateur AS utilisateur '.
'FROM cel_images ci'.
' LEFT JOIN cel_obs_images coi'.
' ON (ci.id_image = coi.id_image) '.
' LEFT JOIN cel_obs AS co '.
' ON (coi.id_observation = co.id_observation) '.
' LEFT JOIN cel_zones_geo AS l '.
" ON (l.id_zone_geo = co.ce_zone_geo) ".
"WHERE transmission = '1' ".
$this->construireWhereCoordonnees().
$this->construireWhereUtilisateur().
$this->construireWhereNumTaxon().
$this->construireWhereNomTaxon().
$this->construireWhereProjet().
(!$this->etreNull($tag_sql) ? "AND ($tag_sql) " : '').
'ORDER BY utilisateur ASC, ci.ordre ASC';
//$this->debug[] = $requete;
//die($requete);
$elements_tag = Cel::db()->requeter($requete);
 
$requete_tag = array();
if ($elements_tag != false && count($elements_tag) > 0) {
 
$filtres = array();
foreach ($elements_tag as $occurence) {
$utilisateur = $occurence['utilisateur'];
$id_obs = $occurence['id_obs'];
if (!array_key_exists($utilisateur, $filtres)) {
$filtres[$utilisateur] = array();
}
if (!array_key_exists($id_obs, $filtres[$utilisateur])) {
$filtres[$utilisateur][$id_obs] = $id_obs;
}
}
 
// Pré-construction du where de la requête
$tpl_where = "(id_observation IN (%s))";
foreach ($filtres as $utilisateur => $id_obs) {
$requete_tag[] = sprintf($tpl_where, implode(',', $id_obs));
}
 
} else {
$this->messages[] = "Aucune observation ne possède d'images avec ce mot-clé.";
}
if (count($requete_tag) > 0) {
$sql = implode(" \nOR ", $requete_tag);
}
}
return $sql;
}
 
/**
* Traitement de $tag pour construction du filtre dans la requête
*/
private function getSqlWhereMotsCles($tag) {
$sql = null;
$mots_cles = $this->decomposerParametreTag($tag);
$requete_projet = $this->getSqlWhereMotsClesImages($mots_cles);
$sql = $requete_projet;
//$this->debug[] = $sql;
return $sql;
}
 
/**
* Traitement de $tag pour construction du filtre dans la requête
*/
private function getSqlWhereMotsClesImages($mots_cles_encodes) {
$where_mots_cles_images = array();
foreach ($mots_cles_encodes['motsClesEncodesProteges'] as $mot_cle_encode) {
$where_mots_cles_images[] = "ci.mots_cles_texte LIKE $mot_cle_encode";
}
$where_mots_cles_images = implode(' '.$mots_cles_encodes['type'].' ', $where_mots_cles_images);
return $where_mots_cles_images;
}
 
private function decomposerParametreTag($tags) {
 
$mots_cles = array('type' => null, 'motsCles' => null, 'motsClesEncodesProteges' => null);
if (preg_match('/.+OU.+/', $tags)) {
$mots_cles['type'] = 'OR';
$mots_cles['motsCles'] = explode('OU', $tags);
} else if (preg_match('/.+ET.+/', $tags)) {
$mots_cles['type'] = 'AND';
$mots_cles['motsCles'] = explode('ET', $tags);
} else {
$mots_cles['motsCles'][] = $tags;
}
 
foreach ($mots_cles['motsCles'] as $mot) {
$mots_cles['motsClesEncodesProteges'][] = Cel::db()->quote('%'.$mot.'%');
}
$this->debug[] = $mots_cles;
return $mots_cles;
}
 
private function decomposerParametreStation() {
$station_infos = array();
if (isset($this->parametres['station'])) {
$station = $this->parametres['station'];
$this->debug[] = $station;
list($type, $coord) = explode(':', $station);
 
if ($type == 'UTM') {
list($utm_x, $utm_y, $secteur) = explode('-', $coord);
$station_infos = array('utm_x' => $utm_x, 'utm_y' => $utm_y, 'secteur' => $secteur);
} else if ($type == 'LngLat') {
list($longitude, $latitude) = explode('-', $coord);
$station_infos = array('longitude' => $longitude, 'latitude' => $latitude);
}
$station_infos['type'] = $type;
}
return $station_infos;
}
 
private function decomposerParametreDate() {
$date_infos = array(null,null);
if (isset($this->parametres['date'])) {
$date = $this->parametres['date'];
if (strpos($date, ':')) {
list($type, $date) = explode(':', $date);
} else {
$type = 'observation';
}
 
$date = str_replace('/', '-', $date);
if (preg_match('/(^[0-9]{2})-([0-9]{2})-([0-9]{4}$)/', $date, $matches)) {
$date = $matches[3].'-'.$matches[2].'-'.$matches[1];
}
 
$date_infos = array($type, $date);
}
return $date_infos;
}
 
private function decomposerParametreTaxon() {
$nom_infos = array(null, null);
if (isset($this->parametres['taxon'])) {
$taxon = $this->parametres['taxon'];
if (strpos($taxon, ':')) {
$nom_infos = explode(':', $taxon);
} else {
$nom_infos = array('retenu', $taxon);
}
}
return $nom_infos;
}
 
private function decomposerParametreCommentaire() {
$commentaire_infos = array(null, null);
if (isset($this->parametres['commentaire'])) {
$commentaire = $this->parametres['commentaire'];
if (strpos($commentaire, ':')) {
$commentaire_infos = explode(':', $commentaire);
} else {
$commentaire_infos = array('observation', $commentaire);
}
}
return $commentaire_infos;
}
}
/branches/v2.3-faux/jrest/services/CelWidgetSaisie.php
New file
0,0 → 1,663
<?php
// declare(encoding='UTF-8');
/**
* Service permettant d'insérer les informations fournie par le widget Saisie dans le CEL.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* Cas d'utilisation :
* PUT /CelWidgetSaisie : ajout de données en les passant via $_POST
*
* @author Jean-Pascal MILCENT <jpm@clapas.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright © 2011, Jean-Pascal MILCENT
*/
class CelWidgetSaisie extends Cel {
 
private $projet = null;
private $projetTags = array();
private $tagsObs = null;
private $tagsImg = null;
private $champsEtendusObs = null;
private $utilisateur_id = null;
const DUREE_DE_VIE_IMG = 86400;// 3600 * 24 * 2 = 172 800
const ARRET_SERVICE = false;// Permet de bloquer le service en cas de problème sur le serveur
 
private $correspondanceIdImgTags = array();
private $gestionMotsClesObs = null;
private $gestionMotsClesImages = null;
 
public function createElement($requeteDonnees) {
if (self::ARRET_SERVICE) {
$this->messages[] = "Désactivation temporaire du service d'envoi des données au CEL.";
} else if (array_key_exists('projet', $requeteDonnees)) {
$this->debug[] = 'Projet : '.$requeteDonnees['projet'];
$this->projet = $requeteDonnees['projet'];
 
// Traitements des tags multiples de projet
$this->traiterProjetTags();
 
// Traitement des tags spécifique aux obs
$this->traiterTagObs($requeteDonnees);
 
// Traitement des tags spécifique aux images
$this->traiterTagImg($requeteDonnees);
 
// Traitement des observations et des images
if (filter_var($requeteDonnees['utilisateur']['courriel'], FILTER_VALIDATE_EMAIL)) {
$this->debug[] = 'Utilisateur : '.print_r($requeteDonnees['utilisateur'], true);
$utilisateur = $requeteDonnees['utilisateur'];
if (array_key_exists('courriel', $utilisateur)) {
$this->debug[] = 'Courriel : '.$utilisateur['courriel'];
$utilisateur = $this->affecterChampsManquantsUtilisateur($utilisateur);
extract($utilisateur);
$this->utilisateur_id = $id_utilisateur;
$ordre = $this->getMaxOrdre($id_utilisateur);
if (!is_null($ordre)) {
$requeteDonnees = $this->supprimerSlashesProfond($requeteDonnees);
// Triage et manipulation des données
$observations = array();
foreach ($requeteDonnees as $cle => $obs) {
if (preg_match('/^obsId[0-9]+$/', $cle)) {
$ordreObs = $ordre++;
 
$this->debug[] = 'commune_nom : '.$obs['commune_nom'];
$this->debug[] = 'commune_code_insee : '.$obs['commune_code_insee'];
 
$obsAAjouter = array();
$obsAAjouter['ce_utilisateur'] = $id_utilisateur;
$obsAAjouter['courriel_utilisateur'] = $courriel;
$obsAAjouter['prenom_utilisateur'] = $prenom;
$obsAAjouter['nom_utilisateur'] = $nom;
$obsAAjouter['ordre'] = $ordreObs;
 
$obsAAjouter['nom_sel'] = $obs['nom_sel'];
$obsAAjouter['nom_sel_nn'] = isset($obs['num_nom_sel']) ? $obs['num_nom_sel'] : null;
$obsAAjouter['nom_ret'] = isset($obs['nom_ret']) ? $obs['nom_ret'] : null;
$obsAAjouter['nom_ret_nn'] = isset($obs['num_nom_ret']) ? $obs['num_nom_ret'] : null;
$obsAAjouter['nt'] = isset($obs['num_taxon']) ? $obs['num_taxon'] : null;
$obsAAjouter['famille'] = isset($obs['famille']) ? $obs['famille'] : null;
$obsAAjouter['nom_referentiel'] = isset($obs['referentiel']) ? $obs['referentiel'] : null;
 
$obsAAjouter['date_observation'] = $this->transormerDateFrVersMysql($obs['date']);
$obsAAjouter['commentaire'] = $obs['notes'];
 
$obsAAjouter['zone_geo'] = $obs['commune_nom'];
$obsAAjouter['ce_zone_geo'] = 'INSEE-C:'.$obs['commune_code_insee'];
$obsAAjouter['lieudit'] = isset($obs['lieudit']) ? $obs['lieudit'] : null;
$obsAAjouter['station'] = isset($obs['station']) ? $obs['station'] : null;
$obsAAjouter['milieu'] = isset($obs['milieu']) ? $obs['milieu'] : null;
$obsAAjouter['latitude'] = $obs['latitude'];
$obsAAjouter['longitude'] = $obs['longitude'];
$obsAAjouter['geodatum'] = 'WGS84';
 
$obsAAjouter['certitude'] = isset($obs['certitude']) ? $obs['certitude'] : null;
$obsAAjouter['phenologie'] = isset($obs['phenologie']) ? $obs['phenologie'] : null;
$obsAAjouter['abondance'] = isset($obs['abondance']) ? $obs['abondance'] : null;
 
$obsAAjouter['transmission'] = '1';
$obsAAjouter['date_creation'] = date('Y-m-d H:i:s');
$obsAAjouter['date_modification'] = $obsAAjouter['date_creation'];
$obsAAjouter['date_transmission'] = $obsAAjouter['date_creation'];
 
$this->champsEtendusObs[$ordreObs] = isset($obs['obs_etendue']) ? $obs['obs_etendue'] : array();
 
$imgAAjouter = null;
if (!empty($obs['image_nom'])) {
$imgAAjouter = $this->traiterImagesALierAObs($id_utilisateur, $ordreObs, $obs);
}
 
if(!trim($courriel) && !trim($id_utilisateur)) {
// XXX: debug
file_put_contents("/tmp/debug-cel-" . time(),
$_POST . "\n=\n" . $requeteDonnees . "\n=\n" . var_export($obsAAjouter, true) .
"\n=\n", $_SERVER);
}
 
$observations[$ordreObs] = array(
'obs' => $this->protegerTableau($obsAAjouter),
'img' => $imgAAjouter);
}
}
$this->debug[] = 'Nbre obs ajoutée : '.count($observations);
$this->debug[] = 'projet : '.$this->projet;
$this->debug[] = 'tagsObs : '.print_r($this->tagsObs, true);
$this->debug[] = 'tagsImg : '.print_r($this->tagsImg, true);
 
// Insertion dans la base
$obs_a_taguer_ordres = array();
$img_a_taguer_ids = array();
foreach ($observations as $infos) {
$obs = $infos['obs'];
$img = $infos['img'];
 
$champs = implode(', ', array_keys($obs));
$valeurs = implode(', ', $obs);
$requete = "INSERT INTO cel_obs ($champs) VALUES ($valeurs) ";
 
if (Cel::db()->executer($requete) === false) {
$this->messages[] = "Un problème est survenu lors de l'insertion de l'obs dans la base de données.";
} else {
$obs_a_taguer_ordres[] = trim($obs['ordre'], "'");
}
 
// si le formulaire contient une image on la traite
if ($img != null) {
$this->nettoyerImagesUploades();
$img_a_taguer_ids = $this->stockerImagesEtLierAObs($img, $id_utilisateur, $utilisateur);
$cmd = sprintf($this->config['cel']['commande_script_images'],implode(',', $img_a_taguer_ids));
pclose(popen($cmd,"r"));
}
}
 
$this->gestionMotsClesObs = new GestionMotsClesChemin($this->config,'obs');
$this->gestionMotsClesImages = new GestionMotsClesChemin($this->config,'images');
 
$obs_a_taguer_ids = $this->obtenirIdsObsPourTableauOrdres($this->utilisateur_id, $obs_a_taguer_ordres);
$this->taguerObs($obs_a_taguer_ids);
$this->taguerImg($img_a_taguer_ids);
 
// Les champs taggés sont des champs supplémentaires stockés sous forme de clé => valeur
$this->ajouterChampsEtendusObs($obs_a_taguer_ids, $this->champsEtendusObs);
} else {
$this->messages[] = "Un nouveau numéro d'ordre d'observation n'a pu être généré.";
}
} else {
$this->messages[] = "L'identifiant de l'utilisateur (courriel) n'a pas été transmis.";
}
} else {
$this->messages[] = "Les informations concernant l'utilisateur (prénom, nom, courriel) n'ont pas été transmises.";
}
} else {
$this->messages[] = "Les informations concernant le projet coopératif n'ont pas été transmises.";
}
if (count($this->messages) > 0) {
$this->debug[] = print_r($this->messages, true);
}
$msg = (count($this->messages) > 0) ? 'erreur' : 'ok';
$retour = (object) array('msg' => $msg);
$this->envoyerJson($retour);
exit;
}
 
private function traiterProjetTags() {
if (strpos($this->projet, ',') === false) {
$this->projetTags = array('Projets coopératifs>'.$this->projet);
} else {
$projetTagsTxt = explode(',', $this->projet);
foreach ($projetTagsTxt as $tag) {
$this->projetTags[] = 'Projets coopératifs>'.$tag;
}
}
}
 
private function traiterTagObs($requeteDonnees) {
if (array_key_exists('tag-obs', $requeteDonnees) && $requeteDonnees['tag-obs'] != '') {
$this->tagsObs = explode(',', $requeteDonnees['tag-obs']);
}
foreach ($this->projetTags as $tag) {
$this->tagsObs[] = $tag;
}
}
 
private function traiterTagImg($requeteDonnees) {
if (array_key_exists('tag-img', $requeteDonnees) && $requeteDonnees['tag-img'] != '') {
$this->tagsImg = explode(',', $requeteDonnees['tag-img']);
}
foreach ($this->projetTags as $tag) {
$this->tagsImg[] = $tag;
}
}
 
private function ajouterChampsEtendusObs($obs_ids, $obs_a_champs_etendus) {
$champs_etendus_obs = array();
$gestionChampsEtendus = new GestionChampsEtendus($this->config, 'obs');
 
foreach ($obs_ids as $id_obs) {
$champs = array_shift($obs_a_champs_etendus);
if ($champs != null && is_array($champs)) {
foreach ($champs as $infosChamp) {
$cle = isset($infosChamp['cle']) ? $infosChamp['cle'] : '';
$label = isset($infosChamp['label']) ? $infosChamp['label'] : '';
$valeur = isset($infosChamp['valeur']) ? $infosChamp['valeur'] : '';
 
if (empty($cle) && !empty($label)) {
$cle = $gestionChampsEtendus->transformerLabelEnCle($label);
}
 
if (!empty($cle) && !empty($valeur)) {
$champEtendu = new ChampEtendu();
$champEtendu->id = $id_obs;
$champEtendu->cle = $cle;
$champEtendu->label = empty($label) ? $cle : $label;
$champEtendu->valeur = $valeur;
 
$champs_etendus_obs[] = $champEtendu;
}
}
}
}
 
if(! $champs_etendus_obs) return TRUE;
 
return $gestionChampsEtendus->ajouterParLots($champs_etendus_obs);
}
 
private function traiterImagesALierAObs($id_utilisateur, $ordreObs, $obs) {
$imgAAjouter = null;
if (is_array($obs['image_nom'])) {
$imgAAjouter = array();
foreach ($obs['image_nom'] as $index => $nom_image) {
$image = array();
$image['id_utilisateur'] = $id_utilisateur;
$image['id_obs'] = $ordreObs;
$image['nom'] = $nom_image;
$image['tags'] = isset($obs['image_tag'][$index]) ? explode(',',$obs['image_tag'][$index]) : '';
// on suppose que les b64 des images sont envoyés dans le même ordre que leurs noms
// TODO: indexer le tableau avec le nom des images
$image['b64'] = isset($obs['image_b64'][$index]) ? $obs['image_b64'][$index] : '';
$this->debug[] = 'Contient B64 : '.(empty($obs['image_b64']) ? 'non' : 'oui');
$imgAAjouter[] = $image;
}
} else {
if (!empty($obs['image_nom'])) {
$imgAAjouter = array();
$imgAAjouter['id_utilisateur'] = $id_utilisateur;
$imgAAjouter['id_obs'] = $ordreObs;
$imgAAjouter['nom'] = $obs['image_nom'];
//$imgAAjouter['tags'] = isset($obs['image_tag']) ? explode(',',$obs['image_tag']) : '';
$imgAAjouter['b64'] = isset($obs['image_b64']) ? $obs['image_b64'] : array();
$this->debug[] = 'Contient B64 : '.(empty($obs['image_b64']) ? 'non' : 'oui');
}
}
 
return $imgAAjouter;
}
 
private function stockerImagesEtLierAObs($img, $id_utilisateur, $utilisateur) {
$img_a_taguer_ids = array();
if (!isset($img['nom']) && is_array($img)) {
foreach ($img as $index => $image) {
$nomFichierImg = $this->traiterNomFichierImage($image['nom']);
$cheminImage = $this->config['cel']['chemin_stockage_temp']."/$nomFichierImg";
// Si l'image est transmise en base 64
if (empty($image['b64']) === false) {
$this->transformerBase64enFichier($cheminImage, $image['b64']);
}
 
$this->debug[] = 'Nom fichier img debut :'.$nomFichierImg;
$idImg = $this->ajouterImageSurDdEtBdd($utilisateur, $cheminImage, $nomFichierImg);
if ($idImg !== false) {
$liaisonOk = $this->lierObsEtImg($idImg, $id_utilisateur, $image['id_obs']);
if ($liaisonOk === true) {
$img_a_taguer_ids[] = $idImg;
if (isset($image['tags'])) {
$this->correspondanceIdImgTags[$idImg] = $image['tags'];
}
}
}
}
} else {
$nomFichierImg = $this->traiterNomFichierImage($img['nom']);
$cheminImage = $this->config['cel']['chemin_stockage_temp']."/$nomFichierImg";
// Si l'image est transmise en base 64
if (empty($img['b64']) === false) {
$this->transformerBase64enFichier($cheminImage, $img['b64']);
}
 
$this->debug[] = 'Nom fichier img debut :'.$nomFichierImg;
$idImg = $this->ajouterImageSurDdEtBdd($utilisateur, $cheminImage, $nomFichierImg);
if ($idImg !== false) {
$liaisonOk = $this->lierObsEtImg($idImg, $id_utilisateur, $img['id_obs']);
if ($liaisonOk === true) {
$img_a_taguer_ids[] = $idImg;
if (isset($img['tags'])) {
$this->correspondanceIdImgTags[$idImg] = $img['tags'];
}
}
}
}
 
return $img_a_taguer_ids;
}
 
private function affecterChampsManquantsUtilisateur($utilisateur) {
$gestion_utilisateur = new User($this->config);
$infos_complementaires = $gestion_utilisateur->obtenirUtilisateurSiExiste($utilisateur['courriel']);
if(!isset($utilisateur['id_utilisateur']) || trim($utilisateur['id_utilisateur']) == '') {
$utilisateur['id_utilisateur'] = ($infos_complementaires['connecte']) ? $infos_complementaires['id_utilisateur'] : $utilisateur['courriel'];
$utilisateur['prenom'] = trim($infos_complementaires['prenom']) != '' ? $infos_complementaires['prenom'] : $utilisateur['prenom'];
$utilisateur['nom'] = trim($infos_complementaires['nom']) != '' ? $infos_complementaires['nom'] : $utilisateur['nom'];
}
 
return $utilisateur;
}
 
private function supprimerSlashesProfond($valeur) {
$valeur = is_array($valeur) ? array_map(array($this, 'supprimerSlashesProfond'), $valeur) : stripslashes($valeur);
return $valeur;
}
 
private function getMaxOrdre($id_utilisateur) {
$ordre = null;
$identifiant = Cel::db()->quote($id_utilisateur);
$requete = "SELECT MAX(ordre) AS ordre ".
"FROM cel_obs ".
"WHERE ce_utilisateur = ".Cel::db()->proteger($id_utilisateur)." ";
 
$ordre_max = Cel::db()->requeterValeurUnique($requete);
if ($ordre_max !== false) {
$ordre = $ordre_max + 1;
}
return $ordre;
}
 
/**
* Transforme une date au format français (jj/mm/aaaa) dans un format Mysql (aaaa-mm-jj).
* @param string $dateFr date au format français (jj/mm/aaaa)
* @return string date au format Mysql (aaaa-mm-jj)
*/
private function transormerDateFrVersMysql($dateFr) {
$dateMysql = '0000-00-00';
$morceauxDate = explode('/', $dateFr);
if (count($morceauxDate) == 3) {
$dateMysql = implode('-', array_reverse($morceauxDate));
}
return $dateMysql;
}
 
private function taguerObs($obs_a_taguer_ids) {
if (count($obs_a_taguer_ids) > 0) {
foreach ($this->tagsObs as $hierarchieTag) {
$tagsALier = explode('>', $hierarchieTag);
$liaisonOk = $this->lierObsAMotsCles($obs_a_taguer_ids, $tagsALier);
if ($liaisonOk === false) {
$e = "Toutes les observations n'ont pas pu être liées aux mots-clés : $hierarchieTag";
$this->messages[] = $e;
}
}
}
}
 
private function lierObsAMotsCles($observations_ids, $tags) {
$chemin_parent = "/";
$listeIdsTags = array();
foreach ($tags as $tag) {
$tag = $this->nettoyerTag($tag);
if ($tag != '') {
$id_mot_cle = $this->gestionMotsClesObs->insererParCheminSiInexistant($tag, $chemin_parent, $this->utilisateur_id);
if ($id_mot_cle !== false) {
$listeIdsTags[] = $id_mot_cle;
$chemin_parent .= $tag."/";
}
}
}
 
$liaison_ok = $this->gestionMotsClesObs->lierParTableaux($listeIdsTags, $observations_ids, $this->utilisateur_id);
if($liaison_ok) {
foreach($observations_ids as $id) {
GestionMotsClesChemin::regenererIndexTexteMotCle($id, 'obs');
}
}
return $liaison_ok;
}
 
private function taguerImg($img_a_taguer_ids) {
if (count($img_a_taguer_ids) > 0) {
$this->debug[] = "Tags img : ".print_r($this->tagsImg, true);
foreach ($this->tagsImg as $hierarchieTag) {
$tagsALier = explode('>', $hierarchieTag);
$liaisonOk = $this->lierImgAMotsCles($img_a_taguer_ids, $tagsALier);
if ($liaisonOk === false) {
$e = "Toutes les images n'ont pas pu être liées aux mots-clés : $hierarchieTag";
$this->messages[] = $e;
}
}
}
// Liaison des tags spécifiques à chaque image s'il y en a
if (count($this->correspondanceIdImgTags) > 0) {
foreach ($this->correspondanceIdImgTags as $id_img => $tags) {
if ($tags != null && !empty($tags)) {
$this->lierImgAMotsCles(array($id_img), $tags);
}
}
}
}
 
private function lierImgAMotsCles($images_ids, $tags) {
$chemin_parent = "/";
$listeIdsTags = array();
foreach ($tags as $tag) {
$tag = $this->nettoyerTag($tag);
if ($tag != '') {
$id_mot_cle = $this->gestionMotsClesImages->insererParCheminSiInexistant($tag, $chemin_parent, $this->utilisateur_id);
if ($id_mot_cle !== false) {
$listeIdsTags[] = $id_mot_cle;
$chemin_parent .= $tag."/";
}
}
}
$liaison_ok = $this->gestionMotsClesImages->lierParTableaux($listeIdsTags, $images_ids, $this->utilisateur_id);
if($liaison_ok) {
foreach($images_ids as $id) {
GestionMotsClesChemin::regenererIndexTexteMotCle($id, 'images');
}
}
return $liaison_ok;
}
 
private function nettoyerTag($tag) {
$tag = trim($tag);
$tag = preg_replace('/(?:\s+|[,]+)/', ' ', $tag);
return $tag;
}
 
private function traiterNomFichierImage($fichierNom) {
$fichierNom = preg_replace('/[.](jpeg|jpg)$/i', '.jpg', strtolower(trim($fichierNom)));
return $fichierNom;
}
 
/**
* Décode l'image en base64,enregistre celle-ci sous forme de fichier du type de l'image
* dans un dossier temporaire.
*/
private function transformerBase64enFichier($cheminImage, $imageInfosB64) {
// Enleve la partie data:image qui permet la previsalisation pour firefox de l'image en base64
$imageBase64 = explode(';', $imageInfosB64);
$dataBase64 = explode(',',$imageBase64[1]);
$dataImg = base64_decode($dataBase64[1]);
 
$imageRessource = fopen($cheminImage, 'wb');
fwrite($imageRessource, $dataImg);
fclose($imageRessource);
 
if (file_exists($cheminImage) == false) {
$this->messages[] = "Erreur lors de la création du fichier";
}
}
 
public function lierObsEtImg($id_image, $utilisateur, $ordre_obs) {
$id_image = Cel::db()->proteger($id_image);
$id_obs = Cel::db()->proteger($this->obtenirIdObsPourIdentifiantEtOrdre($utilisateur, $ordre_obs));
 
$requete = 'INSERT INTO cel_obs_images '.
' (id_image, id_observation, date_liaison) '.
"VALUES ($id_image, $id_obs, NOW()) ".
' ON DUPLICATE KEY UPDATE id_image = id_image';
 
$liaison = true;
if (Cel::db()->executer($requete) === false) {
$this->messages[] = "La requête de liaison de l'obs $id_obs à l'image $id_image pour l'utilisateur $id_utilisateur a échouée.";
$liaison = false;
}
return $liaison;
}
 
private function obtenirIdObsPourIdentifiantEtOrdre($id_utilisateur, $ordre) {
 
$id_utilisateur = Cel::db()->proteger($id_utilisateur);
$ordre = Cel::db()->proteger($ordre);
 
$requete = 'SELECT id_observation '.
'FROM cel_obs '.
"WHERE ce_utilisateur = $id_utilisateur ".
" AND ordre = $ordre ";
 
$resultat = Cel::db()->requeter($requete);
 
$id_obs = (count($resultat) > 0) ? $resultat[0]['id_observation'] : false;
return $id_obs;
}
 
private function obtenirIdsObsPourTableauOrdres($id_utilisateur, $ordres) {
$this->debug[] = print_r($ordres,true);
$id_utilisateur = Cel::db()->proteger($id_utilisateur);
$ordres = array_map(array(Cel::db(),'proteger'), $ordres);
 
$requete = 'SELECT id_observation '.
'FROM cel_obs '.
"WHERE ce_utilisateur = $id_utilisateur ".
" AND ordre IN (".implode(',',$ordres).") ";
$this->debug[] = $requete;
$resultat = Cel::db()->requeter($requete);
$ids = array();
foreach($resultat as $id) {
$ids[] = $id['id_observation'];
}
return $ids;
}
 
public function nettoyerImagesUploades() {
$dossierStockage = $this->config['cel']['chemin_stockage_temp'].'/';
if (is_dir($dossierStockage)) {
$objets = scandir($dossierStockage);
if ($objets !== false) {
foreach ($objets as $objet) {
$chemin = $dossierStockage.$objet;
if (is_file($chemin)) {
$filemtime = @filemtime($chemin);
if ($filemtime !== false) {
$suppression = (time() - $filemtime >= self::DUREE_DE_VIE_IMG) ? true : false;
if ($suppression === true) {
unlink($chemin);
}
}
}
}
}
}
}
 
/**
* Ajoute une image dans la base de données et stocke le fichier en fabriquant les miniatures,
* renvoie le nouvel id d'image en cas de succès
*
* @param string $utilisateur l'utilisateur
* @param string $cheminImage le chemin vers le fichier original de l'image
* @param string $nomFichierImage le nom du fichier original de l'image
*/
public function ajouterImageSurDdEtBdd($utilisateur, $cheminImage, $nomFichierImage) {
$idImage = false;
$idUtilisateur = $utilisateur['id_utilisateur'];
$nouvelOrdre = $this->obtenirNouvelOrdrePourUtilisateur($idUtilisateur);
if ($nouvelOrdre !== false) {
if (file_exists($cheminImage)) {
$extracteurMetadonnees = new ExtracteurMetadonnees();
$metadonnees = $extracteurMetadonnees->extraireMetadonnees($cheminImage) ;
if ($metadonnees !== false) {
$infosImage = $metadonnees;
$infosImage['ordre'] = $nouvelOrdre;
$infosImage['publiable_eflore'] = 'false';
$infosImage['nom_original'] = $nomFichierImage;
$infosImage['ce_utilisateur'] = $idUtilisateur;
$infosImage['courriel_utilisateur'] = $utilisateur['courriel'];
$infosImage['nom_utilisateur'] = $utilisateur['nom'];
$infosImage['prenom_utilisateur'] = $utilisateur['prenom'];
$infosImage['md5'] = md5_file($cheminImage);
$this->debug[] = 'Nom fichier img meta :'.$nomFichierImage;
$requete = $this->construireRequeteInsertionImage($infosImage);
$resultat = Cel::db()->executer($requete);
if ($resultat !== false) {
$idImage = $this->obtenirIdImagePourIdentifiantEtOrdre($idUtilisateur, $nouvelOrdre);
if ($idImage !== false) {
$manipulateurImage = new ImageRecreation($this->config);
$stockageOk = $manipulateurImage->stockerFichierOriginal($cheminImage, $idImage);
if ($stockageOk) {
$miniatureChemin = str_replace('.jpg', '_min.jpg', $cheminImage);
if (file_exists($miniatureChemin)) {
if (@unlink($miniatureChemin) === false) {
$this->messages[] = "La miniature de l'image n'a pu être supprimée.";
}
}
 
} else {
$this->messages[] = "Une erreur s'est produite lors du stockage du fichier.";
}
} else {
$this->messages[] = "Impossible d'obtenir le nouvel identifiant de l'image";
}
} else {
$this->messages[] = "Echec de l'insertion dans la base de donnees des informations de l'image.";
}
} else {
$this->messages[] = "Erreur lors de l'extraction des metadonnées.";
}
} else {
$this->messages[] = "L'image originale est introuvable sur le serveur.";
}
} else {
$this->messages[] = "Erreur lors du calcul du nouvel ordre de l'image.";
}
return $idImage;
}
 
private function obtenirNouvelOrdrePourUtilisateur($id_utilisateur) {
$id_utilisateur = Cel::db()->proteger($id_utilisateur);
 
$requete = 'SELECT MAX(ordre) as max_ordre '.
'FROM cel_images '.
"WHERE ce_utilisateur = $id_utilisateur ";
$resultat = Cel::db()->requeter($requete);
 
$ordre = ($resultat) ? ++$resultat[0]['max_ordre'] : 0;
return $ordre;
}
 
private function obtenirIdImagePourIdentifiantEtOrdre($id_utilisateur, $ordre) {
$id_utilisateur = Cel::db()->proteger($id_utilisateur);
$ordre = Cel::db()->proteger($ordre);
 
$requete = 'SELECT id_image '.
'FROM cel_images '.
"WHERE ce_utilisateur = $id_utilisateur ".
" AND ordre = $ordre ";
$resultat = Cel::db()->requeter($requete);
 
$id_image = (count($resultat) > 0) ? $resultat[0]['id_image'] : false;
return $id_image;
 
}
 
private function construireRequeteInsertionImage($informations) {
$champs = array('date_creation');
$valeurs = array('CURRENT_TIMESTAMP()');
 
foreach ($informations as $champ => $valeur) {
$champs[] = $champ;
$valeurs[] = is_null($valeur) ? 'NULL' : Cel::db()->proteger($valeur);
if ($champ == 'date_creation' && $valeur != 'NULL') {
$champs[] = 'date_creation';
$valeurs[] = Cel::db()->proteger($valeur);
}
}
$champs = implode(', ', $champs);
$valeurs = implode(', ', $valeurs);
 
$requete = "INSERT INTO cel_images ($champs) VALUES ($valeurs) ";
 
return $requete;
}
}
?>
/branches/v2.3-faux/jrest/services/CelImage.php
New file
0,0 → 1,137
<?php
// declare(encoding='UTF-8');
/**
* Service fournissant la liste des ids des images liées à une observation.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* Cas d'utilisation GET :
* /CelImage/liste-ids?obsId=[0-9]+ : ids des images liées à l'observation possédant l'identifiant 'obsId'.
*
* Cas d'utilisation DELETE :
*
* Sortie :
* Type de sortie : json (par défaut), HTML en cas d'erreur.
*
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2010, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
class CelImage extends Cel {
 
/**
* Méthode appelée avec une requête de type GET.
*/
public function getElement($params) {
$parametres = $this->traiterParametres(array('mode'), $params, false);
extract($parametres);
$contenu = '';
 
$retour = null;
if (isset($mode)) {
$methode = $this->traiterNomMethodeGet($mode);
if (method_exists($this, $methode)) {
$this->parametres = array_shift($params);
$retour = $this->$methode();
} else {
$service = get_class($this);
$this->messages[] = "Ce type de mode '$mode' pour le service '$service' n'est pas disponible.";
}
} else {
$this->messages[] = "Vous devez indiquer un type de mode d'interrogation.";
}
 
if (is_null($retour)) {
$this->messages[] = "Un problème est survenu lors de l'appel au service CelImage";
}
$this->envoyerJson($retour);
}
private function getImage() {
$image = null;
if (isset($_GET['imgId'])) {
$recherche = new RechercheImage($this->config);
$params = array('id_image' => $_GET['imgId'], 'transmission' => "1");
$image = $recherche->rechercherImages(null, $params, 0, 1);
if(!empty($image)) {
$image = $image[0];
}
}
return $image;
}
 
/**
* Service fournissant la liste des ids des images liées à une observation.
* Format de l'url du WS :
* /CelImage/liste-ids?obsId=[0-9]+ : ids des images liées à l'observation possédant l'identifiant 'obsId'.
*/
private function getListeIds() {
$ids = array();
 
if (isset($_GET['obsId'])) {
$observations = $this->traiterValeursMultiples($_GET['obsId']);
 
if (! is_null($observations)) {
$requete = 'SELECT co.id_observation, cim.id_image '.
'FROM cel_obs AS co '.
' LEFT JOIN cel_obs_images AS coi '.
' ON (coi.id_observation = co.id_observation) '.
' LEFT JOIN cel_images AS cim '.
' ON (coi.id_image = cim.id_image) '.
"WHERE co.id_observation IN ($observations) ";
 
$resultat_requete_images = Cel::db()->requeter($requete);
 
$infos = array();
if(is_array($resultat_requete_images)) {
$infos = $resultat_requete_images;
}
 
foreach ($infos as $info) {
if(is_numeric($info['id_image'])) {
$ids[$info['id_observation']][] = (int) $info['id_image'];
}
}
}
}
return $ids;
}
 
/**
* Méthode appelée avec une requête de type DELETE.
* Supprime les infos sur l'image et le fichier correspondant à l'ordre passé en parametre
* Supporte la suppression multiple en passant plusieurs numéros séparés par des virgules
*
* @param int uid[0] id utilisateur
* @param string uid[1] : ordre(s) image(s) obligatoire(s) séparés par des virgules
*
*/
public function deleteElement($uid){
$this->controlerAccessibiliteWs();
$this->controleAppelIpAutorisee();
 
$idImage = isset($uid[0]) ? $uid[0] : '';
$this->verifierIdentifiantImage($idImage);
$idsImages = explode(',', $idImage);
 
$gestionnaireImage = new GestionImage($this->config);
$suppressionImage = $gestionnaireImage->supprimerImage($idsImages);
 
if ($suppressionImage) {
$this->envoyer('OK');
} else {
$this->envoyer("Au moins une image « $idImage » n'a pu être supprimé.");
}
}
 
private function verifierIdentifiantImage($chaine) {
$ok = preg_match('/^(?:[0-9]+,)*[0-9]+$/', $chaine);
if ($ok == false) {
$msg = "Indiquer un ou plusieurs identifiants d'image séparés par des virgules.";
$this->envoyerMessageErreur(412, $msg);// Precondition Failed
}
return $ok;
}
}
/branches/v2.3-faux/jrest/services/NameSearch.php
New file
0,0 → 1,75
<?php
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author David Delon <david.delon@clapas.net>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
/**
*
* in : utf8
* out : utf8
*
* NameSearch.php
*
* Cas d'utilisation :
* Service completion nom scientifique
*
* 1 : L'application recoit un debut de nom scientifique ainsi qu'un code de référentiel
* 2 : Si le genre recu est >1, l'application retourne les 50 premieres genre commencant par ce prefixe
* 3 : Si l'espece est presente l'application retourne les 50 premieres genre+espece commencant par ce prefixe
*/
class NameSearch extends Cel {
public function getRessource(){
//TODO: description du service à renvoyer
print "[]";
return;
}
 
public function getElement($uid){
$liste_genre_espece = array();
$referentiel = null;
$genre = null;
$espece = null;
if(isset($uid[0])) {
$referentiel = $uid[0];
}
if(isset($uid[1])) {
$genre = $uid[1];
}
if(isset($uid[2])) {
$espece = $uid[2];
}
 
$chercheur_infos_taxon = new RechercheInfosTaxonBeta($this->config, $referentiel);
$liste_genre_espece = $chercheur_infos_taxon->rechercherGenreEspeceSurPrefixe($genre,$espece);
$this->envoyerJson($liste_genre_espece);
return true;
}
}
 
/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log$
* Revision 1.6 2008-01-30 08:57:28 ddelon
* fin mise en place mygwt
*
* Revision 1.5 2007-05-21 18:13:30 ddelon
* Refactoring et documentation
*
*
*/
?>
/branches/v2.3-faux/jrest/services/CelObs.php
New file
0,0 → 1,287
<?php
// declare(encoding='UTF-8');
/**
* Service permettant de récupérer toutes les informations d'une observation publique.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* Cas d'utilisation :
* GET /CelObs/[id] : oû id est l'identifiant d'une observation publique
*
* @author Jean-Pascal MILCENT <jpm@clapas.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright © 2013, Jean-Pascal MILCENT
*/
class CelObs extends Cel {
private $rechercheObs = null;
private $chpsEtendus = null;
private $donnees = null;
 
public function __construct($config) {
parent::__construct($config);
$this->rechercheObs = new RechercheObservation($config);
$this->chpsEtendus = new GestionChampsEtendus($config, 'obs');
 
$this->chargerNomsTablesReferentiels();
}
 
private function chargerNomsTablesReferentiels() {
// Créé des attributs avec le code du référentiel : bdtfx, bdtxa, apd, isfan
foreach ( $this->config['referentiels'] as $referentiel => $table) {
$this->$referentiel = $table;
}
}
 
function getElement($ressources){
$retour = false;
$idObs = $ressources[0];
if (isset($idObs) && preg_match('/^[0-9]+$/', $idObs)) {
 
$criteres = array('id_observation' => $idObs, 'transmission' => 1);
$obsTrouvee = $this->rechercheObs->rechercherObservations(null, $criteres, 0, 1)->get();
 
$observation = array();
if (is_array($obsTrouvee) && count($obsTrouvee) > 0) {
$observation = $obsTrouvee[0];
}
$observation = $this->preparerChamps($observation);
$observation = $this->selectionnerChamps($observation);
$observation = $this->formaterClePourJs($observation);
 
$champsEtendus = $this->chpsEtendus->consulter($idObs);
if (is_array($champsEtendus) && count($champsEtendus) > 0) {
$champsEtendus = $this->preparerChampsEtendus($champsEtendus);
$observation['extension'] = $champsEtendus;
}
 
$this->envoyerJson($observation);
$retour = true;
}
return $retour;
}
 
private function preparerChamps($champs) {
if (isset($champs['date_observation'])) {
$date = explode(' ', $champs['date_observation']);
$champs['date_observation'] = $date[0];
}
return $champs;
}
 
private function selectionnerChamps($observation) {
$champs = array('id_observation', 'nom_sel', 'nom_ret', 'nom_ret_nn', 'nt', 'famille',
'nom_referentiel', 'ce_zone_geo', 'zone_geo', 'lieudit', 'station', 'milieu', 'latitude', 'longitude',
'geodatum', 'date_observation', 'mots_cles_texte', 'commentaire', 'date_creation', 'date_modification',
'date_transmission', 'code_insee_calcule', 'abondance', 'certitude', 'phenologie', 'altitude');
$selection = array();
foreach ($champs as $chp) {
if (isset($observation[$chp])) {
$selection[$chp] = $observation[$chp];
}
}
return $selection;
}
 
private function formaterClePourJs(Array $tableau) {
$tableauJs = array();
foreach ($tableau as $cle => $valeur) {
if ($cle == 'ce_zone_geo') {
$cle = 'codeZoneGeo';
} else {
$cle = str_replace(' ', '', ucwords(str_replace('_', ' ', $cle)));
$cle{0} = strtolower($cle{0});
}
$tableauJs[$cle] = $valeur;
}
return $tableauJs;
}
 
private function preparerChampsEtendus($champs) {
$retour = array();
foreach ($champs as $chp) {
$retour[$chp['cle']] = array('valeur' => $chp['valeur'], 'label' => $chp['label']);
}
return $retour;
}
 
/**
* Méthode appelée avec une requête de type POST et un identifiant d'observation.
* Modifie une observation en fonction des informations envoyées en POST.
* Utilisé par:
* - service:del:0.1/determinations/ : ValiderDetermination.php::modifierObservationParDetermination()
* - service:del:0.1/observations/#idObs [POST] : pour dépublier une observation
*
* @param $uid array $uid[0] (int) : identifiant observation
* @param pairs array tableau contenant les champs à modifier sous la forme : nom_du_champ=nouvelle_valeur
*/
public function updateElement($ressources, $donnees) {
$this->donnees = $donnees;
if ($this->controlerAccessibiliteWs()) {
if ($this->controleAppelIpAutorisee()) {
$idObs = isset($ressources[0]) ? $ressources[0] : '';
$this->verifierIdentifiantObs($idObs);
 
if (count($this->donnees) == 1) {
$donneesObligatoires = array('transmission');
if ($this->verifierDonneesObligatoires($donneesObligatoires)) {
$this->depublierObs($idObs);
}
} else if (count($this->donnees) == 3) {
$donneesObligatoires = array('id_observation', 'nom_sel_nn', 'nom_referentiel');
if ($this->verifierDonneesObligatoires($donneesObligatoires)) {
$this->accepterPropositionDEL($idObs);
}
} else {
$msg = "La modification complète d'une observation n'est pas implémentée.";
$this->envoyerMessageErreur(501, $msg);
}
 
$this->envoyer('ok');
}
}
return true;
}
 
private function verifierIdentifiantObs($chaine) {
$ok = preg_match('/^[0-9]+$/', $chaine);
if ($ok == false) {
$msg = "Indiquer un seul identifiant numérique d'observation.";
$this->envoyerMessageErreur(412, $msg);
}
return $ok;
}
 
private function verifierDonneesObligatoires($champsObligatoires) {
foreach ($champsObligatoires as $param) {
if (! isset($this->donnees[$param])) {
$msg = sprintf("Paramètre %s manquant (parmi %s)", $param, implode(', ', $champsObligatoires));
$this->envoyerMessageErreur(412, $msg);
}
}
return true;
}
 
private function depublierObs($idObs) {
$gestionnaireObs = new GestionObservation($this->config);
$depublication = $gestionnaireObs->modifierTransmissionObservation($idObs, false);
if ($depublication === false) {
$msg = "Un problème est survenu (voir log). Les observations n'ont pas pu être dépubliées.";
$this->envoyerMessageErreur(304, $msg);
}
}
 
/**
* Modifie une observation aveec les infos d'une proposition :
* Nous complétons les données de la proposition acceptée ici car:
* 1) la table tb_del.del_commentaire ne contient pas toutes les informations nécessaires
* 2) la table tb_del.del_commentaire ne *devrait* pas contenir beaucoup plus que nom_sel et nom_sel_nn
* 3) la génération de ces données ici, au moment de l'UPDATE, est le meilleur garant de leur fiabilité
*/
private function accepterPropositionDEL($idObs) {
$gestion_observation = new GestionObservation($this->config);
$donnees = array_map('trim', $this->donnees);
$donneesAModifier = array(
'certitude' => 'Certaine',
'nom_referentiel' => $donnees['nom_referentiel'],
);
// TODO : la récupération des infos du nom est aussi effectué par la suite voir ce qu'il faut garder
$infosNoms = $this->getNomInfos($donnees['nom_sel_nn'], $donnees['nom_referentiel']);
if ($infosNoms) {
$donneesAModifier = array_merge($donneesAModifier, $infosNoms);
}
 
$modification = $gestion_observation->modifierObservationPublique($idObs, $donneesAModifier);
 
if ($modification) {
// TODO: en modifiant bien la classe de gestion mots clés, on aurait peut être pas besoin de l'id
// utilisateur (car l'id de l'obs est déjà sans ambiguité)
$idUtilisateur = $this->rechercheObs->obtenirIdUtilisateurPourIdObs($idObs);
// supression des éventuelles liaison de l'obs avec le mot clé contenu dans obsKeywordDelete
$gestionMotsClesObs = new GestionMotsClesChemin($this->config, 'obs');
$supp_liaison_mot_cle = $gestionMotsClesObs->supprimerLiaisonPourMotCleEtIdElementLie('aDeterminer', $idObs, $idUtilisateur);
} else {
$msg = "Impossible de modifier l'observation associée à cet identifiant. Erreur mysql : " . mysql_error();
$this->envoyerMessageErreur(500, $msg);// Internal Server Error
}
}
 
// TODO : cette méthode et celles qui en dépendent sont peut être inutiles au vue de la méthode traiterEspece() de GestionObservation
private function getNomInfos($id_nom, $code_referentiel) {
$retour = false;
if ($id_nom && $code_referentiel) {
switch ($code_referentiel) {
case 'bdtfx' :
$retour = $this->getInfosBdtfx($id_nom);
break;
case 'bdtxa' :
$retour = $this->getInfosBdtxa($id_nom);
break;
case 'isfan' :
$retour = $this->getInfosIsfan($id_nom);
break;
case 'apd' :
$retour = $this->getInfosApd($id_nom);
break;
}
}
return $retour;
}
 
private function getInfosBdtfx($id_nom) {
$idNomP = CEL::db()->proteger($id_nom);
$requete = "SELECT o.num_nom_retenu AS nom_ret_nn, o.num_taxonomique AS nt, o.famille, ".
" CONCAT(o.nom_sci, ' ', o.auteur) AS nom_sel, ".
" CONCAT(ret.nom_sci, ' ', ret.auteur) AS nom_ret ".
"FROM {$this->bdtfx} AS o ".
" LEFT JOIN {$this->bdtfx} AS ret ON (o.num_nom_retenu != 0 AND o.num_nom_retenu = ret.num_nom) ".
"WHERE o.num_nom = $idNomP ".
' -- '.__FILE__.' : '.__LINE__;
$resultat = Cel::db()->requeterLigne($requete);
return $resultat;
}
 
private function getInfosBdtxa($id_nom) {
$idNomP = CEL::db()->proteger($id_nom);
// Champ "num_tax" au lieu de "num_taxonomique"
$requete = "SELECT o.num_nom_retenu AS nom_ret_nn, o.num_tax AS nt, o.famille, ".
" CONCAT(o.nom_sci, ' ', o.auteur) AS nom_sel, ".
" CONCAT(ret.nom_sci, ' ', ret.auteur) AS nom_ret ".
"FROM {$this->bdtxa} AS o ".
" LEFT JOIN {$this->bdtxa} AS ret ON (o.num_nom_retenu != 0 AND o.num_nom_retenu = ret.num_nom) ".
"WHERE o.num_nom = $idNomP ".
' -- '.__FILE__.' : '.__LINE__;
$resultat = Cel::db()->requeterLigne($requete);
return $resultat;
}
 
private function getInfosIsfan($id_nom) {
$idNomP = CEL::db()->proteger($id_nom);
// Champ "num_tax" au lieu de "num_taxonomique"
$requete = "SELECT o.num_nom_retenu AS nom_ret_nn, o.num_taxonomique AS nt, o.famille, ".
" CONCAT(o.nom_sci, ' ', o.auteur) AS nom_sel, ".
" CONCAT(ret.nom_sci, ' ', ret.auteur) AS nom_ret ".
"FROM {$this->isfan} AS o ".
" LEFT JOIN {$this->isfan} AS ret ON (o.num_nom_retenu != 0 AND o.num_nom_retenu = ret.num_nom) ".
"WHERE o.num_nom = $idNomP ".
' -- '.__FILE__.' : '.__LINE__;
$resultat = Cel::db()->requeterLigne($requete);
return $resultat;
}
 
private function getInfosApd($id_nom) {
$idNomP = CEL::db()->proteger($id_nom);
// Champ "num_tax" au lieu de "num_taxonomique"
$requete = "SELECT o.num_nom_retenu AS nom_ret_nn, o.num_taxonomique AS nt, o.famille, ".
" CONCAT(o.nom_sci, ' ', o.auteur) AS nom_sel, ".
" CONCAT(ret.nom_sci, ' ', ret.auteur) AS nom_ret ".
"FROM {$this->apd} AS o ".
" LEFT JOIN {$this->apd} AS ret ON (o.num_nom_retenu != 0 AND o.num_nom_retenu = ret.num_nom) ".
"WHERE o.num_nom = $idNomP ".
' -- '.__FILE__.' : '.__LINE__;
$resultat = Cel::db()->requeterLigne($requete);
return $resultat;
}
}
/branches/v2.3-faux/jrest/services/GroupesChampsEtendus.php
New file
0,0 → 1,16
<?php
 
// in utf8
// out utf8
 
// Fournit la liste des groupes de champs etendus
class GroupesChampsEtendus extends Cel {
function getRessource() {
$gestion_champs_etendus = new GestionChampsEtendus($this->config, 'obs');
$groupes = $gestion_champs_etendus->consulterGroupesChampsEtendusPredefinis();
$this->envoyerJson($groupes);
return true;
}
}
/branches/v2.3-faux/jrest/services/ExportXLS.php
New file
0,0 → 1,298
<?php
 
/**
* @category PHP
* @package jrest
* @author Raphaël Droz <raphael@tela-botania.org>
* @copyright 2013 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
*/
 
/**
* Service d'export de données d'observation du CEL au format XLS
*
* Format du service :
* POST /ExportXLS
* POST /ExportXLS/<Utilisateur>
* TODO: GET /ExportXLS/<Utilisateur> [ sans "range" ? ]
*
* Les données POST acceptées sont:
* range (obligatoire): un range d'id_observation sous la forme d'entier ou d'intervalles d'entiers
* séparés par des virgules ou bien '*' (pour toutes)
* TODO: limit
* TODO: départ
* TODO: sets (ou colonnes, ou extended)
* TODO: + les critères supportés par fabriquerSousRequeteRecherche()
*
* Si <Utilisateur> est fourni, celui-ci doit être authentifié
* TODO: export des données public et non-sensible d'un utilisateur
*
* Si <Utilisateur> est fourni, le observations seront le résultat de l'intersection des 2 contraintes
*
*/
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(realpath(__FILE__))) . '/lib');
// TERM
ini_set('html_errors', 0);
ini_set('xdebug.cli_color', 2);
require_once('lib/PHPExcel/Classes/PHPExcel.php');
require_once('lib/FormateurGroupeColonne.php');
 
class ExportXLS extends Cel {
 
private $id_utilisateur = NULL;
private $parametres_defaut = array("range" => "*",
"format" => "CSV");
private $filtres_autorises = array(
'id_utilisateur' => 'id_utilisateur',
'utilisateur' => 'courriel_utilisateur',
'commune' => 'zone_geo',
'dept' => 'departement',
'projet' => 'mots_cles',
'num_taxon' => 'nt',
'date_debut' => 'date_debut',
'date_fin' => 'date_fin',
'taxon' => 'taxon'
);
 
function ExportXLS($config) {
parent::__construct($config);
}
function getRessource() {
return $this->getElement(array());
}
function getElement($uid) {
$parametres_format = $this->traiterParametresFormat($uid, $_GET);
$filtres = $this->traiterFiltres($_GET);
$this->export($parametres_format, $filtres);
exit;
}
function traiterParametresFormat($uid, $params) {
$parametres = $this->parametres_defaut;
if(isset($params['format'])) {
if($params['format'] == 'csv') $parametres['format'] = 'CSV';
if($params['format'] == 'xls') $parametres['format'] = 'Excel5';
if($params['format'] == 'xlsx') $parametres['format'] = 'Excel2007';
if($params['format'] == 'pdf') $parametres['format'] = 'pdf';
}
// TODO: $params['part'] pour le multi-part
$parametres['widget'] = isset($params['widget']) ? $params['widget'] : 'CEL';
$parametres['debut'] = isset($params['debut']) ? intval($params['debut']) : 0;
$parametres['limite'] = isset($params['limite']) ? intval($params['limite']) : 0;
$parametres['id_utilisateur'] = $this->traiterIdUtilisateur($uid);
$parametres['groupe_champs'] = isset($params['colonnes']) ? $params['colonnes'] : 'standard,avance';
return $parametres;
}
function traiterIdUtilisateur($uid) {
$id_utilisateur = null;
// TODO: controleUtilisateur()
if(isset($uid[0])) {
$id_utilisateur = intval($uid[0]);
}
return $id_utilisateur;
}
function traiterFiltres($params) {
$obs_ids = $this->traiterObsIds($params);
$filtres = array();
if(!$obs_ids || count($obs_ids) == 1 && $obs_ids[0] == '*') {
unset($filtres['sql_brut']);
}
else {
$filtres = Array('sql_brut' =>
sprintf('id_observation IN (%s)', implode(',', $obs_ids)));
}
foreach($params as $cle => $valeur) {
if(trim($valeur) != '' && isset($this->filtres_autorises[$cle])) {
$filtres[$this->filtres_autorises[$cle]] = $valeur;
}
}
return $filtres;
}
function traiterObsIds($params) {
$obs_ids = Array('*');
if (isset($params['range']) && trim($params['range']) != '*') {
// trim() car: `POST http://url<<<"range=*"`
$obs_ids = self::rangeToList(trim($params['range']));
}
return $obs_ids;
}
 
/*
* $param: Tableau associatif, indexes supportés:
* - widget: le nom du widget d'origine (utilisé pour les méta-données du tableur)
*
*/
function export(Array $parametres_format = Array(),Array $filtres = array()) {
$chercheur_observations = new RechercheObservation($this->config);
 
$observations = $chercheur_observations
->rechercherObservations($parametres_format['id_utilisateur'], $filtres, $parametres_format['debut'], $parametres_format['limite'], TRUE)
->get();
// debug //echo ($chercheur_observations->requete_selection_observations);
// XXX: malheureusement l'instance de JRest n'est pas accessible ici
if(!$observations) {
header('HTTP/1.0 204 No Content');
exit;
}
 
if($parametres_format['format'] == 'pdf') {
if(count($observations) > 300) die('too much');
require_once('GenerateurPDF.php');
 
$pdf = new GenerateurPDF();
$pdf->export($observations);
//$pdf->export1($observations);
//$pdf->export2($observations);
$pdf->pdf->Output('etiquettes.pdf', 'I');
die;
}
 
$colonnes = FormateurGroupeColonne::nomEnsembleVersListeColonnes($parametres_format['groupe_champs']);
// $colonne_abbrev = array_keys($colonnes);
$objPHPExcel = $this->gerenerFeuilleImportFormatee($parametres_format);
$feuille = $objPHPExcel->setActiveSheetIndex(0);
// attention formaterColonnesFeuille prend ses 2 premiers paramètres par référence
$this->formaterColonnesFeuille($feuille, $colonnes, $parametres_format);
$objPHPExcel->getActiveSheet()->getDefaultColumnDimension()->setWidth(12);
 
$no_ligne = 2;
foreach ($observations as $obs) {
// attention traiterLigneObservation prend ses 3 premiers paramètres par référence
$this->traiterLigneObservation($obs, $colonnes, $feuille, $no_ligne);
$no_ligne++;
}
 
$this->envoyerFeuille($objPHPExcel, $parametres_format);
}
private function envoyerFeuille($objPHPExcel, $parametres_format) {
header("Content-Type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=\"liste.xls\"; charset=utf-8");
header("Cache-Control: max-age=0");
// csv|xls|xlsx => CSV|Excel5|Excel2007
// Note: le format Excel2007 utilise un fichier temporaire
$generateur = PHPExcel_IOFactory::createWriter($objPHPExcel, $parametres_format['format']);
$generateur->save('php://output');
exit;
}
public function traiterLigneObservation(&$obs, &$colonnes, &$feuille, $no_ligne) {
$no_colonne = 0;
foreach($colonnes as $abbrev => $colonne) {
$valeur = null;
if($colonne['extra'] == 2 || ! is_null($colonne['dyna'])) continue;
// valeur direct depuis cel_obs ?
if(isset($obs[$abbrev])) $valeur = $obs[$abbrev];
 
// pré-processeur de la champs
if(function_exists($colonne['fonction'])) {
$valeur = $colonne['fonction']($valeur);
} elseif(method_exists('FormateurGroupeColonne', $colonne['fonction'])) {
$valeur = call_user_func(array('FormateurGroupeColonne', $colonne['fonction']), $valeur);
} elseif(method_exists(__CLASS__, $colonne['fonction'])) {
$valeur = call_user_func(array(__CLASS__, $colonne['fonction']), $valeur);
} elseif($colonne['fonction']) {
die("méthode {$colonne['fonction']} introuvable");
}
// fonction pour obtenir des champs (étendus)
elseif(function_exists($colonne['fonction_data'])) {
$valeur = $colonne['fonction_data']($obs);
}
elseif(method_exists(__CLASS__, $colonne['fonction_data'])) {
$valeur = call_user_func(array(__CLASS__, $colonne['fonction_data']), $obs);
}
// // cette section devrait être vide:
// // cas particuliers ingérable avec l'architecture actuelle:
if(false && $abbrev == 'date_observation' && $valeur == "0000-00-00") {
/* blah */
}
if($abbrev == 'images') {
$valeur = FormateurGroupeColonne::getImages($obs, $this->id_utilisateur, $this);
}
if($abbrev == 'nom-commun') {
$valeur = FormateurGroupeColonne::getNomCommun_v4($obs, $this);
}
 
// // fin de section "cas particuliers"
$feuille->setCellValueByColumnAndRow($no_colonne, $no_ligne, $valeur);
$no_colonne++;
}
}
private function gerenerFeuilleImportFormatee($parametres_format) {
$objPHPExcel = new PHPExcel();
$objPHPExcel->getProperties()->setCreator($parametres_format['widget']) // ou $uid ?
->setLastModifiedBy("XX") // TODO: $uid
->setTitle("Export des observation du carnet en ligne") // TODO
->setSubject("Export") // TODO
->setDescription("Export");
//->setKeywords("office PHPExcel php")
//->setCategory("Test result file")
$objPHPExcel->getActiveSheet()->setTitle("Observations");
return $objPHPExcel;
}
private function formaterColonnesFeuille(&$feuille, &$colonnes, $parametres_format) {
$colid = 0;
foreach($colonnes as $colonne) {
if($colonne['extra'] == 2) continue;
$feuille->setCellValueByColumnAndRow($colid, 1, $colonne['nom']);
if($colonne['extra'] == 1) {
$feuille->getStyleByColumnAndRow($colid, 1)->getBorders()->applyFromArray(
array(
'allborders' => array(
'style' => PHPExcel_Style_Border::BORDER_DASHDOT,
'color' => array('rgb' => PHPExcel_Style_Color::COLOR_BLUE)
)
)
);
}
if(! $colonne['importable']) {
$feuille->getStyleByColumnAndRow($colid, 1)->getFill()->applyFromArray(
array(
'type' => PHPExcel_Style_Fill::FILL_SOLID,
'color' => array('rgb' => PHPExcel_Style_Color::COLOR_YELLOW)
)
);
}
$colid++;
}
}
 
/*
* @param $fieldSets: un range, eg: 1-5,8,32,58-101
* @return un tableau trié, eg: 1,2,3,4,5,8,32,58,...,101
* http://stackoverflow.com/questions/7698664/converting-a-range-or-partial-array-in-the-form-3-6-or-3-6-12-into-an-arra
*/
static function rangeToList($in = '') {
$inSets = explode(',', $in);
$outSets = array();
 
foreach($inSets as $inSet) {
list($start,$end) = explode('-', $inSet . '-' . $inSet);
// ignore les ranges trop importants
if($start > 10000000 || $end > 10000000 || abs($start-$end) > 10000) continue;
$outSets = array_merge($outSets,range($start,$end));
}
$outSets = array_unique($outSets);
$outSets = array_filter($outSets, 'is_numeric');
sort($outSets);
return $outSets;
}
}
/branches/v2.3-faux/jrest/services/CelMessage.php
New file
0,0 → 1,86
<?php
class CelMessage extends Cel {
private $mode = 'obs';
/**
* Méthode appelée avec une requête de type POST avec un identifiant d'obs.
* Envoi un message à l'utilisateur ayant saisi l'observation
*
* @param int $uid[0] mode interrogation (obs ou image)
* @param int $uid[1] identifiant observation ou image suivant le mode
* @param pairs array tableau contenant les valeurs du formulaire de messagerie
* (même format que le web service messagerie utilisateur de l'annuaire)
*/
public function updateElement($uid,$pairs)
{
$this->verifierParametresObligatoires($uid, $pairs);
if(isset($pairs['type_envoi'])) {
unset($pairs['type_envoi']);
}
if($uid[0] != 'obs' && $uid[0] != 'image') {
$info = array();
$info = 'Aucun mode n\'a été indiqué ';
$this->envoyer($info, 'text/html', 'utf-8', false);
exit;
} else {
$this->mode = $uid[0];
$id = $uid[1];
$methode = 'obtenirCourrielUtilisateurPourId'.ucwords($this->mode);
$courriel_utilisateur = $this->$methode($id);
if($courriel_utilisateur !== false) {
$resultat = $this->envoyerRequeteMessage($courriel_utilisateur, $pairs);
$this->envoyerJson($resultat);
exit;
} else {
$info = array();
$info = 'Impossible de trouver le courriel associé à cet identifiant ';
$this->envoyer($info, 'text/html', 'utf-8', false);
exit;
}
}
}
private function envoyerRequeteMessage($courriel_utilisateur, $pairs) {
$base_url = $this->config['settings']['baseURLServicesAnnuaireTpl'];
$rest_client = $this->getRestClient();
$url_messagerie = str_replace('%s', "utilisateur/".urlencode($courriel_utilisateur)."/message", $base_url);
$resultat_json = $rest_client->modifier($url_messagerie, $pairs);
$resultat = json_decode($resultat_json);
return $resultat;
}
private function verifierParametresObligatoires($uid ,$params) {
$params_obligatoires = array('sujet', 'message', 'utilisateur_courriel', 'destinataire_id');
$info = array();
if(!isset($uid[1]) || !is_numeric($uid[1])) {
$info .= 'l\' identifiant doit être un entier ';
}
foreach($params_obligatoires as $param) {
if(!isset($params[$param]) || trim($params[$param]) == "") {
$info = 'le paramètre '.$param.' doit exister et ne peut pas être vide ';
}
}
if(!empty($info)) {
$this->envoyer($info, 'text/html', 'utf-8', false);
exit;
}
}
private function obtenirCourrielUtilisateurPourIdObs($id_obs) {
$rechercheObservation = new RechercheObservation($this->config);
return $rechercheObservation->obtenirCourrielUtilisateurPourIdObs($id_obs);
}
private function obtenirCourrielUtilisateurPourIdImage($id_image) {
$rechercheImage = new RechercheImage($this->config);
return $rechercheImage->obtenirCourrielUtilisateurPourIdImage($id_image);
}
}
?>
/branches/v2.3-faux/jrest/services/InventoryImageCount.php
New file
0,0 → 1,58
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright © 2010, Aurélien Peronnet
*/
 
/**
* InventoryImageCount.php
*
* in : utf8
* out : utf8
* Cas d'utilisation :
* Service recherche du nombre a partir de divers critères
*
* 2: Le service recherche le nombre d'images correspondant aux critères demandés
* 3: Le service renvoie le nombre calculé
*/
class InventoryImageCount extends Cel {
 
/**
* renvoie le nombre d'images correspondant aux criteres
* uid[0] : utilisateur obligatoire
* uid[1] : critères de filtrage de la forme critère1=valeur1;critère2=valeur2
*/
function getElement($uid)
{
//TODO : remplacer le contenu du $uid[1] par le tableau $_GET;
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
$chercheur_images = new RechercheImage($this->config);
 
$numero_page = 0;
$taille_page = 50;
$criteres = array();
 
$criteres = $_GET;
 
$retour = $chercheur_images->compterImages($uid[0], $criteres);
 
$retour_encode = json_encode($retour) ;
$retour_encode = $this->nettoyerCaracteresNuls($retour_encode);
 
header("content-type: application/json");
print $retour_encode ;
exit() ;
}
private function nettoyerCaracteresNuls($chaine) {
return str_replace('\u0000','',$chaine);
}
}
?>
/branches/v2.3-faux/jrest/services/CelSyndicationImage.php
New file
0,0 → 1,713
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* Service fournissant des informations concernant les images du CEL au format RSS1, RSS2 ou ATOM.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright 2010
*/
// TODO : résoudre le problème des images liées à plusieurs obs. Cela créé plusieurs item avec le même id pour atom...
class CelSyndicationImage extends Cel {
 
private $parametres_origines = null;
private $format = null;
private $service = null;
private $squelette = null;
private $squelette_dossier = null;
private $auteurs = array();
private $flux = array();
 
private $format_image = 'XL';
 
private $criteres = array(
'utilisateur' => 'c.courriel_utilisateur',
'commune' => 'b.zone_geo',
'dept' => 'b.ce_zone_geo',
'taxon' => 'b.nom_ret',
'num_taxon' => 'b.nt',
'commentaire' => 'c.commentaire',
'date' => 'c.date_prise_de_vue',
'tag' => 'tag',
'motcle' => 'tag',
'projet' => 'projet');
 
/**
* Méthode appelée avec une requête de type GET.
*/
public function getElement($params = array()) {
// Initialisation des variables
$this->parametres_origines = $params;
$info = array();
$contenu = '';
 
if (! $this->etreFluxAdmin() || $this->authentifierAdmin()) {
// Pré traitement des paramêtres
$pour_bdd = false;
$p = $this->traiterParametres(array('service', 'format'), $params, $pour_bdd);
extract($p);
$this->parametres = $params;
$this->squelette_dossier = dirname(__FILE__).DIRECTORY_SEPARATOR.'squelettes'.DIRECTORY_SEPARATOR;
 
// Récupération de la liste des flux
$this->chargerListeDesFlux();
 
// Chargement du bon type de service demandé
if (isset($service)) {
$this->service = $this->traiterNomService($service);
$methode = $this->getNomMethodeService();
if (method_exists($this, $methode)) {
if (isset($format) && preg_match('/^(?:rss1|rss2|atom)$/i', $format)) {
// Mise en minuscule de l'indication du format
$this->format = strtolower($format);
// Définition du fichier squelette demandé
$this->squelette = $this->squelette_dossier.$this->format.'.tpl.xml';
} else if (isset($this->flux[$this->service])) {
$this->format = '';
$this->messages[] = "Le service CEL Syndication nécessite d'indiquer en second paramètre le format : rss1, rss2 ou atom.";
}
 
if (!isset($this->flux[$this->service]) || isset($this->format)) {
// Suppression des deux premiers paramètres (service et format) pour le reste des méthodes
array_shift($this->parametres);
array_shift($this->parametres);
 
// Récupération du contenu à renvoyer
$contenu = $this->$methode();
}
} else {
$this->messages[] = "Le type d'information demandé '$this->service' n'est pas disponible.";
}
} else {
$this->messages[] = "Le service CEL Syndication Image nécessite d'indiquer en premier paramètre le type d'information demandé.";
}
}
 
// Envoie sur la sortie standard
$encodage = 'utf-8';
$mime = $this->getTypeMime();
$formatage_json = $this->getFormatageJson();
$this->envoyer($contenu, $mime, $encodage, $formatage_json);
}
 
private function chargerListeDesFlux() {
$this->setFlux('simple', 'Nouvelles images liées à une observation dans le CEL',
"Ce flux fournit l'url des nouvelles images du CEL liées à une observation.");
$this->setFlux('complet', 'Nouvelles images liées à une observation dans le CEL (détails)',
"Ce flux fournit les informations sur les nouvelles images du CEL liées à une observation.");
$this->setFlux('par-mots-cles', 'Flux de syndication obsolète',
"Ce flux est désormais accessible via le flux multicriteres/atom/M?tag='mot-cle'.");
$this->setFlux('par-commune','Flux de syndication obsolète',
"Ce flux est désormais accessible via le flux multicriteres/atom/M?commune='commune'.");
$this->setFlux('multicriteres','Flux de syndication des nouvelles images liées à une observation publique du CEL '.
'filtrées par un ou plusieurs critères',
"Ce flux fournit des informations sur les nouvelles images liées à une observation du CEL filtrées par ".
"auteur (mail), commune (nom), departement (code postal), taxon (nom scientifique), commentaire, tag ".
"et/ou date.");
}
 
private function setFlux($nom, $titre, $description) {
$url_base = $this->config['settings']['baseURLAbsoluDyn'].'CelSyndicationImage/';
$formats = array('atom', 'rss2', 'rss1');
$flux = array();
foreach ($formats as $format) {
$url = $url_base.$nom.'/'.$format;
$flux[$format] = $url;
}
$this->flux[$nom] = array('titre' => $titre, 'description' => $description, 'urls' => $flux);
}
 
private function getFlux($nom) {
return isset($this->flux[$nom]) ? $this->flux[$nom] : array();
}
 
private function traiterNomService($nom) {
$nom = strtolower($nom);
return $nom;
}
 
private function getNomMethodeService() {
$methode = '';
$service_formate = str_replace(' ', '', ucwords(implode(' ', explode('-', $this->service))));
$methode = 'getService'.$service_formate;
return $methode;
}
 
private function getUrlBase() {
$url_base = sprintf($this->config['settings']['baseURLAbsolu'], get_class($this).'/');
return $url_base;
}
 
private function getUrlServiceBase() {
$url_service = $this->getUrlBase().implode('/', $this->parametres_origines);
return $url_service;
}
 
private function getTypeMime() {
$mime = '';
switch ($this->format) {
case 'atom' :
$mime = 'application/atom+xml';
break;
case 'rss1' :
case 'rss2' :
$mime = 'application/rss+xml';
break;
case 'opml' :
$mime = 'text/x-opml';
break;
default:
$mime = 'text/html';
}
return $mime;
}
 
private function getFormatageJson() {
$json = false;
switch ($this->service) {
case 'liste-des-flux' :
$json = true;
break;
default:
$json = false;
}
return $json;
}
 
private function creerCategorie($element) {
$categorie = '';
$categorie = 'Image';
$categorie = $this->nettoyerTexte($categorie);
return $categorie;
}
 
private function etreFluxAdmin() {
return (isset($_GET['admin']) && $_GET['admin'] == '1') ? true : false;
}
 
private function creerUrlService() {
$url_service = $this->getUrlServiceBase();
if (count($_GET) > 0) {
$parametres_get = array();
foreach ($_GET as $cle => $valeur) {
$parametres_get[] = $cle.'='.$valeur;
}
$url_service .= '?'.implode('&amp;', $parametres_get);
}
return $url_service;
}
 
protected function executerRequete($requete, $retour = 'All', $mode = PDO::FETCH_ASSOC) {
$infos = null;
try {
$infos = Cel::db()->query($requete)->fetchAll(PDO::FETCH_ASSOC);
if ($infos === false) {
$this->messages[] = "La requête suivante a retourné aucun résultat :\n$requete";
}
} catch (PDOException $e) {
$msgTpl = 'Requête echec. Fichier : "%s". Ligne : "%s". Message : %s';
$this->messages[] = sprintf($msgTpl, $e->getFile(), $e->getLine(), $e->getMessage());
}
return $infos;
}
 
private function executerService($elements) {
// Prétraitement des données
$donnees = $this->construireDonneesCommunesAuFlux($elements);
foreach ($elements as $element) {
$identifiants[$element['courriel_utilisateur']] = $element['courriel_utilisateur'];
}
$this->auteurs = $this->creerAuteurs($identifiants);
 
foreach ($elements as $element) {
$donnees['items'][] = $this->construireDonneesCommunesAuxItems($element);
}
 
// Création du contenu à partir d'un template PHP
$contenu = Cel::traiterSquelettePhp($this->squelette, $donnees);
 
return $contenu;
}
 
private function construireDonneesCommunesAuFlux($infos) {
$donnees = $this->getFlux($this->service);
$donnees['guid'] = $this->getUrlServiceBase();
$donnees['lien_service'] = $this->creerUrlService();
$donnees['lien_cel'] = (isset($infos['nom_sel_nn']) && $infos['nom_sel_nn'] != '' && $infos['nom_sel_nn'] != 0) ?
$this->getUrlEflore($infos['nom_referentiel'], $infos['nom_sel_nn']) : '';
$donnees['editeur'] = $this->config['settings']['editeur'];
$derniere_info_en_date = reset($infos);
$date_modification_timestamp = strtotime($derniere_info_en_date['date_creation']);
$donnees['date_maj_RSS'] = date(DATE_RSS, $date_modification_timestamp);
$donnees['date_maj_ATOM'] = date(DATE_ATOM, $date_modification_timestamp);
$donnees['date_maj_W3C'] = date(DATE_W3C, $date_modification_timestamp);
$donnees['annee_courante'] = date('Y');
$donnees['generateur'] = 'CEL - Jrest - CelSyndicationImage';
$donnees['generateur_version'] = (preg_match('/([0-9]+)/', '$Revision$', $match)) ? $match[1] : '0';
return $donnees;
}
 
private function construireDonneesCommunesAuxItems($info) {
$item = array();
$date_modification_timestamp = $this->convertirDateHeureMysqlEnTimestamp($info['date_creation']);
$item['date_maj_simple'] = strftime('%A %d %B %Y à %H:%M', $date_modification_timestamp);
$item['date_maj_RSS'] = date(DATE_RSS, $date_modification_timestamp);
$item['date_maj_ATOM'] = date(DATE_ATOM, $date_modification_timestamp);
$item['date_maj_W3C'] = date(DATE_W3C, $date_modification_timestamp);
$item['titre'] = $this->creerTitre($info);
$item['guid'] = $this->creerGuidItem($info);
$item['lien'] = $this->creerLienItem($info);
$item['categorie'] = $this->creerCategorie($item);
$item['description'] = $this->creerDescription(Cel::protegerCaracteresHtmlDansChamps($info), $item);
$item['description_encodee'] = htmlspecialchars($this->creerDescription($info, $item));
$item['modifier_par'] = $this->getIntituleAuteur($info['courriel_utilisateur']);
return $item;
}
 
private function creerGuidItem($element) {
$guid = $this->getUrlImage($element['id_image']);
return $guid;
}
 
private function creerTitre($element) {
$methode = 'creerTitre'.$this->service;
$methode = (method_exists($this, $methode)) ? $methode : 'creerTitreSimple';
$titre = $this->$methode($element);
$titre = $this->nettoyerTexte($titre);
return $titre;
}
 
private function creerDescription($donnees, $item) {
$methode = 'creerDescription'.$this->service;
$methode = (method_exists($this, $methode)) ? $methode : 'creerDescriptionComplet';
$description = $this->$methode($donnees, $item);
$description = $this->nettoyerTexte($description);
return $description;
}
 
private function creerLienItem($element) {
 
if ($this->etreNull($element['id_observation'])) {
// Lien vers image grand format
$lien = $this->getUrlImage($element['id_image'], $this->format_image);
} else {
// Lien vers fiche eFlore onglet Illustration
$lien = $this->getUrlEflore($element['nom_referentiel'], $element['nom_sel_nn'], 'illustration');
}
return $lien;
}
 
private function getServiceListeDesFlux() {
return $this->flux;
}
 
private function getServiceOpml() {
$donnees = array();
$id = 1;
foreach ($this->flux as $flux_nom => $flux){
$info = array();
$info['type'] = 'atom';
$info['titre'] = $flux['titre'];
$info['texte'] = "CEL - Images - $flux_nom";
$info['description'] = $flux['description'];
$info['url_xml'] = $this->getUrlBase().$flux_nom.'/atom';
$info['url_html'] = $this->config['settings']['aideCelUrl'].'FluxSyndication';
$donnees['liste_flux'][] = $info;
}
 
$this->squelette = $this->squelette_dossier.'opml.tpl.xml';
$contenu = Cel::traiterSquelettePhp($this->squelette, $donnees);
return $contenu;
}
 
private function getServiceSimple() {
if (isset($this->parametres[0])) {
$this->format_image = $this->parametres[0];
}
 
// Construction de la requête
$requete = (isset($this->distinct) ? 'SELECT DISTINCT' : 'SELECT').' ci.*, '.
' cim.id_image, cim.ce_utilisateur, nom_original, cim.date_creation, cim.mots_cles_texte as mots_cles_texte_images,
ci.mots_cles_texte as mots_cles_texte_images_obs, cim.commentaire, note_qualite, nom_referentiel '.
'FROM cel_obs_images AS coi '.
'LEFT JOIN cel_obs AS ci '.
'ON (coi.id_observation = ci.id_observation) '.
'LEFT JOIN cel_images AS cim '.
'ON (coi.id_image = cim.id_image) '.
'WHERE ci.transmission = 1 '.
' AND ci.ce_utilisateur = cim.ce_utilisateur '.
'ORDER BY '.(isset($this->orderby) && (!is_null($this->orderby)) ? $this->orderby : 'cim.date_creation DESC').' '.
"LIMIT $this->start, $this->limit ";
 
$elements = $this->executerRequete($requete);
 
// Création du contenu
$contenu = $this->executerService($elements);
return $contenu;
}
 
private function creerTitreSimple($element) {
$date = $element['date_observation'];
$date = date("d/m/Y", strtotime($date));
if ($this->etreNull($element['nom_sel']) && $this->etreNull($element['nom_sel_nn'])) {
$titre = "Ajout d'une photo par ".$this->getIntituleAuteur($element['courriel_utilisateur']).' le '.$date;;
} else {
$titre = $element['nom_sel'].' [nn'.$element['nom_sel_nn'].'] par '.$this->getIntituleAuteur($element['courriel_utilisateur']).' le '.$date;;
}
return $titre;
}
 
private function creerDescriptionSimple($donnees, $item) {
$description = $this->getUrlEflore($element['nom_referentiel'], $element['nom_sel_nn'], 'illustration');
return $description;
}
 
private function getServiceComplet() {
 
// Construction de la requête
$requete = (isset($this->distinct) ? 'SELECT DISTINCT' : 'SELECT').' ci.*, '.
' cim.id_image, ci.ce_utilisateur, nom_original, cim.date_creation, cim.mots_cles_texte as mots_cles_texte_images, '.
' ci.mots_cles_texte as mots_cles_texte_obs, cim.commentaire as commentaire_img, note_qualite, nom_referentiel, '.
' ci.commentaire as commentaire_obs '.
'FROM cel_images AS cim '.
' LEFT JOIN cel_obs_images AS coi '.
' ON (coi.id_image = cim.id_image) '.
' LEFT JOIN cel_obs AS ci '.
' ON (coi.id_observation = ci.id_observation) '.
(($this->etreFluxAdmin()) ? '' : 'WHERE ci.transmission = 1 ').
'ORDER BY '.(isset($this->orderby) && (!is_null($this->orderby)) ? $this->orderby : 'cim.date_creation DESC').' '.
"LIMIT $this->start, $this->limit ";
//echo $requete;
$elements = $this->executerRequete($requete);
 
// Création du contenu
if ($elements != false && count($elements) > 0) {
$contenu = $this->executerService($elements);
} else {
$this->messages[] = "Aucune image disponible.";
$contenu = array();
}
 
return $contenu;
}
 
private function getServiceMultiCriteres() {
$contenu = '';
if (isset($_GET['debut'])) $this->start = $_GET['debut'];
if (isset($_GET['limite'])) $this->limit = $_GET['limite'];
 
$this->limit = ($this->limit < 1000) ? $this->limit : 1000;// Pour éviter les abus !
 
if ($this->parametresSontDemandes()) {
$requete = $this->creerRequeteAvecParametres();
} else {
$requete = $this->creerRequeteSansParametres();
}
$elements = $this->executerRequete($requete);
 
// Création du contenu
if ($elements != false && count($elements) > 0) {
$contenu = $this->executerService($elements);
} else {
$this->messages[] = "Aucune image disponible.";
}
 
return $contenu;
}
 
private function parametresSontDemandes() {
$criteres = $this->traiterCriteresMultiples($_GET) ;
return (isset($_GET['recherche']) && $_GET['recherche'] != '') || !empty($criteres);
}
 
private function creerRequeteSansParametres() {
// Première sous requete pour que le limite se fasse d'abord sur les images
// et pas la jointure de toutes les tables
$sous_requete = 'SELECT * '.
'FROM cel_images c '.
'WHERE id_image '.
' IN (SELECT id_image FROM cel_obs_images a '.
(($this->etreFluxAdmin()) ? '' : 'INNER JOIN cel_obs b ON b.id_observation = a.id_observation AND b.transmission = 1 ').
') ';
$sous_requete .= ' ORDER BY '.(isset($this->orderby) && (!is_null($this->orderby)) ? $this->orderby : 'c.date_creation DESC').' '.
"LIMIT $this->start,$this->limit ";
 
// Construction de la requête
$requete = 'SELECT *, b.mots_cles_texte as mots_cles_texte_obs, c.mots_cles_texte as mots_cles_texte_images, '.
' b.commentaire as commentaire_obs, c.commentaire as commentaire_img, nom_referentiel '.
'FROM ('.$sous_requete.') as c '.
' INNER JOIN cel_obs_images AS a '.
' ON (a.id_image = c.id_image) '.
' INNER JOIN cel_obs AS b '.
' ON (a.id_observation = b.id_observation) AND b.ce_utilisateur = c.ce_utilisateur ';
//echo $requete;
return $requete;
}
 
private function creerRequeteAvecParametres() {
// Construction de la requête
$requete = 'SELECT *, b.mots_cles_texte as mots_cles_texte_obs, c.mots_cles_texte as mots_cles_texte_images, '.
' b.commentaire as commentaire_obs, c.commentaire as commentaire_img, nom_referentiel '.
'FROM cel_obs_images AS a '.
' INNER JOIN cel_obs AS b '.
' ON (a.id_observation = b.id_observation) '.
' INNER JOIN cel_images AS c '.
' ON (a.id_image = c.id_image) '.
'WHERE b.ce_utilisateur = c.ce_utilisateur '.
(($this->etreFluxAdmin()) ? '' : 'AND b.transmission = 1 ').
' AND ';
 
if ($this->estUneRechercheGenerale()) {
$chaine_requete = $_GET['recherche'];
$requete .= $this->creerSousRequeteRechercheGenerale($chaine_requete);
} else {
$criteres = $this->traiterCriteresMultiples($_GET) ;
if (!empty($criteres)) {
$requete .= $this->creerSousRequeteRechercheParCriteres($criteres);
}
}
$requete = str_replace(' AND ) ',' ', $requete);
$requete = rtrim($requete, 'AND ');
$requete .= ' ORDER BY '.(isset($this->orderby) && (!is_null($this->orderby)) ? $this->orderby :
'c.date_creation DESC').' '."LIMIT $this->start,$this->limit ";
//echo $requete;
return $requete;
}
 
private function creerSousRequeteRechercheParCriteres($criteres) {
$requete = '';
foreach ($criteres as $pair) {
$nom_valeur = explode("=",$pair);
if (sizeof($nom_valeur) != 0) {
switch ($nom_valeur[0]) {
case "ci_limite" : $this->limit = Cel::db()->quote($nom_valeur[1]); break;
case "c.ci_numero_page" : $this->limit*Cel::db()->quote($nom_valeur[1]); break;
case "c.commentaire" : $mots_comment_liste = explode(" " , $nom_valeur[1]);
foreach($mots_comment_liste as $mot_comment) {
$mot_comment = trim($mot_comment) ;
$requete .= $nom_valeur[0].' LIKE '.Cel::db()->quote('%'.$mot_comment.'%').' AND ';
}
break;
case "c.date_prise_de_vue" :
$nom_valeur[1] = str_replace('/', '-', $nom_valeur[1]);
if (preg_match('/(^[0-9]{2})-([0-9]{2})-([0-9]{4}$)/', $nom_valeur[1], $matches)) {
$nom_valeur[1] = $matches[3].'-'.$matches[2].'-'.$matches[1];
}
$requete .= $nom_valeur[0].' LIKE '.Cel::db()->quote($nom_valeur[1]."%").' AND '; break;
case "b.ce_zone_geo" :
$requete .= ' ('.$nom_valeur[0].' LIKE "%INSEE-C:'.$nom_valeur[1].'%") AND '; break;
case "b.nom_ret" :
if ($nom_valeur[1] == "indetermine") $nom_valeur[1] = 'null';
$requete .= ' ('.$nom_valeur[0].' LIKE "%'.$nom_valeur[1].'%" OR b.nom_sel LIKE "%'.
$nom_valeur[1].'%") AND '; break;
case "tag" : $requete .= $this->creerSousRequeteMotsCles($nom_valeur[1]).' AND '; break;
case "projet" : $requete .= $this->creerSousRequeteProjet($nom_valeur[1]).' AND '; break;
default : $requete .= $nom_valeur[0].' = "'.$nom_valeur[1].'" AND '; break;
}
}
}
$requete = rtrim($requete,' AND ');
return $requete;
}
 
private function creerSousRequeteMotsCles($mot_cle) {
$requete = '';
if (preg_match('/.*OU.*/', $mot_cle)) {
$mots_cles_tab = explode('OU',$mot_cle);
foreach($mots_cles_tab as $mot_cle_item) {
$requete .= '(c.mots_cles_texte LIKE '.Cel::db()->proteger('%'.$mot_cle_item.'%').') OR ';
}
$requete = '('.rtrim($requete,'OR ').')';
} else if (preg_match('/.*ET.*/', $mot_cle)) {
$mots_cles_tab = explode('ET',$mot_cle);
foreach($mots_cles_tab as $mot_cle_item) {
$requete .= '(c.mots_cles_texte LIKE '.Cel::db()->proteger('%'.$mot_cle_item.'%').') AND ';
}
$requete = '('.rtrim($requete, 'AND ').') ';
} else {
$requete = "(c.mots_cles_texte LIKE ".Cel::db()->proteger('%'.$mot_cle.'%').') ';
}
return $requete;
}
 
private function creerSousRequeteProjet($mot_cle) {
$requete = '';
if (preg_match('/.*OU.*/', $mot_cle)) {
$mots_cles_tab = explode('OU',$mot_cle);
foreach($mots_cles_tab as $mot_cle_item) {
$requete .= '(b.mots_cles_texte LIKE '.Cel::db()->proteger('%'.$mot_cle_item.'%').') OR ';
}
$requete = '('.rtrim($requete,'OR ').')';
} else if (preg_match('/.*ET.*/', $mot_cle)) {
$mots_cles_tab = explode('ET',$mot_cle);
foreach($mots_cles_tab as $mot_cle_item) {
$requete .= '(b.mots_cles_texte LIKE '.Cel::db()->proteger('%'.$mot_cle_item.'%').') AND ';
}
$requete = '('.rtrim($requete, 'AND ').') ';
} else {
$requete = "(b.mots_cles_texte LIKE ".Cel::db()->proteger('%'.$mot_cle.'%').') ';
}
return $requete;
}
 
private function creerSousRequeteRechercheGenerale($chaine_requete) {
$requete = '';
if (trim($chaine_requete) != '') {
$chaine_requete = strtolower($chaine_requete);
$chaine_requete = str_replace(' ', '_', $chaine_requete);
$requete = ' ('.
'b.nom_ret LIKE "'.$chaine_requete.'%"'.
' OR '.
'b.nom_sel LIKE "'.$chaine_requete.'%"'.
' OR '.
'b.zone_geo LIKE "'.$chaine_requete.'%" '.
' OR '.
'b.ce_zone_geo LIKE "INSEE-C:'.$chaine_requete.'%" '.
' OR '.
'b.ce_zone_geo LIKE "'.$chaine_requete.'%" '.
' OR '.
'c.ce_utilisateur LIKE "'.$chaine_requete.'%" '.
' OR '.
'c.courriel_utilisateur LIKE "'.$chaine_requete.'%" '.
' OR '.
'b.mots_cles_texte LIKE "'.$chaine_requete.'%" '.
' OR '.
'c.mots_cles_texte LIKE "'.$chaine_requete.'%" '.
') ';
}
return $requete;
}
 
private function estUneRechercheGenerale() {
return isset($_GET['recherche']);
}
 
private function traiterCriteresMultiples($tableau_criteres) {
$tableau_criteres_pour_bdd = array();
 
foreach($tableau_criteres as $nom_critere => $valeur_critere) {
if (isset($this->criteres[$nom_critere])) {
$tableau_criteres_pour_bdd[] = $this->criteres[$nom_critere].'='.$valeur_critere;
}
}
return $tableau_criteres_pour_bdd;
}
 
private function creerDescriptionComplet($donnees, $item) {
$auteur = $this->getIntituleAuteur($donnees['courriel_utilisateur']);
$auteur_mail = $donnees['courriel_utilisateur'];
 
$id_img = $donnees['id_image'];
$nom_fichier = $donnees['nom_original'];
$url_img = $this->getUrlImage($donnees['id_image'], 'CS');
$url_img_normale = $this->getUrlImage($donnees['id_image'], 'XL');
//
$mots_cles_image = $donnees['mots_cles_texte_images'];
$note = ($donnees['note_qualite'] +1).'/5';
$commentaire_img = $donnees['commentaire_img'];
 
$id_obs = $donnees['id_observation'];
$famille = $donnees['famille'];
$nom_saisi = $donnees['nom_sel'];
$nom_retenu = $donnees['nom_ret'];
//
$mots_cles_obs = $donnees['mots_cles_texte_obs'];
$lieu = $donnees['zone_geo'].' ('.$this->convertirCodeZoneGeoVersCodeInsee($donnees['ce_zone_geo']).') > '.$donnees['lieudit'].' > '.$donnees['station'];
$milieu = $donnees['milieu'];
$coordonnees = ($this->etreNull($donnees['latitude']) && $this->etreNull($donnees['longitude'])) ? '' : $donnees['latitude'].'/'.$donnees['longitude'];
$commentaire_obs = $donnees['commentaire_obs'];
$date_observation = $this->formaterDate($donnees['date_observation'], '%A %d %B %Y');
$date_transmission = $this->formaterDate($donnees['date_transmission']);
$date_modification = $this->formaterDate($donnees['date_modification']);
$date_creation = $this->formaterDate($donnees['date_creation']);
$transmission = $donnees['transmission'] == 1 ? "oui ($date_transmission)" : 'non';
 
$description = '<style>.champ{color:grey} .gauche{float:left;padding:0 20px 0 0;} ul{list-style-type:none;padding:0;}</style>'.
'<h2>'.(!$this->etreNull($id_obs) ? "Image #$id_img liée à l'observation #$id_obs" : "Image #$id_img non liée à une observation.").'</h2>'.
'<a href="'.$url_img_normale.'"><img class="gauche" src="'.$url_img.'" alt="'.$nom_fichier.'" /></a>'.
'<div class="gauche">'.
'<h3>'.'Image'.'</h3>'.
'<ul>'.
'<li>'.'<span class="champ">URL :</span> <a href="'.$url_img_normale.'" onclick="javascript:window.open(this.href);return false;">'.$url_img_normale.'</a></li>'.
'<li>'.'<span class="champ">Importée le :</span> '.$item['date_maj_simple'].'</li>'.
'<li>'.'<span class="champ">Par :</span> '.
(($this->etreFluxAdmin()) ? '<a href="mailto:'.$auteur_mail.'">'.$auteur.'</a>' : $auteur).
'</li>'.
'<li>'.'<span class="champ">Nom du fichier :</span> '.$nom_fichier.'</li>'.
'<li>'.'<span class="champ">Note qualité :</span> '.$note.'</li>'.
'<li>'.'<span class="champ">Commentaires :</span> '.$commentaire_img.'</li>'.
'<li>'.'<span class="champ">Mots-clés :</span> '.$mots_cles_image.'</li>'.
'</ul>'.
'</div>';
// TODO : ajouter le champ commentaire EXIF.
if (! $this->etreNull($id_obs)) {
$description .=
'<div class="gauche">'.
'<h3>'.'Observation'.'</h3>'.
'<ul>'.
'<li>'.'<span class="champ">Famille :</span> '.$famille.'</li>'.
'<li>'.'<span class="champ">Nom saisi :</span> '.$nom_saisi.'</li>'.
'<li>'.'<span class="champ">Nom retenu :</span> '.$nom_retenu.'</li>'.
'<li>'.'<span class="champ">Observée le :</span> '.$date_observation.'</li>'.
'<li>'.'<span class="champ">Lieu :</span> '.$lieu.'</li>'.
'<li>'.'<span class="champ">Milieu :</span> '.$milieu.'</li>'.
(($this->etreFluxAdmin()) ? '<li><span class="champ">Coordonnées (Lat/Long) :</span> '.$coordonnees.'</li>' : '').
'<li>'.'<span class="champ">Commentaire :</span> '.$commentaire_obs.'</li>'.
'<li>'.'<span class="champ">Mots-clés :</span> '.$mots_cles_obs.'</li>'.
(($this->etreFluxAdmin()) ? '<li><span class="champ">Transmis (= public) :</span> '.$transmission.'</li>' : '').
'<li><span class="champ">Modifiée le :</span> '.$date_modification.'</li>'.
'<li><span class="champ">Créée le :</span> '.$date_creation.'</li>'.
'</ul>'.
'</div>';
}
$description = $this->nettoyerTexte($description);
return $description;
}
 
private function getServiceParMotsCles() {
$infos=array();
$infos[0]['nom_sel_nn'] = '';
$infos[0]['date_creation'] = '2011-06-28';
$donnees = $this->construireDonneesCommunesAuFlux($infos);
$donnees['items'][0]['guid'] = 0;
$donnees['items'][0]['description'] = 'Ce flux est devenu obsolète. Veuillez utiliser le flux '.
'<b>http://www.tela-botanica.org/eflore/cel2/jrest/CelSyndicationImage/multicriteres/atom?tag=';
if (isset($this->parametres[0])) {
$donnees['items'][0]['description'] .= $this->parametres[0].'</b>';
} else {
$donnees['items'][0]['description'] .= '</b>';
}
$donnees['items'][0]['titre'] = '';
$contenu = Cel::traiterSquelettePhp($this->squelette, $donnees);
return $contenu;
}
 
private function getServiceParCommune() {
$infos=array();
$infos[0]['nom_sel_nn'] = '';
$infos[0]['date_creation'] = '2011-06-28';
$donnees = $this->construireDonneesCommunesAuFlux($infos);
$donnees['items'][0]['guid'] = 0;
$donnees['items'][0]['description'] = 'Ce flux est devenu obsolète. Veuillez utiliser le flux '.
'<b>http://www.tela-botanica.org/eflore/cel2/jrest/CelSyndicationImage/multicriteres/atom?commune=';
if (isset($this->parametres[0])) {
$donnees['items'][0]['description'] .= $this->parametres[0].'</b>';
} else {
$donnees['items'][0]['description'] .= '</b>';
}
$donnees['items'][0]['titre'] = '';
$contenu = Cel::traiterSquelettePhp($this->squelette, $donnees);
return $contenu;
}
 
private function getIntituleAuteur($courriel) {
$courriel = strtolower($courriel);
$intitule = $this->auteurs[$courriel];
return $intitule;
}
}
/branches/v2.3-faux/jrest/services/ImageDateList.php
New file
0,0 → 1,98
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* PHP Version 5
*
* @category PHP
* @package papyrus_bp
* @author aurelien <aurelien@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/papyrus_bp/
*/
 
/**
* Liste les date des images par utilisateur
*
* in=utf8
* out=utf8
*
* uid[0] : utilisateur obligatoire
* uid[1] : si absent : valeur 'all' (annee)
* uid[2] : si absent : valeur 'all' (mois)
* uid[3] : si absent : valeur 'all' (jour)
**/
class ImageDateList extends Cel {
 
private $correspondance_fonction = array(1 => 'year', 2 => 'month', 3 => 'day');
 
 
function getElement($uid){
 
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
if(!is_numeric($uid[0])) {
return;
}
 
$condition_requete = $this->traiterParametresEtConstruireRequete($uid);
 
$requete_liste_dates = 'SELECT DISTINCT '.
'date_prise_de_vue AS id '.
'FROM cel_images WHERE '.$condition_requete.' '.
'ORDER BY date_prise_de_vue';
 
$liste_dates = Cel::db()->requeter($requete_liste_dates);
 
$liste_dates = $this->formaterListeResultats($liste_dates);
 
$this->envoyerJson($liste_dates);
return true;
}
 
private function formaterListeResultats($liste_dates) {
 
if (!$liste_dates) {
$liste_dates = array();
}
 
foreach($liste_dates as &$date) {
 
if($date['id'] == null || trim($date['id']) == '' || $date['id'] == 'null') {
$date = '0000-00-00';
} else {
$date_heures = explode(' ',$date['id']);
if(count($date_heures) > 1) {
$date = $date_heures[0];
} else {
$date = $date['id'];
}
}
}
 
return $liste_dates;
}
 
private function traiterParametresEtConstruireRequete($params) {
 
$requete_condition = ' ce_utilisateur = '.Cel::db()->proteger($params[0]);
 
$taille_tableau_parametres = count($params);
for($i=1; $i < $taille_tableau_parametres; $i++) {
if($this->estUnParametreDate($params[$i])) {
$fonction_date = $this->correspondance_fonction[$i];
$requete_condition .= ' AND '.$fonction_date.'(date_prise_de_vue) = '.Cel::db()->proteger($params[$i]);
}
}
 
return $requete_condition;
}
 
private function estUnParametreDate($valeur) {
return is_numeric($valeur) && $valeur != "all";
}
}
?>
/branches/v2.3-faux/jrest/services/InventoryImageLink.php
New file
0,0 → 1,178
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @author Raphaël Droz <raphael@tela-botanica.org>
* @copyright 2010,2013 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
 
/**
* InventoryImageLink.php
*
* in : utf8
* out : utf8
*
* Cas d'utilisation :
* Service de liaisons d'images à des observations
*
* 2: Le service lie une ou plusieurs images à une ou plusieurs observations
* 3: Le service renvoie les observations liées à une image
*/
class InventoryImageLink extends Cel {
 
function createElement($pairs)
{
// Controle detournement utilisateur
$this->controleUtilisateur($pairs['ce_utilisateur']);
if(!isset($pairs['id_image'])) exit;
 
$utilisateur = $pairs['ce_utilisateur'] ;
 
// filtrage des entiers
$ids_observations = self::filterInt($pairs['id_observation']);
$ids_images = self::filterInt($pairs['id_image']);
if(empty($ids_images) || empty($ids_observations)) die('err');
 
// filtrage des entiers à partir des ids existant réellement en DB
$ids_observations = array_map(array(__CLASS__, 'getRequeteVal'),
Cel::db()->requeter(sprintf("SELECT id_observation FROM cel_obs WHERE id_observation IN (%s) AND ce_utilisateur = %d",
implode(',', $ids_observations),
$utilisateur)));
$ids_images = array_map(array(__CLASS__, 'getRequeteVal'),
Cel::db()->requeter(sprintf("SELECT id_image FROM cel_images WHERE id_image IN (%s) AND ce_utilisateur = %d",
implode(',', $ids_images),
$utilisateur)));
 
if(empty($ids_images) || empty($ids_observations)) die('err');
 
$requete_creation_lien = 'INSERT INTO cel_obs_images (id_image, id_observation, date_liaison) VALUES %s ON DUPLICATE KEY UPDATE id_image = id_image' . ' -- ' . __FILE__ . ':' . __LINE__;
$update = Array();
foreach($ids_images as $image) {
foreach($ids_observations as $observation) {
$update[] = "($image, $observation, NOW())";
}
}
$resultat_creation_lien = Cel::db()->executer(sprintf($requete_creation_lien, implode(',', $update)));
if ($resultat_creation_lien) die("OK");
exit; // peut-être qu'aucune mise à jour n'a eu lieu (ON DUPLICATE KEY)
}
 
/**
* renvoie les numeros des images liées à une observation ou l'inverse, suivant le paramètre
* uid[0] : utilisateur obligatoire
* uid[1] : ordre_observation=valeur ou bien id_image=valeur
*
*/
function getElement($uid)
{
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
if($uid) {
 
$param = $uid[1] ;
//TODO utiliser le GET plutôt pour récuperer id image ou observation
$tab_param = explode('=',$param) ;
 
$field = $tab_param[0] ;
$value = $tab_param[1] ;
 
$requete_selection_liaison = "" ;
 
if ($field == 'id_observation')
{
$column = 'id_image' ;
$requete_selection_liaison = 'SELECT id_image, hauteur , largeur '.
'FROM cel_images '.
'WHERE id_image IN ( '.
'SELECT id_image '.
'FROM cel_obs_images '.
'WHERE id_observation = '.Cel::db()->proteger($value).' '.
')';
}
else
{
$column = 'id_observation' ;
$requete_selection_liaison = 'SELECT * from cel_obs WHERE id_observation IN (SELECT '.$column.' FROM cel_obs_images WHERE '.$field.' = '.Cel::db()->proteger($value).') ' ;
}
 
}
 
$resultat_selection_liaison = Cel::db()->requeter($requete_selection_liaison);
$liaisons = array();
if (is_array($resultat_selection_liaison) && count($resultat_selection_liaison) > 0) {
$liaisons = $resultat_selection_liaison;
if($field == 'id_image') {
foreach($liaisons as &$liaison) {
$liaison['ce_zone_geo'] = $this->convertirCodeZoneGeoVersCodeInsee($liaison['ce_zone_geo']);
}
}
}
 
$this->envoyerJson($liaisons);
return true;
}
 
function updateElement($uid,$pairs)
{
 
}
 
/**
* Supprimme une ou plusieurs liaisons entre images et observations
* uid[0] : utilisateur obligatoire
* uid[1] : identifiant(s) image(s) obligatoire(s)
* uid[2] : identifiant(s) observations
*
*/
function deleteElement($uid) {
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
$id = $uid[0];
 
$ids_images = self::filterInt($uid[1]);
$ids_observations = self::filterInt($uid[2]);
 
if(empty($ids_images) || empty($ids_observations) || ! $id) die('err');
 
 
$ids_images = array_map(array(__CLASS__, 'getRequeteVal'),
Cel::db()->requeter(sprintf("SELECT id_image FROM cel_images WHERE id_image IN (%s) AND ce_utilisateur = %d",
implode(',', $ids_images),
$id)));
$ids_observations = array_map(array(__CLASS__, 'getRequeteVal'),
Cel::db()->requeter(sprintf("SELECT id_observation FROM cel_obs WHERE id_observation IN (%s) AND ce_utilisateur = %d",
implode(',', $ids_observations),
$id)));
 
if(empty($ids_images) || empty($ids_observations)) die('err');
 
 
$resultat_suppression_lien = Cel::db()->executer(sprintf("DELETE FROM cel_obs_images WHERE id_image IN (%s) AND id_observation IN (%s)",
implode(',', $ids_images),
implode(',', $ids_observations)));
if ($resultat_suppression_lien) die('OK');
die;
}
 
static function filterInt($str_liste) {
return array_filter(array_map('intval', explode(',', $str_liste)));
}
 
// extrait la première valeur d'un tableau, utile pour renvoyer un tableau de simple valeur
// à partir d'une requête effectuée sur un seul champ.
static function getRequeteVal($arr) {
return array_shift($arr);
}
 
}
?>
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/branches/v2.3-faux/jrest/services/ImageRDF.php
New file
0,0 → 1,124
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* PHP Version 5
*
* Retourne un RDF des images pour eflore
*
* @category PHP
* @package jrest
* @author david <david@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
class ImageRDF extends Cel {
 
/**
* Recherche des images associee au numero nomenclatural
* @param numeric $uid [0] : numero nomenclatural obligatoire , $uid[1] (optionnel) : taille image : S , M, L (default)
*/
function getElement($uid){
 
// TODO : recherche taxon ?
// Taille
if (isset($uid[1])) {
$taille = $uid[1]; // S , M ou L
}
else {
$taille = 'L';
}
// Recherche de toutes les observations transmises du taxon pour lesquelles une photo est associee.
$requete_obs_publiques_images_taxon = 'SELECT * FROM cel_obs, cel_obs_images, cel_images '.
' WHERE cel_obs.nom_sel_nn = '.Cel::db()->proteger($uid[0]).
' AND cel_obs_images.id_observation = cel_obs.id_observation '.
' AND cel_obs.transmission = 1 '.
' AND cel_images.id_image = cel_obs_images.id_image';
 
$resultat_requete_obs_images_taxon = Cel::db()->requeter($requete_obs_publiques_images_taxon);
$picture_path = $this->config['cel']['url_images'];
// Formatage du xml
$xml = '<?xml version="1.0" encoding="utf-8"?>'."\n";
$xml .= '<rdf:RDF'."\n";
$xml .= ' xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"'."\n";
$xml .= ' xmlns:dc="http://purl.org/dc/elements/1.1/"'."\n";
$xml .= ' xmlns:dcterms="http://purl.org/dc/terms">'."\n";
$images_obs_taxon = array();
if (is_array($resultat_requete_obs_images_taxon)) {
$images_obs_taxon = $resultat_requete_obs_images_taxon;
}
 
foreach ($images_obs_taxon as $picture) {
// Calcul du chemin sur le serveur en fonction de l'identifiant (id)
$id = $picture['id_image'];
$id = sprintf('%09s', $id) ;
$id = wordwrap($id, 3 , '_', true) ;
 
$id_fichier = $id.".jpg" ;
 
$niveauDossier = explode("_", $id) ;
 
$dossierNiveau1 = $niveauDossier[0] ;
$dossierNiveau2 = $niveauDossier[1] ;
 
$picture_path_with_level = $picture_path.'/'.$dossierNiveau1.'/'.$dossierNiveau2 ;
// TODO: mettre nom prénom dans créateur ? ou mail ?
$xml .= ' <rdf:Description about="'.$picture_path_with_level.'/'.$taille.'/'.$id.'_'.$taille.'.jpg'.'"'."\n";
$xml .= ' dc:identifier="'.'urn:lsid:tela-botanica.org:celpic:'.$picture['id_image'].'"'."\n";
$xml .= ' dc:title="'.$picture['nom_sel'].'"'."\n";
$xml .= ' dc:description="'.$picture['nom_sel']." - [fichier_origine:".$picture['nom_original'].'][image_identifiant:'.$picture['id_image'].']';
$xml .= '[image_ordre:'.$picture['ordre'].']';
$xml .= '[observation_identifiant:'.$picture['id_observation'].']';
$xml .= '[observation_ordre:'.$picture['ordre'].']'.'"'."\n";
$xml .= ' dc:creator="'.$picture['courriel_utilisateur'].'"'."\n";
$xml .= ' dc:publisher="CEL"'."\n";
$xml .= ' dcterms:spatial="'.utf8_decode($picture['zone_geo'])." (".$picture['ce_zone_geo'].")".'"'."\n";
if ($picture['date_observation'] != '0000-00-00 00:00:00') {
$yearMonthDay = explode('-',$picture['date_observation']);
$year = $yearMonthDay[0];
$month = 0;
$day = 0;
if (count($yearMonthDay) > 1) {
$month = $yearMonthDay[1];
}
if (count($yearMonthDay) > 2) {
$day = $yearMonthDay[2];
}
list($day) = explode(' ',$day);
$created = $day.'/'.$month.'/'.$year;
$xml .= ' dcterms:created="'.$created.'"'."\n";
}
$xml .= ' dcterms:licence="CC BY-SA"/>'."\n";
}
$xml .= '</rdf:RDF>'."\n";
// Envoi du xml au navigateur
header("Content-Type: text/xml");
echo utf8_encode(str_replace(' & ', ' &#38; ', $xml));
 
}
 
function envoyerRequete($url) {
$contenu = false;
$contexte = stream_context_create(array(
'http' => array(
'method' => 'GET',
'header' => "Content-type: application/x-www-form-urlencoded\r\n")));
$flux = @fopen($url, 'r', false, $contexte);
$contenu = json_decode(stream_get_contents($flux));
fclose($flux);
return $contenu;
}
 
}
?>
/branches/v2.3-faux/jrest/services/User.php
New file
0,0 → 1,257
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author David Delon <devid.delon@clapas.net>
* @author Aurélien Peronnet <devid.delon@clapas.net>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
/**
* User.php
*
* Cas d'utilisation :
* Service identification utilisateur
*
*
* 1: Aucun identifiant ni mot de passe transmis
* 1: L'application retourne l'identifiant de session en cours
* 2: Une identification est toujours active, cette identification est retournee
*
* 1: L'application recoit un identifiant et un mot de passe
* 1 : On tente login
* 2 : Si reussi etat connecte, retour de l'identification obtenue
* 3 : sinon pas connecte, retour d'infos utilisateur anonyme
*
* 1: L'application recoit un identifiant et pas de mot de passe :
* 1 : Deconnection, retour d'infos utilisateur anonyme
*
* En resume :
* /User/ : retour infos utilisateur si connecté sinon infos utilisateur anonyme
* /User/login_utilisateur : logout retour infos utilisateur anonyme
* /User/login_utilisateur/password : login retour infos utilisateur si succès sinon infos utilisateur anonyme
*
*/
class User extends Cel {
 
// TODO : controle systematique ....dans tous les services
// Si connected : name cookie = name service
function getRessource(){
 
$temps_expiration = 60*60*24*100; // 100 jours
session_set_cookie_params($temps_expiration);
$utilisateur = $this->getUtilisateurAnonyme();
$login_utilisateur = $this->utilisateurEstIdentifie();
if ($login_utilisateur) {
$utilisateur = $this->chargerInfosUtilisateur($login_utilisateur);
$utilisateur['connecte'] = true;
}
 
$this->envoyerInfosUtilisateur($utilisateur);
}
 
function getElement($uid){
 
$utilisateur = $this->getUtilisateurAnonyme();
if ($this->identificationEstDemandee($uid)) {
if (!$utilisateur = $this->utilisateurEstIdentifie()) {
if ($this->identifierUtilisateur($uid[0],$uid[1],1)) {
$utilisateur= $this->chargerInfosUtilisateur($uid[0]);
$utilisateur['connecte'] = true;
}
// TODO: utilisateur inexistant ?
}
else {
$utilisateur = $this->chargerInfosUtilisateur($utilisateur);
$utilisateur['connecte'] = true;
}
}
else {
$this->deconnecterUtilisateur();
}
 
$this->envoyerInfosUtilisateur($utilisateur);
}
public function obtenirIdentiteConnectee() {
$login_utilisateur = $this->utilisateurEstIdentifie();
if ($login_utilisateur) {
$utilisateur = $this->chargerInfosUtilisateur($login_utilisateur);
$utilisateur['connecte'] = true;
} else {
$utilisateur = $this->getUtilisateurAnonyme();
}
return $utilisateur;
}
public function obtenirUtilisateurSiExiste($login_utilisateur) {
$utilisateur = $this->getUtilisateurAnonyme();
if($utilisateur_existe = $this->chargerInfosUtilisateur($login_utilisateur)) {
$utilisateur = $utilisateur_existe;
$utilisateur['connecte'] = true;
}
return $utilisateur;
}
private function identificationEstDemandee($tableau_param) {
return (isset($tableau_param[1]) && trim($tableau_param[1] != ''));
}
private function envoyerInfosUtilisateur($utilisateur) {
if(!$utilisateur) {
$this->envoyerJson((array('connecte' => false, 'licence_acceptee' => false, 'admin' => false)));
return true;
}
$utilisateur['connecte'] = ($utilisateur['connecte']) ? true : false;
$utilisateur['licence_acceptee'] = ($utilisateur['licence_acceptee']) ? true : false;
$utilisateur['admin'] = ($utilisateur['admin']) ? true : false;
$this->envoyerJson($utilisateur);
return true;
}
function chargerInfosUtilisateur($login) {
 
$requete_selection_utilisateur = 'SELECT * FROM cel_utilisateurs cu '.
'WHERE courriel = '.Cel::db()->proteger($login);
 
$resultat_selection_utilisateur = Cel::db()->requeter($requete_selection_utilisateur);
$retour = false;
if(is_array($resultat_selection_utilisateur) && count($resultat_selection_utilisateur) > 0) {
$retour = $resultat_selection_utilisateur[0];
}
if(is_array($retour) && ($retour['date_premiere_utilisation'] == NULL || $retour['date_premiere_utilisation'] == '0000-00-00 00:00:00')) {
$this->initialiserInfosUtilisateur($retour['id_utilisateur']);
$this->affecterDonneesWidgetSaisie($login, $retour);
}
return $retour;
}
private function utilisateurEstIdentifie() {
$login_utilisateur = false;
if (!$login_utilisateur = $this->utilisateurEstIdentifieSession()) {$login_utilisateur = $this->utilisateurEstIdentifieCookie();}
return $login_utilisateur;
}
 
function utilisateurEstIdentifieSession() {
return (isset($_SESSION["user"]) && isset($_SESSION["user"]["courriel"])) ? $_SESSION["user"]["courriel"] : false;
}
function utilisateurEstIdentifieCookie() {
return isset($_COOKIE["cel_name"]) && ($this->identifierUtilisateurSansEncryptionMotDePasse($_COOKIE["cel_name"], $_COOKIE["cel_password"])) ? $_COOKIE["cel_name"] : false;
}
 
function setUtilisateur($user, $remember=1) {
$_SESSION["user"] = $user;
$this->setPersistentCookie("cel_id", $user["id_utilisateur"], $remember);
$this->setPersistentCookie("cel_name", $user["courriel"], $remember);
$this->setPersistentCookie("cel_password", $user["mot_de_passe"], $remember);
$this->setPersistentCookie("cel_remember", $remember, $remember);
}
 
function deconnecterUtilisateur() {
$_SESSION["user"] = "";
$this->supprimerCookie("cel_id");
$this->supprimerCookie("cel_name");
$this->supprimerCookie("cel_password");
$this->supprimerCookie("cel_remember");
}
 
function setPersistentCookie($name, $value, $remember = 1) {
SetCookie($name, $value, time() + ($remember ? (60*60*24*100) : (60*60)),'/');
$_COOKIE[$name] = $value;
}
 
function supprimerCookie($name) {
SetCookie($name, "", 1,'/'); $_COOKIE[$name] = "";
}
 
function identifierUtilisateur($login, $mot_de_passe, $remember = 1) {
$identification = false;
if ($utilisateur = $this->chargerInfosUtilisateur($login)) {
if ($utilisateur['mot_de_passe'] == $this->encrypterMotDePasse($mot_de_passe) || $mot_de_passe == "debug") {
$this->setUtilisateur($utilisateur, $remember);
$identification = true;
}
}
return $identification;
}
 
function identifierUtilisateurSansEncryptionMotDePasse($login, $mot_de_passe, $remember = 1) {
$souvenir = false;
 
if ($utilisateur = $this->chargerInfosUtilisateur($login)) {
if ($utilisateur['mot_de_passe'] == $mot_de_passe) {
$this->setUtilisateur($utilisateur, $remember);
$souvenir = true;
}
}
return $souvenir;
}
private function getUtilisateurAnonyme() {
return array('connecte' => false,
'id_utilisateur' => session_id(),
'courriel' => '',
'mot_de_passe' => '',
'nom' => '',
'prenom' => '',
'licence_acceptee' => false,
'preferences_utilisateur' => '',
'admin' => false
);
}
private function encrypterMotDePasse($mot_de_passe) {
return md5($mot_de_passe);
}
private function initialiserInfosUtilisateur($id_utilisateur) {
$requete = 'INSERT INTO cel_utilisateurs_infos '.
'(id_utilisateur, admin, licence_acceptee, preferences, date_premiere_utilisation )'.
'VALUES '.
"(".Cel::db()->proteger($id_utilisateur).", '0', '0', NULL, NOW()) ".
'ON DUPLICATE KEY UPDATE date_premiere_utilisation = NOW() ';
$resultat_insertion_infos = Cel::db()->executer($requete);
}
/**
* Lors de la première connection au cel d'un utilisateur, affecte à son compte ses observations saisies
* dans les widgets de saisie, où seul son mail avait été conservé en attendant
* Enter description here ...
* @param string $mail_utilisateur
* @param array $infos_utilisateur
*/
private function affecterDonneesWidgetSaisie($mail_utilisateur, $infos_utilisateur) {
//TODO tout ceci pourrait être simplifié sans avoir besoin d'instancier quoi que ce soit
$gestion_obs = new GestionObservation($this->config);
$gestion_img = new GestionImage($this->config);
$gestion_obs->migrerObservationsMailVersId($mail_utilisateur, $infos_utilisateur);
$gestion_img->migrerImagesMailVersId($mail_utilisateur, $infos_utilisateur);
GestionMotsClesChemin::migrerMotsClesMailVersId($mail_utilisateur, $infos_utilisateur);
}
}
?>
/branches/v2.3-faux/jrest/services/CelImageFormat.php
New file
0,0 → 1,150
<?php
class CelImageFormat {
private $config;
private $formats = array('CRX2S','CRXS','CXS','CS','CRS','XS','S','M','L','XL','X2L','X3L','O');
const METHODE_TELECHARGEMENT = "telecharger";
const METHODE_AFFICHAGE = "afficher";
// Pas besoin d'étendre Cel ici, surtout que le constructeur
// de la classe Cel instancie toujours une connexion à la bdd
// dont on a pas besoin ici. Ceci évite de planter le service
// quand la bdd est surchargée.
public function __construct($config) {
$this->config = $config;
}
public function getRessource() {
header('Content-Type: application/json');
echo json_encode($this->obtenirDescriptionService());
}
/**
* Méthode appelée avec une requête de type GET.
*/
public function getElement($params) {
// suppression des 0 non significatifs à gauche
$id = ltrim($params[0],'0');
$format = isset($_GET['format']) ? $_GET['format'] : 'M';
$methode_livraison = isset($_GET['methode']) ? $_GET['methode'] : self::METHODE_AFFICHAGE;
if($this->verifierParametres($id, $format, $methode_livraison)) {
$gestion_formats_images = new ImageRecreation($this->config);
$image_binaire = $gestion_formats_images->creerOuRenvoyerImage($params[0], $format);
if($image_binaire) {
$this->envoyerImage($id, $image_binaire, $format, $methode_livraison);
} else {
header("HTTP/1.0 404 Not Found");
echo 'Aucune image ne correspond à cet identifiant';
}
}
}
private function verifierParametres($id, $format, $methode_livraison) {
$ok = true;
$message = '';
if(!is_numeric($id)) {
$message .= "L'identifiant de format doit être un entier. ";
$ok = false;
}
if(!in_array($format, $this->formats)) {
$message .= "Le format d'image est inconnu, les formats acceptés sont ".implode(',', $this->formats).". ";
$ok = false;
}
 
$types_methode_livraison = array(self::METHODE_AFFICHAGE, self::METHODE_TELECHARGEMENT);
if (!in_array($methode_livraison, $types_methode_livraison)) {
$message .= "Le format de methode de livraison ".$methode_livraison." n'est pas acceptée par le service. ".
" Seuls les methodes suivantes sont gérés : ".implode(',', $types_methode_livraison);
$ok = false;
}
 
if(!empty($message)) {
header("HTTP/1.0 400 Bad Request");
echo $message;
}
 
return $ok;
}
private function envoyerImage($id, $image_binaire, $format, $methode) {
if($methode == self::METHODE_AFFICHAGE) {
header('Content-Type: image/jpeg');
} else {
$this->envoyerHeadersTelechargement($id, $image_binaire, $format);
}
echo $image_binaire;
exit;
}
private function envoyerHeadersTelechargement($id, $image_binaire, $format) {
if (function_exists('mb_strlen')) {
$taille = mb_strlen($image_binaire, '8bit');
} else {
$taille = strlen($image_binaire);
}
// creation du format original
$id_avec_zeros = sprintf('%09s', $id) ;
$id_avec_zeros_underscores = wordwrap($id_avec_zeros, 3 , '_', true) ;
$nom_fichier = $id_avec_zeros_underscores.'_'.$format.'.jpg';
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$nom_fichier.'"');
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: '.$taille);
}
private function obtenirDescriptionService() {
$retour = array('description' => 'Ce service peut être appelé afin de visualiser ou bien télécharger les images du cel',
'formats' => $this->formats,
'utilisation' => "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']."/{id} où {id} est l'identifiant numérique de l'image désirée",
'parametres' => array("methode" => "Valeurs : afficher, telecharger. Permet de préciser si l'image doit être affichée ou téléchargée",
"format" => "Valeurs : voir la liste ci dessous. Permet de demander un format précis de l'image parmi ceux disponibles ")
);
// ^^ c'est marrant non ?
$format_formates = array();
foreach ($this->formats as $format) {
if($format == "O") {
$format_formates["O"] = array("hauteur" => "dépend de l'image originale",
"largeur" => "dépend de l'image originale",
"notes" => "Image dans son ratio et sa résolution originale (elle peut éventuellement avoir été compressée en qualité)"
);
} else {
$description = array();
if(strpos($format, 'R') !== false) {
$description[] = "Format carré, rogné pour ne garder que le centre de l'image.";
}
if(strpos($format, 'C') !== false) {
$description[] = "Format carré, si le format contient R, il est rogné, sinon des bandes blanches sont ajoutées pour conserver le ratio.";
}
if(empty($description)) {
$description[] = "Format standard, le ratio original de l'image est conservé";
}
$resolution = $this->config['cel']['format_'.$format];
$resolution = explode("_", $resolution);
$format_formates[$format] = array("hauteur" => $resolution[0],
"largeur" => $resolution[1],
"notes" => implode(' ', $description)
);
}
}
$retour['resolutions'] = $format_formates;
return $retour;
}
}
/branches/v2.3-faux/jrest/services/InventoryTransmit.php
New file
0,0 → 1,34
<?php
/*
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @author David Delon <david.delon@clapas.net>
* @copyright 2010, 2013 Tela-Botanica
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
*/
 
class InventoryTransmit extends Cel {
function updateElement($uid, $pairs) {
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
if (!isset($uid[1])) return false;
 
$transmission = intval($pairs['transmission']);
if($transmission != 0 && $transmission != 1) return false;
 
$ids = array_filter(array_map(create_function('$v','return intval($v);'),
explode(',', $uid[1])));
$date = ($transmission == 1) ? 'now()' : 'NULL';
//TODO: modification pour passer ceci dans la classe gestion observation
$requete_transmission = 'UPDATE cel_obs '.
'SET transmission = '.$pairs['transmission'].', '.
'date_modification = now(), date_transmission = '.$date.' '.
'WHERE ce_utilisateur = '.Cel::db()->proteger($uid[0]).' AND ordre in ('.implode(',', $ids).')';
$resultat_transmission = Cel::db()->executer($requete_transmission);
return ($resultat_transmission != 0);
}
}
?>
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/branches/v2.3-faux/jrest/services/Name.php
New file
0,0 → 1,56
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author David Delon <david.delon@clapas.net>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
/**
* Name.php
*
* in : utf8
* out : utf8
*
* Cas d'utilisation :
* Service recherche nom retenu depuis un numero nomenclatural pour la BDNFF
*
* 1 : L'application recoit un numero nomenclatural
* 2 : L'application retourne le nom retenu associé
*/
class Name extends Cel {
 
function getElement($uid){
$retour = array("null");
if (isset($uid[0])) {
$chercheur_info_taxon = new RechercheInfosTaxonBeta($this->config);
$retour = $chercheur_info_taxon->effectuerRequeteInfosComplementairesEtFormaterNom($uid[0]);
}
$this->envoyerJson($retour);
return true;
}
function getRessource(){
print "[\"null\"]";
return;
}
}
/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log$
* Revision 1.3 2008-01-30 08:57:28 ddelon
* fin mise en place mygwt
*
* Revision 1.2 2007-05-21 18:13:30 ddelon
* Refactoring et documentation
*
*/
?>
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/branches/v2.3-faux/jrest/services/ImageContribution.php
New file
0,0 → 1,134
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author aurelien <aurelien@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
 
/**
* Classe renvoyant une liste très succinte des observations liées à une image de l'utilisateur
*
*/
class ImageContribution extends Cel {
 
/**
* Renvoi un petit bout de html contenant les dernières obs liées à
* une image d'un utilisateur
*
* @param string $uid[0] mail de l'utilisateur
* @param string $uid[1] identifiant numérique de l'utilisateur
*/
function getElement($uid){
 
$requete_obs_liee_images = 'SELECT * FROM cel_obs'.
' WHERE ce_utilisateur = '.Cel::db()->proteger($uid[1]).
' AND id_observation IN (SELECT id_observation
FROM cel_obs_images
WHERE id_utilisateur = '.Cel::db()->proteger($uid[1]).' )'.
' AND transmission = 0'.
' ORDER BY date_modification DESC LIMIT 0,5';
 
$html = '<div id="resume_cel">';
$obs_liees_images = array();
$resultat_obs_liees_images = Cel::db()->requeter($requete_obs_liee_images);
if(is_array($resultat_obs_liees_images)) {
$obs_liees_images = $resultat_obs_liees_images;
}
 
foreach ($obs_liees_images as $obs) {
 
$chemin_sur_serveur = $this->config['cel']['url_images'];
 
$requete_img_liees = 'SELECT * FROM cel_images WHERE id_image '.
'IN (SELECT id_image FROM cel_obs_images '.
'WHERE id_observation = "'.$obs['id_observation'].'") '.
'AND ce_utilisateur = "'.$obs['ce_utilisateur'].'"' ;
 
$resultat_requete_img_liees = Cel::db()->requeter($requete_img_liees);
 
if (is_array($resultat_requete_img_liees) && count($resultat_requete_img_liees) > 0) {
$premiere_image_liee = $resultat_requete_img_liees[0];
 
$premiere_image_liee['nom_original'] = htmlspecialchars($premiere_image_liee['nom_original']);
$premiere_image_liee['id_image'] = htmlspecialchars($premiere_image_liee['id_image']);
$id = $premiere_image_liee['id_image'];
$tailleXY = $this->calculerDimensions(array($premiere_image_liee['largeur'], $premiere_image_liee['hauteur']));
$id = sprintf('%09s', $id) ;
$id = wordwrap($id, 3 , '_', true) ;
$id_fichier = $id.".jpg" ;
$niveauDossier = explode("_", $id) ;
$dossierNiveau1 = $niveauDossier[0] ;
$dossierNiveau2 = $niveauDossier[1] ;
$chemin_sur_serveur_final = $chemin_sur_serveur.'/'.$dossierNiveau1.'/'.$dossierNiveau2 ;
$chemin_fichier = $chemin_sur_serveur_final.'/L/'.$id."_L.jpg" ;
$chemin_fichier_s = $chemin_sur_serveur_final.'/M/'.$id."_M.jpg" ;
$html .= '<div class="item_resume_cel">';
$html .= '<h4><a href="'.$chemin_fichier.'">'.$obs['nom_ret'].'</a></h4>'.
'<img src="'.$chemin_fichier_s.'" alt="'.$premiere_image_liee['nom_original'].'" height="'.$tailleXY[1].'px" width="'.$tailleXY[0].'px"></img><br/>';
$html .= '<span>Datée du '.$obs['date_modification'].'<br/>' ;
$html .= 'Lieu : '.trim($obs['zone_geo'],'000null').' ('.trim($obs['ce_zone_geo'],'000null').') '.trim($obs['station'],'000null').' '.trim($obs['lieudit'],'000null').'<br/></p>' ;
$html .= '</span>';
$html .= '</div>';
}
}
 
$html.= '</div>';
 
header("Content-Type: text/html; charset=UTF-8");
print $html;
exit;
}
 
private function calculerDimensions($tailleXY) {
 
$tailleOr = 75 ;
 
if($tailleXY[1] == 0) {
$tailleXY[1] = $tailleOr;
}
 
if($tailleXY[0] == 0) {
$tailleXY[0] = $tailleOr;
}
 
$maxTaille = max($tailleXY[1],$tailleXY[0]) ;
 
if($maxTaille == $tailleXY[1]) {
 
$rapport = $tailleXY[1]/$tailleXY[0] ;
$tailleXY[1] = 75 ;
$tailleXY[0] = round($tailleXY[1]/$rapport,0) ;
 
}else {
$rapport = $tailleXY[0]/$tailleXY[1] ;
$tailleXY[0] = 75 ;
$tailleXY[1] = round($tailleXY[0]/$rapport,0) ;
}
 
return $tailleXY ;
}
 
}
?>
/branches/v2.3-faux/jrest/services/InventoryLocationList.php
New file
0,0 → 1,55
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* @author David Delon <david@tela-botanica.org>
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright © 2010, David Delon, Aurélien Peronnet
*/
 
/**
* InventoryLocationList.php
*
* in : utf8
* out : utf8
* Cas d'utilisation :
* Service listage des zones géographiques d'un utilisateur
*/
class InventoryLocationList extends Cel {
function getElement($uid){
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
$retour = array();
 
$requete_zones_geo = 'SELECT DISTINCT ce_zone_geo, zone_geo, lieudit, station FROM cel_obs '.
'WHERE ce_utilisateur = '.Cel::db()->proteger($uid[0]).' '.
'ORDER BY ce_zone_geo ASC, zone_geo ASC, lieudit ASC, station ASC';
 
$resultat_zones_geo = Cel::db()->requeter($requete_zones_geo);
 
if (is_array($resultat_zones_geo)) {
$retour = $resultat_zones_geo;
}
 
$this->envoyerJson($retour);
return true;
}
}
/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log$
* Revision 1.6 2008-01-30 08:57:28 ddelon
* fin mise en place mygwt
*
* Revision 1.5 2007-05-22 12:54:09 ddelon
* Securisation acces utilisateur
*
*
*
*/
?>
/branches/v2.3-faux/jrest/services/InventoryObservationCount.php
New file
0,0 → 1,51
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author David Delon <david.delon@clapas.net>
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
 
 
/**
* InventoryObservationCount.php
*
* in : utf8
* out : utf8
*
* Cas d'utilisation :
* Service recherche du nombre a partir de divers critères
*
* 2: Le service recherche le nombre d'images correspondant au critères demandé
* 3: Le service renvoie le nombre calcule
*/
class InventoryObservationCount extends Cel {
 
/**
* renvoie le nombre d' observations correspondant aux criteres
* uid[0] : utilisateur obligatoire
* uid[1] : criteres de filtrage de la forme critere1=valeur1&critere2=valeur2
*
*/
function getElement($uid)
{
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
$chercheur_observations = new RechercheObservation($this->config);
 
$criteres = $_GET;
$retour = $chercheur_observations->compterObservations($uid[0], $criteres);
$this->envoyerJson($retour);
return true;
}
}
?>
/branches/v2.3-faux/jrest/services/SelfRefList.php
New file
0,0 → 1,73
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
// in utf8
// out utf8
 
// Fournit un référentiel relatif à l'utilisateur sur l'un des champs demandes
class SelfRefList extends Cel {
 
private $referentiels = array('station', 'lieudit', 'milieu');
 
/**
* Suivant le type de référentiel donné en paramètre, renvoie les liste de ses éléments
*
* uid[0] : utilisateur obligatoire
* uid[1] : referentiel demandé (obligatoire)
* $_GET["start"] et $GET_["limit"] : selection intervalle
* $_GET["recherche"] : cherche les noms qui commmencent selon la valeur
*
*/
public function getElement($uid){
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
if (!$this->paramObligatoiresSontPresents($uid)) {
return;
}
 
if ($_GET['recherche'] == '*') {
$_GET['recherche'] = '%';
}
 
$referentiel_demande = $uid[1];
$idUtilisateur = Cel::db()->proteger($uid[0]);
 
$requete = "SELECT DISTINCT $referentiel_demande " .
'FROM cel_obs '.
"WHERE ce_utilisateur = '$idUtilisateur' ";
if ($this->filtreRechercheEstDemande()) {
$requete .= " AND $referentiel_demande LIKE '".$_GET["recherche"]."%'";
}
if ($this->limiteEstDemandee()) {
$requete .= " ORDER BY $referentiel_demande LIMIT ".$_GET['start'].','.$_GET['limit'];
}
$resultat = Cel::db()->requeter($requete);
 
$referentiel = array();
foreach ($resultat as $cle => $valeur) {
if ($this->estUneValeurValide($valeur[$referentiel_demande])) {
$referentiel[] = $valeur[$referentiel_demande];
}
 
}
$this->envoyerJson($referentiel);
return true;
}
 
private function paramObligatoiresSontPresents($uid) {
return (isset($uid[1]) && in_array($uid[1], $this->referentiels) && (isset($uid[0]) && $uid[0] != ''));
}
 
private function filtreRechercheEstDemande() {
return (isset($_GET['recherche']) && trim($_GET['recherche']) != '');
}
 
private function limiteEstDemandee() {
return isset($_GET['start']) && is_numeric($_GET['start']) && isset($_GET['limit']) && is_numeric($_GET['limit']);
}
 
private function estUneValeurValide($chaine) {
return ($chaine != null && $chaine != '000null' && trim($chaine) != '');
}
}
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/branches/v2.3-faux/jrest/services/NameImage.php
New file
0,0 → 1,85
<?php
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author David Delon <david.delon@clapas.net>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
 
/**
* NameImage.php
*
* in : utf8
* out : 8859
*
* Cas d'utilisation :
* Service recherche d'image a partir d'un numero nomenclatural
*
* 1: Le service recoit un numero nomenclatural
* 2: Le service calcul le numero taxonomique associe
* 3: Le service recherche une image disponible pour ce numero taxonomique
* 4: Le service redimensionne l'image et la renvoie
*/
class NameImage extends Cel {
 
function getElement($uid){
$image = array("","");
if(isset($uid[0]) && isset($uid[1])) {
$uid[0] = $uid[0] != '' ? $uid[0] : 'bdtfx';
$image = $this->obtenirIllustration($uid[0], $uid[1]);
}
$this->envoyerJson($image);
return true;
}
function obtenirIllustration($referentiel_taxo, $nn) {
// TODO: gérer ici les images d'autres référentiels si celles si sont disponibles
$retour = array("","");
switch($referentiel_taxo) {
case 'bdtfx':
$retour = $this->effectuerRequetePhotoFlora($nn);
break;
default:
break;
}
return $retour;
}
private function effectuerRequetePhotoFlora($nn) {
$url_photoflora = $this->config['eflore']['url_service_photoflora'];
$url = $url_photoflora.'?masque.nn='.$nn.'&navigation.limite=1';
$resultat = @file_get_contents($url);
$resultat = json_decode($resultat);
if(is_object($resultat) && isset($resultat->resultats)) {
$element = (array)$resultat->resultats;
$element = array_pop($element);
if(is_object($element)) {
$image = array($element->{'binaire.href'}, $element->{'binaire.hrefmax'});
} else {
$image = array('','');
}
}
return $image;
}
}
/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log$
* Revision 1.4 2008-11-13 11:29:12 ddelon
* Reecriture gwt-ext
*
* Revision 1.2 2008-01-30 08:57:28 ddelon
* fin mise en place mygwt
*
* Revision 1.1 2007-06-06 13:31:16 ddelon
* v0.09
*
*/
?>
/branches/v2.3-faux/jrest/services/InventoryDateList.php
New file
0,0 → 1,89
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author Aurelien Peronnet <aurelien@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
 
/**
* Liste les date de releves par utilisateur
*
* in=utf8
* out=utf8
*
**/
class InventoryDateList extends Cel {
 
private $correspondance_fonction = array(1 => 'year', 2 => 'month', 3 => 'day');
 
/**
* @param int uid[0] : utilisateur obligatoire
* @param int uid[1] : si absent : valeur 'all' (annee)
* @param int uid[2] : si absent : valeur 'all' (mois)
* @param int uid[3] : si absent : valeur 'all' (jour)
*/
function getElement($uid){
 
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
$condition_requete = $this->traiterParametresEtConstruireRequete($uid);
 
$requete_liste_dates = 'SELECT DISTINCT '.
'date_observation AS id '.
'FROM cel_obs WHERE '.$condition_requete.' '.
'ORDER BY date_observation';
 
$liste_dates = Cel::db()->requeter($requete_liste_dates);
 
$liste_dates = $this->formaterListeResultats($liste_dates);
 
$this->envoyerJson($liste_dates);
return true;
}
 
private function formaterListeResultats($liste_dates) {
 
if (!$liste_dates) {
$liste_dates = array();
}
 
foreach($liste_dates as &$date) {
$date_heures = explode(' ',$date['id']);
if(count($date_heures) > 1) {
$date = $date_heures[0];
}
 
$date = $date;
}
 
return $liste_dates;
}
 
private function traiterParametresEtConstruireRequete($params) {
 
$requete_condition = ' ce_utilisateur = '.Cel::db()->proteger($params[0]);
 
$taille_tableau_parametres = count($params);
for($i=1; $i < $taille_tableau_parametres; $i++) {
if($this->estUnParametreDate($params[$i])) {
$fonction_date = $this->correspondance_fonction[$i];
$requete_condition .= ' AND '.$fonction_date.'(date_observation) = '.Cel::db()->proteger($params[$i]);
}
}
 
return $requete_condition;
}
 
private function estUnParametreDate($valeur) {
return is_numeric($valeur) && $valeur != "all";
}
}
?>
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/branches/v2.3-faux/jrest/services/InventoryContributionList.php
New file
0,0 → 1,76
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* PHP Version 5
*
* @category PHP
* @package papyrus_bp
* @author aurelien <aurelien@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/
*/
 
/**
* Classe renvoyant fragment html constitué à partir d'une liste très succinte des contributions de l'utilisateur
*
*/
class InventoryContributionList extends Cel {
 
function getRessource() {
echo '';
}
 
function getElement($uid){
 
if(!isset($uid[0])) {
echo '';
}
 
$requete_contributions = "SELECT * FROM cel_obs ".
"WHERE ce_utilisateur = ".Cel::db()->proteger($uid[0])." ".
"ORDER BY date_modification DESC LIMIT 0,5";
 
$resultat_contributions = Cel::db()->requeter($requete_contributions);
$resume = '';
 
if (is_array($resultat_contributions)) {
 
foreach ($resultat_contributions as $ligne) {
$ligne['nom_sel'] = htmlspecialchars($ligne['nom_sel']);
$ligne['ce_utilisateur'] = htmlspecialchars($ligne['ce_utilisateur']);
$ligne['zone_geo'] = htmlspecialchars($ligne['zone_geo']);
$ligne['id_zone_geo'] = htmlspecialchars($this->convertirCodeZoneGeoVersDepartement($ligne['ce_zone_geo']));
$ligne['station'] = htmlspecialchars($ligne['station']);
$ligne['milieu'] = htmlspecialchars($ligne['milieu']);
$ligne['commentaire'] = htmlspecialchars($ligne['commentaire']);
$ligne['transmission'] = htmlspecialchars($ligne['transmission']);
$resume.= '<p>'.$ligne['nom_sel'] ." (".$ligne['nom_sel_nn'].") ".
'Location : '. $ligne['zone_geo']." (".$ligne['id_zone_geo']."),". $ligne['station'] . "," .
$ligne['milieu'] . "," . $ligne['commentaire'] . "," . $ligne['transmission'] .
'</p>';
}
}
 
header("Content-Type: text/html; charset=ISO-8859-1");
print $resume;
exit;
}
}
/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log$
* Revision 1.5 2008-11-13 11:29:12 ddelon
* Reecriture gwt-ext
*
* Revision 1.4 2007-06-06 13:31:16 ddelon
* v0.09
*
* Revision 1.3 2007-05-22 12:54:09 ddelon
* Securisation acces utilisateur
*
*/
?>
/branches/v2.3-faux/jrest/services/InventoryCheck.php
New file
0,0 → 1,82
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* PHP Version 5
*
* @category PHP
* @package papyrus_bp
* @author David Delon <delon@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/
*/
 
/**
*
* Utilitaire mise a jour enregistrement inventaire
* A voir avec David mais ne devrait plus être utilisé
*
*/
class InventoryCheck extends Cel {
 
function getRessource(){
return;
 
$requete_obs ="SELECT id_observation, zone_geo, ce_zone_geo, date_observation, ce_utilisateur, courriel_utilisateur FROM cel_obs";
$resultat_obs = Cel::db()->requeter($requete_obs);
$observations = array();
if (is_array($resultat_obs)) {
$observations = $resultat_obs;
}
foreach ($observations as $obs) {
 
if ($obs['ce_zone_geo']!="000null") {
$requete_lieu = "select * from cel_zones_geo where nom = '".mysql_escape_string($obs['zone_geo'])."' and id_zone_geo='".mysql_escape_string($obs['ce_zone_geo'])."' limit 1";
}
else {
$requete_lieu = "select * from cel_zones_geo where name = '".mysql_escape_string($obs['zone_geo'])."' limit 1";
}
$res_loc = Cel::db()->requeter($requete_lieu);
if (is_array($res_loc) && count($res_loc) > 0) {
print $obs['id_observation'];
print " ";
print $obs['mail_utilisateur'];
print " : ";
print $obs['zone_geo'];
print " - ";
print $obs['ce_zone_geo'];
print " - ";
$lk="http://www.tela-botanica.org/cel/jrest/util/cel_inventory.php?PME_sys_fl=0&PME_sys_fm=0&PME_sys_sfn[0]=0&PME_sys_operation=PME_op_Change&PME_sys_rec=".$obs['id_observation'];
$link_desc=' <a href="'.$lk.'">Correction</a>';
print $link_desc;
print "<br>";
}
}
}
}
 
/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log$
* Revision 1.2 2008-01-30 08:57:28 ddelon
* fin mise en place mygwt
*
* Revision 1.1 2007-06-06 13:31:16 ddelon
* v0.09
*
* Revision 1.3 2007-05-22 12:54:09 ddelon
* Securisation acces utilisateur
*
*
*
*/
?>
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/branches/v2.3-faux/jrest/services/Inventory.php
New file
0,0 → 1,212
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author David Delon <david@tela-botanica.org>
* @author Aurelien Peronnet <aurelien@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
 
/**
* CRUD observation
*
* in=utf8
* out=utf8
*
**/
class Inventory extends Cel {
// TODO: faire un descriptif du service
function getRessource(){
 
}
 
function getElement($uid){
 
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
$value=array();
 
if(!isset($uid[0])) {
return;
}
$parametres_recherche = array(array('ce_utilisateur',$uid[0]),array('ordre',$uid[1]));
$chercheur_observations = new RechercheObservation($this->config);
$retour_recherche = $chercheur_observations->rechercherObservations($uid[0], $parametres_recherche, 0, 1)->get();
$observation = array();
if(is_array($retour_recherche) && count($retour_recherche) > 0) {
$observation = $retour_recherche[0];
}
$observation = $this->formaterObservationVersTableauSequentiel($observation);
$output = json_encode($observation);
$this->envoyerJson($output);
return true;
}
private function formaterObservationVersTableauSequentiel(&$observation) {
if ($observation['date_observation']!="0000-00-00 00:00:00") {
list($year,$month,$day)= explode('-',$observation['date_observation']);
list($day)= explode(' ',$day);
$observation['date_observation']=$day."/".$month."/".$year;
}
 
$observation = array($observation['nom_sel'], $observation['nom_sel_nn'],
$observation['nom_ret'], $observation['nom_ret_nn'],
$observation['nt'], $observation['famille'], $observation['zone_geo'],
$observation['ce_zone_geo'], $observation['ordre'],
$observation['date_observation'], $observation['lieudit'],
$observation['station'], $observation['milieu'],
$observation['commentaire'], $observation['latitude'],
$observation['longitude']);
return $observation;
}
 
function updateElement($uid,$pairs) {
 
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
if (!isset($uid[1])) {
//TODO: envoyer un message d'erreur
return;
}
$uid[1] = rtrim($uid[1],',');
$champs_etendus = isset($pairs['obs_etendue']) ? json_decode(stripslashes($pairs['obs_etendue']),true) : null;
unset($pairs['obs_etendue']);
 
if(isset($pairs['date_observation']) && !empty($pairs['date_observation'])) {
$time = strtotime(str_replace("/", "-", $pairs['date_observation']));
if(!$time || $time > time()) {
throw new Exception('Date invalide');
}
}
$gestionnaire_observation = new GestionObservation($this->config);
$modification_observation = $gestionnaire_observation->modifierObservation($uid[0],$uid[1],$pairs);
if($champs_etendus != null) {
$gestion_champs_etendus = new GestionChampsEtendus($this->config, 'obs');
$id_obs = $gestionnaire_observation->renvoyerIdPourOrdre($uid[0],$uid[1]);
foreach($champs_etendus as &$champ_etendu) {
$objet_champ_etendu = new ChampEtendu();
$objet_champ_etendu->id = $id_obs;
if($this->doitGenererCleChampEtendu($champ_etendu)) {
$champ_etendu['cle'] = $gestion_champs_etendus->transformerLabelEnCle($champ_etendu['label']);
}
$objet_champ_etendu->cle = $champ_etendu['cle'];
$objet_champ_etendu->label = $champ_etendu['label'];
$objet_champ_etendu->valeur = $champ_etendu['valeur'];
$champ_etendu = $objet_champ_etendu;
}
// ajouterParLots modifie les champs et ajoute ceux qui existent déjà
$champs_supp = $gestion_champs_etendus->ajouterParLots($champs_etendus);
}
return true;
}
 
function createElement($pairs) {
// Controle detournement utilisateur
$this->controleUtilisateur($pairs['ce_utilisateur']);
$champs_etendus = isset($pairs['obs_etendue']) ? json_decode(stripslashes($pairs['obs_etendue']),true) : null;
unset($pairs['obs_etendue']);
 
if(isset($pairs['date_observation']) && !empty($pairs['date_observation'])) {
$time = strtotime(str_replace("/", "-", $pairs['date_observation']));
if(!$time || $time > time()) {
throw new Exception('Date invalide');
}
}
$gestionnaire_observation = new GestionObservation($this->config);
$id_nouvelle_obs = $gestionnaire_observation->ajouterObservation($pairs['ce_utilisateur'], $pairs);
 
if($champs_etendus != null) {
$gestion_champs_etendus = new GestionChampsEtendus($this->config, 'obs');
foreach($champs_etendus as &$champ_etendu) {
$objet_champ_etendu = new ChampEtendu();
$objet_champ_etendu->id = $id_nouvelle_obs;
if($this->doitGenererCleChampEtendu($champ_etendu)) {
$champ_etendu['cle'] = $gestion_champs_etendus->transformerLabelEnCle($champ_etendu['label']);
}
$objet_champ_etendu->cle = $champ_etendu['cle'];
$objet_champ_etendu->label = $champ_etendu['label'];
$objet_champ_etendu->valeur = $champ_etendu['valeur'];
$champ_etendu = $objet_champ_etendu;
}
 
$champs_supp = $gestion_champs_etendus->ajouterParLots($champs_etendus);
}
return true;
}
/**
* Supprime une observation
*
* uid[0] : utilisateur obligatoire
* uid[1] : ordres de l'observation à supprimer
*/
function deleteElement($uid){
 
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
if (!isset($uid[1])) {
//TODO: envoyer un message d'erreur
return;
}
$uid[1] = rtrim($uid[1],',');
$gestionnaire_observation = new GestionObservation($this->config);
$id_obs = $gestionnaire_observation->renvoyerIdPourOrdre($uid[0],$uid[1]);
$suppression_observation = $gestionnaire_observation->supprimerObservation($uid[0],$uid[1]);
$gestion_champs_etendus = new GestionChampsEtendus($this->config, 'obs');
$champs_supp = $gestion_champs_etendus->vider($id_obs);
if ($suppression_observation) {
echo "OK";
}
exit() ;
}
function doitGenererCleChampEtendu($champ_etendu) {
return !isset($champ_etendu['cle']) ||
trim($champ_etendu['cle'] == "" ||
strpos($champ_etendu['cle'],'tempid_') !== false);
}
}
/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log$
* Revision 1.11 2008-11-13 11:29:12 ddelon
* Reecriture gwt-ext
*
* Revision 1.10 2008-01-30 08:57:28 ddelon
* fin mise en place mygwt
*
* Revision 1.9 2007-05-22 12:54:09 ddelon
* Securisation acces utilisateur
*
*/
?>
/branches/v2.3-faux/jrest/services/TestNameParser.php
New file
0,0 → 1,123
<?php
require_once('NameParser.php');
$parse = new NameParser();
 
$str=array();
$str[]='Paris quadrifolia L.';
$str[]='Phyteuma spicatum L.';
$str[]='Pinus sylvestris L.';
$str[]='Polygonatum multiflorum (L.) All.';
$str[]='Polygonatum multiflorum (L.) All.';
$str[]='Potentilla sterilis (L.) Garcke';
$str[]='Potentilla sterilis (L.) Garcke';
$str[]='Primula elatior (L.) Hill';
$str[]='Primula elatior (L.) Hill';
$str[]='Ranunculus ficaria L.';
$str[]='Ranunculus ficaria L.';
$str[]='Ranunculus ficaria L.';
$str[]='Ranunculus ficaria L.';
$str[]='Salvia pratensis L.';
$str[]='Sanguisorba officinalis L.';
$str[]='Sanicula europaea L.';
$str[]='Scrophularia nodosa L.';
$str[]='Securigera varia (L.) P. Lassen';
$str[]='Silene latifolia Poiret';
$str[]='Sonchus asper (L.) Hill';
$str[]='Stachys recta L.';
$str[]='Stachys sylvatica L.';
$str[]='Stellaria holostea L.';
$str[]='Symphytum officinale L.';
$str[]='Symphytum officinale L.';
$str[]='Teucrium scorodonia L.';
$str[]='Tilia platyphyllos Scop.';
$str[]='Tussilago farfara L.';
$str[]='Urtica dioica L.';
$str[]='Urtica dioica L.';
$str[]='Urtica dioica L.';
$str[]='Vaccinium myrtillus L.';
$str[]='Valeriana officinalis subsp. repens (Host) O. Bolòs and Vigo';
$str[]='Valeriana officinalis subsp. repens (Host) O. Bolòs & Vigo';
$str[]='Viburnum lantana L.';
$str[]='Viburnum opulus L.';
$str[]='Viola reichenbachiana Jordan ex Boreau';
$str[]='Viscum album L.';
$str[]='Aegopodium podagraria L.';
$str[]='Ajuga reptans L.';
$str[]='Alisma plantago-aquatica L.';
$str[]='Alliaria petiolata (M. Bieb.) Cavara & Grande';
$str[]='Alnus glutinosa (L.) Gaertn.';
$str[]='Bidens frondosa L.';
$str[]='Bidens tripartita L.';
$str[]='Callitriche palustris L.';
$str[]='Campanula trachelium L.';
$str[]='Carex brizoides L.';
$str[]='Carex vesicaria L.';
$str[]='Circaea lutetiana L.';
$str[]='Dryopteris filix-mas (L.) Schott';
$str[]='Elatine hexandra (Lapierre) DC.';
$str[]='Fragaria vesca L.';
$str[]='Glechoma hederacea L.';
$str[]='Glyceria fluitans (L.) R. Br.';
$str[]='Gnaphalium uliginosum L.';
$str[]='Iris pseudacorus L.';
$str[]='Lathyrus pratensis L.';
$str[]='Lemna minor L.';
$str[]='Leucanthemum vulgare Lam.';
$str[]='Lotus pedunculatus Cav.';
$str[]='Lycopus europaeus L.';
$str[]='Lysimachia nemorum L.';
$str[]='Lythrum portula (L.) D.A. Webb';
$str[]='Lythrum salicaria L.';
$str[]='Milium effusum L.';
$str[]='Oxalis acetosella L.';
$str[]='Phalaris arundinacea L.';
$str[]='Phyteuma spicatum L.';
$str[]='Potamogeton natans L.';
$str[]='Primula elatior (L.) Hill';
$str[]='Ranunculus flammula L.';
$str[]='Ranunculus sceleratus L.';
$str[]='Sagittaria sagittifolia L.';
$str[]='Scrophularia nodosa L.';
$str[]='Silene dioica (L.) Clairv.';
$str[]='Sparganium emersum Rehmann';
$str[]='Sparganium erectum L.';
$str[]='Valeriana officinalis L. subsp. tenuifolia Schübler & Martens';
$str[]='Veronica montana L.';
$str[]='Vinca minor L.';
$str[]='Acer campestre L.';
$str[]='Acer campestre L.';
$str[]='Achillea millefolium L.';
$str[]='Achillea millefolium L.';
$str[]='Achillea ptarmica L.';
$str[]='Achillea ptarmica L.';
$str[]='Achillea ptarmica L.';
 
foreach ($str as $st) {
$data = $parse->parse($st);
print 'nom : ';
print $st;
print ', genus : ';
print $data['genus'];
print ', species : ';
print $data['species'];
print ', authority : ';
print $data['authority'];
if (isset ($data['infra']) && $data['infra']!='') {
print ', infra : ';
print $data['infra'];
}
if (isset ($data['infra_authority']) && $data['infra_authority']!='') {
print ', infra authority : ';
print $data['infra_authority'];
}
if (isset ($data['infra_type']) && $data['infra_type']!='') {
print ', infra type : ';
print $data['infra_type'];
}
print "</br>";
}
 
?>
/branches/v2.3-faux/jrest/services/LocationSearch.php
New file
0,0 → 1,100
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* Classe gérant la completion des noms de lieux
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* @author David Delon <david.delon@clapas.net>
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright © 2010, David Delon
*/
 
/**
* Cas d'utilisation :
* Service completion nom de commune (plus tard de lieu en général)
*
* 1 : L'application recoit un debut de nom de lieu
* 2 : Si la longueur du prefixe est > 2, l'application retourne les 50 premieres lieux
* commencant par ce prefixe
**/
class LocationSearch extends Cel {
 
function getElement($uid){
 
$retour = array();
if (isset($uid[0])) {
$retour = $this->executerRequeteLieu($uid[0]);
}
$this->envoyerJson($retour);
return true;
}
 
function getRessource(){
print "[]";
return;
}
private function executerRequeteLieu($lieu) {
$lieu_formate = $this->formaterChaineLieuPourRequete($lieu);
$retour = array();
if ($this->estUneChaineRequeteValide($lieu_formate)) {
$requete_information_lieu = 'SELECT DISTINCT nom, code '.
'FROM cel_zones_geo '.
'WHERE '.
'nom LIKE '.Cel::db()->proteger($lieu_formate.'%').' '.
'ORDER BY nom LIMIT 50';
 
$liste_lieux = Cel::db()->requeter($requete_information_lieu);
if($liste_lieux) {
foreach($liste_lieux as $lieu_trouve) {
$retour[] = $this->formaterLigneResultat($lieu_trouve);
}
}
}
return $retour;
}
 
/**
* Remplace les * par % pour faire des recherches floues
* Remplace les + par _ (nginx envoie des "+" dans l'URL à la place des espaces)
* Remplace les espaces et les - par _ car les noms de communes peuvent avoir des espaces ou des tirets
* @param string $lieu
* @return string le lieu formaté pour la recherche
*/
private function formaterChaineLieuPourRequete($lieu) {
$lieu = ltrim($lieu);
$lieu = preg_replace('/\*+/', '%', $lieu);
$lieu = str_replace(['+', ' ', '-'], '_', $lieu);
return $lieu;
}
private function estUneChaineRequeteValide($lieu) {
return (strlen($lieu) > 0) && ($lieu != '%');
}
private function formaterLigneResultat($ligne) {
return array($ligne['nom']." (".substr(sprintf("%02s",$ligne['code']),0,2).")",$ligne['code']);
}
}
/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log$
* Revision 1.4 2008-01-30 08:57:28 ddelon
* fin mise en place mygwt
*
* Revision 1.3 2007-05-21 18:13:03 ddelon
* Correction bug recherche commune du type "la canourgue"
*
*
*/
?>
/branches/v2.3-faux/jrest/services/NomsChampsEtendus.php
New file
0,0 → 1,80
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
// in utf8
// out utf8
 
// Fournit un référentiel relatif à l'utilisateur sur les noms ou les valeurs des champs étendus
class NomsChampsEtendus extends Cel {
 
/**
* Suivant le type de référentiel donné en paramètre, renvoie les liste de ses éléments
*
* uid[0] : "cle" ou "valeur"
* $_GET["start"] et $GET_["limit"] : selection intervalle
* $_GET["cle"] : restreint la recherche sur les valeurs d'une certaine clé
* $_GET["recherche"] : cherche les noms qui commmencent selon la valeur
*/
function getElement($uid){
if (!$this->paramObligatoiresSontPresents($uid)) {
return;
}
 
$_GET['recherche'] = str_replace('*', '%', $_GET['recherche']);
$referentiel = array();
 
if($uid[0] == "cle") {
$referentiel = $this->rechercherCles($_GET['recherche']);
} else if($uid[0] == "valeur") {
$referentiel = $this->rechercherValeurs($_GET['cle'], $_GET['recherche']);
}
 
$this->envoyerJson($referentiel);
return true;
}
 
function rechercherCles($recherche_cle) {
$requete = "SELECT DISTINCT cle, label FROM cel_obs_etendues WHERE ".
"cle LIKE ".Cel::db()->proteger($recherche_cle)." OR ".
"label LIKE ".Cel::db()->proteger($recherche_cle)." ";
$resultat = Cel::db()->requeter($requete);
 
$referentiel = array();
foreach($resultat as $valeur) {
$referentiel[$valeur['cle']] = $valeur['label'];
}
return $referentiel;
}
 
function rechercherValeurs($cle, $recherche_valeur) {
$requete = "SELECT DISTINCT valeur FROM cel_obs_etendues WHERE ".
"cle = ".Cel::db()->proteger($cle)." AND ".
"valeur LIKE ".Cel::db()->proteger($recherche_valeur.'%')." ";
 
$referentiel_resultat = Cel::db()->requeter($requete);
$referentiel = array();
 
foreach ($referentiel_resultat as $valeur) {
if (trim($valeur['valeur']) != '') {
$referentiel[] = $valeur['valeur'];
}
}
return $referentiel;
}
 
function paramObligatoiresSontPresents($uid) {
return (isset($uid[0]) && ($uid[0] == 'cle' || $uid[0] == 'valeur'));
}
 
function filtreRechercheEstDemande() {
return (isset($_GET["recherche"]) && trim($_GET["recherche"]) != '');
}
 
function limiteEstDemandee() {
return isset($_GET["start"]) && is_numeric($_GET["start"]) && isset($_GET["limit"]) && is_numeric($_GET["limit"]);
}
 
function estUneValeurValide($chaine) {
return ($chaine != null && $chaine != "000null" && trim($chaine) != '');
}
}
/branches/v2.3-faux/jrest/services/Resume.php
New file
0,0 → 1,129
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* PHP Version 5
*
* @category PHP
* @package papyrus_bp
* @author aurelien <aurelien@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/papyrus_bp/
*/
 
/**
* Classe renvoyant un petit bout de json contenant les dernières obs publiques d'un utilisateur
* Utilisée par l'annuaire appelant les web services résumé de chaque application
*
*/
class Resume extends Cel {
 
function getElement($uid){
 
$requete_dernieres_obs = 'SELECT * FROM cel_obs'.
' WHERE ce_utilisateur = '.Cel::db()->proteger($uid[1]).
' AND transmission = 0'.
' ORDER BY date_modification DESC LIMIT 0,5';
 
$resultat_dernieres_obs = Cel::db()->requeter($requete_dernieres_obs);
$dernieres_obs = array();
$resume = array();
 
if (is_array($resultat_dernieres_obs)) {
$dernieres_obs = $resultat_dernieres_obs;
}
 
$resume['titre'] = 'Vos dernières observations publiées';
$resume['lien_appli'] = '<a href="www.tela-botanica.org/appli:cel2"> Accéder au carnet en ligne </a>';
 
if (count($dernieres_obs) == 0) {
$resume['message'] = 'Aucune observation saisie pour le moment';
}
 
foreach ($dernieres_obs as $obs) {
 
$chemin_sur_serveur = $this->config['cel']['url_images'];
 
$date = 'Datée du '.$obs['date_modification'].'<br/>' ;
$lieu = 'Lieu : '.trim($obs['zone_geo'],'000null').' ('.$this->convertirCodeZoneGeoVersDepartement(trim($obs['ce_zone_geo']),'000null').') '.trim($obs['station'],'000null').' '.trim($obs['lieudit'],'000null').'<br/>' ;
 
$image ='';
$cible_lien = '';
$req_liaison = 'SELECT * FROM cel_images WHERE id_image IN (SELECT id_image FROM cel_obs_images WHERE id_observation = "'.$obs['id_observation'].'") AND ce_utilisateur = "'.$obs['ce_utilisateur'].'"' ;
$res_liaison = Cel::db()->requeter($req_liaison);
 
$ligne_image = null;
foreach ($res_liaison as $img) {
$row = $img;
}
 
if($row != null) {
$row['nom_original'] = htmlspecialchars($row['nom_original']);
$row['id_image'] = htmlspecialchars($row['id_image']);
$id = $row['id_image'];
$tailleXY = $this->calculerDimensions(array($row['largeur'], $row['hauteur']));
$id = sprintf('%09s', $id) ;
$id = wordwrap($id, 3 , '_', true) ;
$id_fichier = $id.".jpg" ;
$niveauDossier = explode("_", $id) ;
$dossierNiveau1 = $niveauDossier[0] ;
$dossierNiveau2 = $niveauDossier[1] ;
$chemin_sur_serveur_final = $chemin_sur_serveur.'/'.$dossierNiveau1.'/'.$dossierNiveau2 ;
$chemin_fichier = $chemin_sur_serveur_final.'/L/'.$id."_L.jpg" ;
$chemin_fichier_s = $chemin_sur_serveur_final.'/M/'.$id."_M.jpg" ;
$image = '<img src="'.$chemin_fichier_s.'" alt="'.$row['nom_original'].'" height="'.$tailleXY[1].'px" width="'.$tailleXY[0].'px"></img>';
$cible_lien = $chemin_fichier;
}
$resume_item = array('element' => $obs['nom_ret'].$date.$lieu, 'lien' => $cible_lien,'image' => $image);
$resume['elements'][] = $resume_item;
}
 
$this->envoyerJson($resume);
return true;
}
 
public function calculerDimensions($tailleXY) {
 
$tailleOr = 75 ;
 
if($tailleXY[1] == 0) {
$tailleXY[1] = $tailleOr;
}
 
if($tailleXY[0] == 0) {
$tailleXY[0] = $tailleOr;
}
 
$maxTaille = max($tailleXY[1],$tailleXY[0]) ;
 
if($maxTaille == $tailleXY[1]) {
 
$rapport = $tailleXY[1]/$tailleXY[0] ;
$tailleXY[1] = 75 ;
$tailleXY[0] = round($tailleXY[1]/$rapport,0) ;
 
}else {
$rapport = $tailleXY[0]/$tailleXY[1] ;
$tailleXY[0] = 75 ;
$tailleXY[1] = round($tailleXY[0]/$rapport,0) ;
}
 
return $tailleXY ;
}
}
?>
/branches/v2.3-faux/jrest/services/ImportXLS.php
New file
0,0 → 1,1161
<?php
/**
* @category PHP
* @package jrest
* @author Raphaël Droz <raphael@tela-botania.org>
* @copyright 2013 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
*/
 
/**
* Service d'import de données d'observation du CEL au format XLS
*
* Sont define()'d commme n° de colonne tous les abbrevs retournés par
* FormateurGroupeColonne::nomEnsembleVersListeColonnes() préfixés par C_ cf: detectionEntete()
*
* Exemple d'un test:
* $ GET "/jrest/ExportXLS/22506?format=csv&range=*&limite=13" \
* | curl -F "upload=@-" -F utilisateur=22506 "/jrest/ImportXLS"
* # 13 observations importées
* + cf MySQL general_log = 1
*
**/
 
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(realpath(__FILE__))) . '/lib');
// TERM
error_reporting(-1);
ini_set('html_errors', 0);
ini_set('xdebug.cli_color', 2);
require_once('lib/PHPExcel/Classes/PHPExcel.php');
require_once('FormateurGroupeColonne.php');
 
 
date_default_timezone_set("Europe/Paris");
 
// nombre d'INSERT à cumuler par requête SQL
// (= nombre de lignes XLS à bufferiser)
//define('NB_LIRE_LIGNE_SIMUL', 30);
define('NB_LIRE_LIGNE_SIMUL', 5);
 
// en cas d'import d'un fichier CSV, utilise fgetcsv() plutôt
// que PHPExcel ce qui se traduit par un gain de performances très substanciel
define('QUICK_CSV_IMPORT', TRUE);
 
// Numbers of days between January 1, 1900 and 1970 (including 19 leap years)
// see traiterDateObs()
// define("MIN_DATES_DIFF", 25569);
 
 
class MyReadFilter implements PHPExcel_Reader_IReadFilter {
// exclusion de colonnes
public $exclues = array();
 
// lecture par morceaux
public $ligne_debut = 0;
public $ligne_fin = 0;
public static $gestion_mots_cles = null;
 
public function __construct() {}
public function def_interval($debut, $nb) {
$this->ligne_debut = $debut;
$this->ligne_fin = $debut + $nb;
}
public function readCell($colonne, $ligne, $worksheetName = '') {
if(@$this->exclues[$colonne]) return false;
// si des n° de morceaux ont été initialisés, on filtre...
if($this->ligne_debut && ($ligne < $this->ligne_debut || $ligne >= $this->ligne_fin)) return false;
return true;
}
}
 
// XXX: PHP 5.3
function __anonyme_1($v) { return !$v['importable']; }
function __anonyme_2(&$v) { $v = $v['nom']; }
function __anonyme_3($cell) { return !is_null($cell); };
function __anonyme_5($item) { return is_null($item) ? '?' : $item; }
function __anonyme_6() { return NULL; }
 
class ImportXLS extends Cel {
static function __anonyme_4(&$item, $key) { $item = self::quoteNonNull(trim($item)); }
 
static $ordre_BDD = Array(
"ce_utilisateur",
"prenom_utilisateur",
"nom_utilisateur",
"courriel_utilisateur",
"ordre",
"nom_sel",
"nom_sel_nn",
"nom_ret",
"nom_ret_nn",
"nt",
"famille",
"nom_referentiel",
"zone_geo",
"ce_zone_geo",
"date_observation",
"lieudit",
"station",
"milieu",
"mots_cles_texte",
"commentaire",
"transmission",
"date_creation",
"date_modification",
"date_transmission",
"latitude",
"longitude",
"altitude",
"abondance",
"certitude",
"phenologie",
"code_insee_calcule"
);
 
// cf: initialiser_pdo_ordered_statements()
// eg: "INSERT INTO cel_obs (ce_utilisateur, ..., phenologie, code_insee_calcule) VALUES"
// colonnes statiques d'abord, les autres ensuite, dans l'ordre de $ordre_BDD
static $insert_prefix_ordre;
// eg: "(<id>, <prenom>, <nom>, <email>, now(), now(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
// dont le nombre de placeholder dépend du nombre de colonnes non-statiques
// colonnes statiques d'abord, les autres ensuite, dans l'ordre de $ordre_BDD
static $insert_ligne_pattern_ordre;
 
// seconde (meilleure) possibilité
// cf: initialiser_pdo_statements()
// eg: "INSERT INTO cel_obs (ce_utilisateur, ..., date_creation, ...phenologie, code_insee_calcule) VALUES"
static $insert_prefix;
// eg: "(<id>, <prenom>, <nom>, <email>, ?, ?, ?, now(), now(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
// dont le nombre de placeholder dépend du nombre de colonnes non-statiques
static $insert_ligne_pattern;
 
/*
Ces colonnes:
- sont propres à l'ensemble des enregistrements uploadés
- sont indépendantes du numéro de lignes
- n'ont pas de valeur par défaut dans la structure de la table
- nécessitent une initialisation dans le cadre de l'upload
 
initialiser_colonnes_statiques() y merge les données d'identification utilisateur
*/
public $colonnes_statiques = Array(
"ce_utilisateur" => NULL,
"prenom_utilisateur" => NULL,
"nom_utilisateur" => NULL,
"courriel_utilisateur" => NULL,
 
// fixes (fonction SQL)
// XXX future: mais pourraient varier dans le futur si la mise-à-jour
// d'observation est implémentée
"date_creation" => "now()",
"date_modification" => "now()",
);
 
public $id_utilisateur = NULL;
 
// erreurs d'import
public $bilan = Array();
 
// cache (pour traiterLocalisation() pour l'instant)
static $cache = Array('geo' => array());
 
function ImportXLS($config) {
parent::__construct($config);
}
 
function createElement($pairs) {
if(!isset($pairs['utilisateur']) || trim($pairs['utilisateur']) == '') {
exit('0');
}
 
$id_utilisateur = intval($pairs['utilisateur']);
$this->id_utilisateur = $id_utilisateur; // pour traiterImage();
 
if(!isset($_SESSION)) session_start();
$this->controleUtilisateur($id_utilisateur);
 
$this->utilisateur = $this->getInfosComplementairesUtilisateur($id_utilisateur);
 
 
$this->initialiser_colonnes_statiques($id_utilisateur);
 
// initialisation du statement PDO/MySQL
// première version, pattern de requête pas génial
/* list(self;;$insert_prefix_ordre, self::$insert_ligne_pattern_ordre) =
$this->initialiser_pdo_ordered_statements($this->colonnes_statiques); */
list(self::$insert_prefix, self::$insert_ligne_pattern) =
$this->initialiser_pdo_statements($this->colonnes_statiques);
 
$infos_fichier = array_pop($_FILES);
/*$objPHPExcel = PHPExcel_IOFactory::load($infos_fichier['tmp_name']);
$donnees = $objPHPExcel->getActiveSheet()->toArray(NULL,FALSE,FALSE,TRUE);*/
 
/*$objReader = PHPExcel_IOFactory::createReader("Excel5");
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load($infos_fichier['tmp_name']);*/
 
//var_dump($donnees);
 
// renomme le fichier pour lui ajouter son extension initiale, ce qui
// permet (une sorte) d'autodétection du format.
$fichier = $infos_fichier['tmp_name'];
$extension = pathinfo($infos_fichier['name'], PATHINFO_EXTENSION);
if( (strlen($extension) == 3 || strlen($extension) == 4) &&
(@rename($fichier, $fichier . '.' . $extension))) { // XXX: @ safe-mode
$fichier = $fichier . '.' . $extension;
}
 
$objReader = PHPExcel_IOFactory::createReaderForFile($fichier);
// TODO: check if compatible with toArray(<1>,<2>,TRUE,<4>)
$objReader->setReadDataOnly(true);
 
// TODO: is_a obsolete entre 5.0 et 5.3, retirer le @ à terme
$IS_CSV = @is_a($objReader, 'PHPExcel_Reader_CSV') && QUICK_CSV_IMPORT;
// en cas d'usage de fgetcsv, testons que nous pouvons compter les lignes
if($IS_CSV) $nb_lignes = intval(exec("wc -l $fichier"));
// et, le cas échéant, fallback sur PHPExcel à nouveau. La raison de ce test ici est
// l'instabilité du serveur (safe_mode, safe_mode_exec_dir, symlink vers binaires pour exec(), ... multiples points-of-failure)
if($IS_CSV && !$nb_lignes) $IS_CSV = FALSE;
 
if($IS_CSV) {
$objReader->setDelimiter(',')
->setEnclosure('"')
->setLineEnding("\n")
->setSheetIndex(0);
}
 
// on ne conserve que l'en-tête
$filtre = new MyReadFilter();
$filtre->def_interval(1, 2);
$objReader->setReadFilter($filtre);
 
$objPHPExcel = $objReader->load($fichier);
$obj_infos = $objReader->listWorksheetInfo($fichier);
 
if($IS_CSV) {
// $nb_lignes est déjà défini ci-dessus
$csvFileHandler = fopen($fichier, 'r');
// nous utilisons la valeur de retour dans un but informatif de l'utilisateur à la
// fin de l'import, *mais aussi* dans un array_diff_key() ci-dessous car bien que dans le
// fond le "parser" fgetcsv() n'ait pas d'intérêt à connaître les colonnes à ignorer,
// il se trouve que celles-ci peuvent interférer sur des fonctions comme traiterEspece()
// cf test "ref-nom-num.test.php" pour lequel l'élément C_NOM_SEL vaudrait 3 et $ligne serait array(3 => -42)
$filtre->exclues = self::detectionEntete(fgetcsv($csvFileHandler), TRUE);
} else {
// XXX: indépendant du readFilter ?
$nb_lignes = $obj_infos[0]['totalRows'];
$donnees = $objPHPExcel->getActiveSheet()->toArray(NULL, FALSE, TRUE, TRUE);
$filtre->exclues = self::detectionEntete($donnees[1]);
}
 
$obs_ajouts = 0;
$obs_maj = 0;
$nb_images_ajoutees = 0;
$nb_mots_cle_ajoutes = 0;
 
$dernier_ordre = Cel::db()->requeter("SELECT MAX(ordre) AS ordre FROM cel_obs WHERE ce_utilisateur = $id_utilisateur");
$dernier_ordre = intval($dernier_ordre[0]['ordre']) + 1;
if(! $dernier_ordre) $dernier_ordre = 0;
 
// on catch to les trigger_error(E_USER_NOTICE);
set_error_handler(array($this, 'erreurs_stock'), E_USER_NOTICE);
$this->taxon_info_webservice = new RechercheInfosTaxonBeta($this->config, NULL);
 
 
// lecture par morceaux (chunks), NB_LIRE_LIGNE_SIMUL lignes à fois
// pour aboutir des requêtes SQL d'insert groupés.
for($ligne = 2; $ligne < $nb_lignes + NB_LIRE_LIGNE_SIMUL; $ligne += NB_LIRE_LIGNE_SIMUL) {
if(!$IS_CSV) {
$filtre->def_interval($ligne, NB_LIRE_LIGNE_SIMUL);
$objReader->setReadFilter($filtre);
 
/* recharge avec $filtre actif (filtre sur lignes colonnes):
- exclue les colonnes inutiles/inutilisables)
- ne selectionne que les lignes dans le range [$ligne - $ligne + NB_LIRE_LIGNE_SIMUL] */
$objPHPExcel = $objReader->load($fichier)->getActiveSheet();
 
// set col typing
if(C_CE_ZONE_GEO != 'C_CE_ZONE_GEO')
$objPHPExcel->getStyle(C_CE_ZONE_GEO . '2:' . C_CE_ZONE_GEO . $objPHPExcel->getHighestRow())->getNumberFormat()->setFormatCode('00000');
 
// TODO: set to string type
if(C_ZONE_GEO != 'C_ZONE_GEO')
$objPHPExcel->getStyle(C_ZONE_GEO . '2:' . C_ZONE_GEO . $objPHPExcel->getHighestRow())->getNumberFormat()->setFormatCode('00000');
 
$donnees = $objPHPExcel->toArray(NULL, FALSE, TRUE, TRUE);
}
else {
$i = NB_LIRE_LIGNE_SIMUL;
$donnees = array();
while($i--) {
$tab = fgetcsv($csvFileHandler);
if(!$tab) continue;
$donnees[] = array_diff_key($tab, $filtre->exclues);
}
 
}
 
// var_dump($donnees, get_defined_constants(true)['user']);die;
// ici on appel la fonction qui fera effectivement l'insertion multiple
// à partir des (au plus) NB_LIRE_LIGNE_SIMUL lignes
 
// TODO: passer $this, ne sert que pour appeler des méthodes publiques qui pourraient être statiques
list($enregistrements, $images, $mots_cle) =
self::chargerLignes($this, $donnees, $this->colonnes_statiques, $dernier_ordre);
if(! $enregistrements) break;
 
self::trierColonnes($enregistrements);
// normalement: NB_LIRE_LIGNE_SIMUL, sauf si une enregistrement ne semble pas valide
// ou bien lors du dernier chunk
 
$nb_rec = count($enregistrements);
$sql_pattern = self::$insert_prefix .
str_repeat(self::$insert_ligne_pattern_ordre . ', ', $nb_rec - 1) .
self::$insert_ligne_pattern_ordre;
 
$sql_pattern = self::$insert_prefix .
str_repeat(self::$insert_ligne_pattern . ', ', $nb_rec - 1) .
self::$insert_ligne_pattern;
 
Cel::db()->beginTransaction();
$stmt = Cel::db()->prepare($sql_pattern);
$donnees = array();
foreach($enregistrements as $e) $donnees = array_merge($donnees, array_values($e));
 
// echo $sql_pattern . "\n"; var_dump($enregistrements, $donnees); die; // debug ici
 
$stmt->execute($donnees);
 
// $stmt->debugDumpParams(); // https://bugs.php.net/bug.php?id=52384
$dernier_autoinc = Cel::db()->lastInsertId();
Cel::db()->commit();
 
if(! $dernier_autoinc) trigger_error("l'insertion semble avoir échoué", E_USER_NOTICE);
 
$obs_ajouts += count($enregistrements);
// $obs_ajouts += count($enregistrements['insert']);
// $obs_maj += count($enregistrements['update']);
$ordre_ids = self::chargerCorrespondancesIdOrdre($this, $enregistrements);
$nb_images_ajoutees += self::stockerImages($enregistrements, $images, $ordre_ids);
$nb_mots_cle_ajoutes += self::stockerMotsCle($enregistrements, $mots_cle, $dernier_autoinc);
}
 
restore_error_handler();
 
if($this->bilan) echo implode("\n", $this->bilan) . "\n";
printf('%1$d observation%2$s ajoutée%2$s' . "\n" .
'%3$d image%4$s attachée%4$s' . "\n" .
// '%5$d mot%6$c-clef ajouté%6$c [TODO]' . "\n" . // TODO
(count($filtre->exclues) > 0 ? 'colonne%7$s non-traitée%7$s: %8$s' . "\n" : ''),
 
$obs_ajouts,
$obs_ajouts > 1 ? 's' : '',
$nb_images_ajoutees,
$nb_images_ajoutees > 1 ? 's' : '',
$nb_mots_cle_ajoutes,
$nb_mots_cle_ajoutes > 1 ? 's' : '',
count($filtre->exclues) > 1 ? 's' : '',
implode(', ', $filtre->exclues));
die();
}
 
/* detectionEntete() sert deux rôles:
1) détecter le type de colonne attendu à partir des textes de la ligne d'en-tête afin de define()
2) permet d'identifier les colonnes non-supportées/inutiles afin d'alléger le processus de parsing de PHPExcel
grace au ReadFilter (C'est le rôle de la valeur de retour)
 
La raison de la présence du paramètre $numeric_keys est que pour réussir à identifier les colonnes à exclure nous
devons traiter un tableau représentant la ligne d'en-tête aussi bien:
- sous forme associative pour PHPExcel (les clefs sont les lettres de l'alphabet)
- sous forme de clefs numériques (fgetcsv())
Le détecter après coup est difficile et pourtant cette distinction est importante car le comportement
d'array_merge() (réordonnancement des clefs numérique) n'est pas souhaitable dans le second cas. */
static function detectionEntete($entete, $numeric_keys = FALSE) {
$colonnes_reconnues = Array();
$cols = FormateurGroupeColonne::nomEnsembleVersListeColonnes('standard,avance');
foreach($entete as $k => $v) {
// traite les colonnes en faisant fi de la casse et des accents
$entete_simple = iconv('UTF-8', 'ASCII//TRANSLIT', strtolower(trim($v)));
foreach($cols as $col) {
$entete_officiel_simple = iconv('UTF-8', 'ASCII//TRANSLIT', strtolower(trim($col['nom'])));
$entete_officiel_abbrev = $col['abbrev'];
if($entete_simple == $entete_officiel_simple || $entete_simple == $entete_officiel_abbrev) {
// debug echo "define C_" . strtoupper($entete_officiel_abbrev) . ", $k ($v)\n";
define("C_" . strtoupper($entete_officiel_abbrev), $k);
$colonnes_reconnues[$k] = 1;
break;
}
}
}
// défini tous les index que nous utilisons à une valeur d'index de colonne Excel qui n'existe pas dans
// le tableau renvoyé par PHPExcel
// Attention cependant d'utiliser des indexes différenciés car traiterLonLat() et traiterEspece()
// les utilisent
foreach($cols as $col) {
if(!defined("C_" . strtoupper($col['abbrev'])))
define("C_" . strtoupper($col['abbrev']), "C_" . strtoupper($col['abbrev']));
}
 
// prépare le filtre de PHPExcel qui évitera le traitement de toutes les colonnes superflues
 
// eg: diff ( Array( H => Commune, I => rien ) , Array( H => 1, K => 1 )
// ==> Array( I => rien )
$colonnesID_non_reconnues = array_diff_key($entete, $colonnes_reconnues);
 
// des colonnes de FormateurGroupeColonne::nomEnsembleVersListeColonnes()
// ne retient que celles marquées "importables"
$colonnes_automatiques = array_filter($cols, '__anonyme_1');
 
// ne conserve que le nom long pour matcher avec la ligne XLS d'entête
array_walk($colonnes_automatiques, '__anonyme_2');
 
// intersect ( Array ( N => Milieu, S => Ordre ), Array ( ordre => Ordre, phenologie => Phénologie ) )
// ==> Array ( S => Ordre, AA => Phénologie )
$colonnesID_a_exclure = array_intersect($entete, $colonnes_automatiques);
 
if($numeric_keys) {
return $colonnesID_non_reconnues + $colonnesID_a_exclure;
}
// TODO: pourquoi ne pas comparer avec les abbrevs aussi ?
// merge ( Array( I => rien ) , Array ( S => Ordre, AA => Phénologie ) )
// ==> Array ( I => rien, AA => Phénologie )
return array_merge($colonnesID_non_reconnues, $colonnesID_a_exclure);
}
static function chargerCorrespondancesIdOrdre($cel, $lignes) {
$ordre_ids = array();
$requete_obs_ids = "SELECT id_observation, ordre FROM cel_obs WHERE ordre IN (";
foreach($lignes as &$ligne) {
$requete_obs_ids .= $ligne['ordre'].',';
}
$requete_obs_ids = rtrim($requete_obs_ids, ',');
$requete_obs_ids .= ") AND ce_utilisateur = ".Cel::db()->proteger($cel->id_utilisateur);
$obs_ids = Cel::db()->requeter($requete_obs_ids);
foreach($obs_ids as &$obs) {
$ordre_ids[$obs['ordre']] = $obs['id_observation'];
}
return $ordre_ids;
}
 
/*
* charge un groupe de lignes
*/
static function chargerLignes($cel, $lignes, $colonnes_statiques, &$dernier_ordre) {
$enregistrement = NULL;
$enregistrements = Array();
$toutes_images = Array();
$tous_mots_cle = Array();
 
foreach($lignes as $ligne) {
// dans le cas de fgetcsv, on peut avoir des false additionnel (cf do/while l. 279)
if($ligne === false) continue;
 
//$ligne = array_filter($ligne, function($cell) { return !is_null($cell); });
//if(!$ligne) continue;
// on a besoin des NULL pour éviter des notice d'index indéfini
if(! array_filter($ligne, '__anonyme_3')) continue;
 
if( ($enregistrement = self::chargerLigne($ligne, $dernier_ordre, $cel)) ) {
// $enregistrements[] = array_merge($colonnes_statiques, $enregistrement);
$enregistrements[] = $enregistrement;
$pos = count($enregistrements) - 1;
$last = &$enregistrements[$pos];
 
if(isset($enregistrement['_images'])) {
// ne dépend pas de cel_obs, et seront insérées *après* les enregistrements
// mais nous ne voulons pas nous priver de faire des INSERT multiples pour autant
$toutes_images[] = Array("images" => $last['_images'],
"obs_pos" => $pos);
// ce champ n'a pas à faire partie de l'insertion dans cel_obs,
// mais est utile pour cel_obs_images
unset($last['_images']);
}
 
if(isset($enregistrement['_mots_cle'])) {
// ne dépend pas de cel_obs, et seront insérés *après* les enregistrements
// mais nous ne voulons pas nous priver de faire des INSERT multiples pour autant
$tous_mots_cle[] = Array("mots_cle" => $last['_mots_cle'],
"obs_pos" => $pos);
// la version inlinée des mots est enregistrées dans cel_obs
// mais cel_mots_cles_obs fait foi.
// XXX: postponer l'ajout de ces informations dans cel_obs *après* l'insertion effective
// des records dans cel_mots_cles_obs ?
unset($last['_mots_cle']);
}
 
$dernier_ordre++;
}
}
 
// XXX future: return Array($enregistrements_a_inserer, $enregistrements_a_MAJ, $toutes_images);
return Array($enregistrements, $toutes_images, $tous_mots_cle);
}
 
 
static function trierColonnes(&$enregistrements) {
foreach($enregistrements as &$enregistrement) {
$enregistrement = self::sortArrayByArray($enregistrement, self::$ordre_BDD);
//array_walk($enregistrement, function(&$item, $k) { $item = is_null($item) ? "NULL" : $item; });
//$req .= implode(', ', $enregistrement) . "\n";
}
}
 
 
static function stockerMotsCle($enregistrements, $tous_mots_cle, $lastid) {
$c = 0;
// debug: var_dump($tous_mots_cle);die;
foreach($tous_mots_cle as $v) $c += count($v['mots_cle']['to_insert']);
return $c;
}
 
static function stockerImages($enregistrements, $toutes_images, $ordre_ids) {
$images_insert = 'INSERT INTO cel_obs_images (id_image, id_observation) VALUES %s ON DUPLICATE KEY UPDATE id_image = id_image';
$images_obs_assoc = Array();
 
foreach($toutes_images as $images_pour_obs) {
$obs = $enregistrements[$images_pour_obs["obs_pos"]];
$id_obs = $ordre_ids[$obs['ordre']]; // id réel de l'observation correspondant à l'ordre
foreach($images_pour_obs['images'] as $image) {
$images_obs_assoc[] = sprintf('(%d,%d)',
$image['id_image'], // intval() useless
$id_obs); // intval() useless
}
}
 
if($images_obs_assoc) {
$requete = sprintf($images_insert, implode(', ', $images_obs_assoc));
// debug echo "$requete\n";
Cel::db()->requeter($requete);
}
 
return count($images_obs_assoc);
}
 
/*
Aucune des valeurs présentes dans $enregistrement n'est quotée
cad aucune des valeurs retournée par traiter{Espece|Localisation}()
car ce tableau est passé à un PDO::preparedStatement() qui applique
proprement les règle d'échappement.
*/
static function chargerLigne($ligne, $dernier_ordre, $cel) {
// évite des notices d'index lors des trigger_error()
$ref_ligne = !empty($ligne[C_NOM_SEL]) ? trim($ligne[C_NOM_SEL]) : '';
 
// en premier car le résultat est utile pour
// * traiter espèce (traiterEspece())
// * traiter longitude et latitude (traiterLonLat())
$referentiel = self::identReferentiel(trim(strtolower(@$ligne[C_NOM_REFERENTIEL])), $ligne, $ref_ligne);
 
// $espece est rempli de plusieurs informations
$espece = Array(C_NOM_SEL => NULL, C_NOM_SEL_NN => NULL, C_NOM_RET => NULL,
C_NOM_RET_NN => NULL, C_NT => NULL, C_FAMILLE => NULL);
self::traiterEspece($ligne, $espece, $referentiel, $cel->taxon_info_webservice);
 
if(!$espece[C_NOM_SEL]) $referentiel = Cel::$fallback_referentiel;
if($espece[C_NOM_SEL] && !$espece[C_NOM_SEL_NN]) $referentiel = Cel::$fallback_referentiel;
 
// $localisation est rempli à partir de plusieurs champs: C_ZONE_GEO et C_CE_ZONE_GEO
$localisation = Array(C_ZONE_GEO => NULL, C_CE_ZONE_GEO => NULL);
self::traiterLocalisation($ligne, $localisation);
 
// $transmission est utilisé pour date_transmission
// XXX: @ contre "Undefined index"
@$transmission = in_array(strtolower(trim($ligne[C_TRANSMISSION])), array(1, 'oui')) ? 1 : 0;
 
 
// Dans ce tableau, seules devraient apparaître les données variable pour chaque ligne.
// Dans ce tableau, l'ordre des clefs n'importe pas (cf: self::sortArrayByArray())
$enregistrement = Array(
"ordre" => $dernier_ordre,
 
"nom_sel" => $espece[C_NOM_SEL],
"nom_sel_nn" => $espece[C_NOM_SEL_NN],
"nom_ret" => $espece[C_NOM_RET],
"nom_ret_nn" => $espece[C_NOM_RET_NN],
"nt" => $espece[C_NT],
"famille" => $espece[C_FAMILLE],
 
"nom_referentiel" => $referentiel,
 
"zone_geo" => $localisation[C_ZONE_GEO],
"ce_zone_geo" => $localisation[C_CE_ZONE_GEO],
 
// $ligne: uniquement pour les infos en cas de gestion d'erreurs (date incompréhensible)
"date_observation" => isset($ligne[C_DATE_OBSERVATION]) ? self::traiterDateObs($ligne[C_DATE_OBSERVATION], $ref_ligne) : NULL,
 
"lieudit" => isset($ligne[C_LIEUDIT]) ? trim($ligne[C_LIEUDIT]) : NULL,
"station" => isset($ligne[C_STATION]) ? trim($ligne[C_STATION]) : NULL,
"milieu" => isset($ligne[C_MILIEU]) ? trim($ligne[C_MILIEU]) : NULL,
 
"mots_cles_texte" => NULL, // TODO: foreign-key
// XXX: @ contre "Undefined index"
"commentaire" => isset($ligne[C_COMMENTAIRE]) ? trim($ligne[C_COMMENTAIRE]) : NULL,
 
"transmission" => $transmission,
"date_transmission" => $transmission ? date("Y-m-d H:i:s") : NULL, // pas de fonction SQL dans un PDO statement, <=> now()
 
// $ligne: uniquement pour les infos en cas de gestion d'erreurs (lon/lat incompréhensible)
"latitude" => isset($ligne[C_LATITUDE]) ? self::traiterLonLat(NULL, $ligne[C_LATITUDE], $referentiel, $ref_ligne) : NULL,
"longitude" => isset($ligne[C_LONGITUDE]) ? self::traiterLonLat($ligne[C_LONGITUDE], NULL, $referentiel, $ref_ligne) : NULL,
"altitude" => isset($ligne[C_ALTITUDE]) ? intval($ligne[C_ALTITUDE]) : NULL, // TODO: guess alt from lon/lat
 
// @ car potentiellement optionnelles ou toutes vides => pas d'index dans PHPExcel (tableau optimisé)
"abondance" => @$ligne[C_ABONDANCE],
"certitude" => @$ligne[C_CERTITUDE],
"phenologie" => @$ligne[C_PHENOLOGIE],
 
"code_insee_calcule" => substr($localisation[C_CE_ZONE_GEO], -5) // varchar(5)
);
 
// passage de $enregistrement par référence, ainsi ['_images'] n'est défini
// que si des résultats sont trouvés
// "@" car PHPExcel supprime les colonnes null sur toute la feuille (ou tout le chunk)
if(@$ligne[C_IMAGES]) self::traiterImage($ligne[C_IMAGES], $cel->id_utilisateur, $enregistrement);
 
if(@$ligne[C_MOTS_CLES_TEXTE]) self::traiterMotsCle($ligne[C_MOTS_CLES_TEXTE], $cel->id_utilisateur, $enregistrement);
 
return $enregistrement;
}
 
static function traiterImage($str, $id_utilisateur, &$enregistrement) {
$liste_images = array_filter(explode("/", $str));
 
//array_walk($liste_images, '__anonyme_4');
array_walk($liste_images, array(__CLASS__, '__anonyme_4'));
$requete = sprintf(
"SELECT id_image, nom_original FROM cel_images WHERE ce_utilisateur = %d AND nom_original IN (%s)",
$id_utilisateur,
implode(',', $liste_images));
 
$resultat = Cel::db()->requeter($requete);
 
if($resultat) $enregistrement['_images'] = $resultat;
}
 
static function traiterMotsCle($str, $id_utilisateur, &$enregistrement) {
$liste_mots_cle = $liste_mots_cle_recherche = array_map("trim", array_unique(array_filter(explode(",", $str))));
array_walk($liste_mots_cle_recherche, array(__CLASS__, '__anonyme_4'));
 
if(self::$gestion_mots_cles == null) {
$gestion_mots_cles = new GestionMotsCles($this->config, 'obs');
}
$mots_cles_ids = $gestion_mots_cles->obtenirIdsMotClesPourMotsCles($liste_mots_cle, $id_utilisateur);
foreach($mots_cles_ids as $mot_cle) {
$resultat[$mot_cle['id_mot_cle']] = $mot_cle['mot_cle'];
}
 
$enregistrement['mots_cles_texte'] = implode(',', $liste_mots_cle);
$enregistrement['_mots_cle'] = array("existing" => $resultat,
"to_insert" => array_diff($liste_mots_cle, $resultat));
}
 
 
/* FONCTIONS de TRANSFORMATION de VALEUR DE CELLULE */
 
// TODO: PHP 5.3, utiliser date_parse_from_format()
// TODO: parser les heures (cf product-owner)
// TODO: passer par le timestamp pour s'assurer de la validité
static function traiterDateObs($date, $ref_ligne) {
// TODO: see https://github.com/PHPOffice/PHPExcel/issues/208
// TODO: PHPExcel_Shared_Date::ExcelToPHP()
if(is_double($date)) {
if($date > 0)
return PHPExcel_Style_NumberFormat::toFormattedString($date, PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2) . " 00:00:00";
trigger_error("ligne \"{$ref_ligne}\": " .
"Attention: date antérieure à 1970 et format de cellule \"DATE\" utilisés ensemble",
E_USER_NOTICE);
 
// throw new Exception("erreur: date antérieure à 1970 et format de cellule \"DATE\" utilisés ensemble");
 
// attention, UNIX timestamp, car Excel les décompte depuis 1900
// cf http://fczaja.blogspot.fr/2011/06/convert-excel-date-into-timestamp.html
// $timestamp = ($date - MIN_DATES_DIFF) * 60 * 60 * 24 - time(); // NON
 
// $timestamp = PHPExcel_Calculation::getInstance()->calculateFormula("=" . $date . "-DATE(1970,1,1)*60*60*24"); // NON
 
// echo strftime("%Y/%m/%d 00:00:00", $timestamp); // NON
}
else {
// attend l'un des formats de
// http://www.php.net/manual/fr/datetime.formats.date.php
// le plus simple: YYYY/MM/DD (utilisé à l'export), mais DD-MM-YYYY est aussi supporté
$matches = NULL;
// et on essaie d'être sympa et supporter aussi DD/MM/YYYY
if(preg_match(';^([0-3]?\d)/([01]\d)/([12]\d\d\d)$;', $date, $matches)) {
$date = $matches[3] . '/' . $matches[2] . '/' . $matches[1];
}
$timestamp = strtotime($date);
if(! $timestamp || $timestamp > time() + 3600 * 24 * 1) { // une journée d'avance maxi autorisée (décallage horaire ?)
if($date) trigger_error("ligne \"{$ref_ligne}\": Attention: date erronée ($date)", E_USER_NOTICE);
return NULL;
}
return strftime("%Y-%m-%d 00:00:00", $timestamp);
}
}
 
static function identReferentiel($referentiel, $ligne, $ref_ligne) {
// SELECT DISTINCT nom_referentiel, COUNT(id_observation) AS count FROM cel_obs GROUP BY nom_referentiel ORDER BY count DESC;
if(strpos($referentiel, 'bdtfx') !== FALSE) return 'bdtfx'; //:v1.01';
if(strpos($referentiel, 'bdtxa') !== FALSE) return 'bdtxa'; //:v1.00';
//if(strpos($referentiel, 'bdnff') !== FALSE) return 'bdnff'; //:4.02';
if(strpos($referentiel, 'bdnff') !== FALSE) return 'bdtfx';
if(strpos($referentiel, 'isfan') !== FALSE) return 'isfan'; //:v1.00';
if(strpos($referentiel, 'apd') !== FALSE) return 'apd'; //:v1.00';
if(strpos($referentiel, 'autre') !== FALSE) return 'autre';
 
if($referentiel && isset($ligne[C_NOM_SEL]) && $ligne[C_NOM_SEL]) {
trigger_error("ligne \"{$ref_ligne}\": Attention: référentiel \"{$referentiel}\" inconnu", E_USER_NOTICE);
return 'autre';
}
 
// pas de référentiel ou pas de NOM_SEL: NULL
return NULL;
/* TODO: cf story,
En cas de NULL faire une seconde passe de détection à partir du nom saisi
+ accepter les n° de version */
}
 
static function traiterLonLat($lon = NULL, $lat = NULL, $referentiel = 'bdtfx', $ref_ligne) {
// en CSV ces valeurs sont des string, avec séparateur en français (","; cf défauts dans ExportXLS)
if($lon && is_string($lon)) $lon = str_replace(',', '.', $lon);
if($lat && is_string($lat)) $lat = str_replace(',', '.', $lat);
 
// sprintf applique une précision à 5 décimale (comme le ferait MySQL)
// tout en uniformisant le format de séparateur des décimales (le ".")
if($lon && is_numeric($lon) && $lon >= -180 && $lon <= 180) return sprintf('%.5F', $lon);
if($lat && is_numeric($lat) && $lat >= -90 && $lat <= 90) return sprintf('%.5F', $lat);
 
if($lon || $lat) {
trigger_error("ligne \"{$ref_ligne}\": " .
"Attention: longitude ou latitude erronée",
E_USER_NOTICE);
}
return NULL;
 
/* limite france métropole si bdtfx ? ou bdtxa ? ...
NON!
Un taxon d'un référentiel donné peut être théoriquement observé n'importe où sur le globe.
Il n'y a pas lieu d'effectuer des restriction ici.
Cependant des erreurs fréquentes (0,0 ou lon/lat inversées) peuvent être détectés ici.
TODO */
$bbox = self::getReferentielBBox($referentiel);
if(!$bbox) return NULL;
 
if($lon) {
if($lon < $bbox['EST'] && $lon > $bbox['OUEST']) return is_numeric($lon) ? $lon : NULL;
else return NULL;
}
if($lat) {
if($lat < $bbox['NORD'] && $lat > $bbox['SUD']) return is_numeric($lat) ? $lat : NULL;
return NULL;
}
}
 
/*
TODO: s'affranchir du webservice pour la détermination du nom scientifique en s'appuyant sur cel_references,
pour des questions de performances
*/
static function traiterEspece($ligne, Array &$espece, &$referentiel, $taxon_info_webservice) {
if(empty($ligne[C_NOM_SEL])) {
// TODO: nous ne déclarons pas "Numéro nomenclatural" comme colonne importable
// Nous ne pouvons donc pas tenter d'être sympa sur la détermination par num_nom
/* if(!empty($ligne[C_NOM_SEL_NN]) && $referentiel != Cel::$fallback_referentiel)
$ligne[C_NOM_SEL] = $referentiel . ':nn:' . $ligne[C_NOM_SEL_NN];
else */
return;
}
 
// nom_sel reste toujours celui de l'utilisateur
$espece[C_NOM_SEL] = trim($ligne[C_NOM_SEL]);
 
// XXX/attention, nous ne devrions pas accepter un référentiel absent !
if(!$referentiel) $referentiel = 'bdtfx';
$taxon_info_webservice->setReferentiel($referentiel);
$ascii = iconv('UTF-8', 'ASCII//TRANSLIT', $ligne[C_NOM_SEL]);
 
// TODO: si empty(C_NOM_SEL) et !empty(C_NOM_SEL_NN) : recherche info à partir de C_NOM_SEL_NN
// echo "rechercherInformationsComplementairesSurNom()\n";
/*
SELECT num_nom, nom_sci, num_nom_retenu ,auteur, annee, biblio_origine, nom_sci,auteur FROM bdtfx_v1_01 WHERE (nom_sci LIKE 'Heliotropium europaeum') ORDER BY nom_sci ASC LIMIT 0, 1
#
SELECT num_nom, nom_sci, num_nom_retenu ,auteur, annee, biblio_origine, nom_sci,auteur FROM bdtfx_v1_01 WHERE (nom_sci LIKE 'eliotropium euro') ORDER BY nom_sci ASC LIMIT 0, 1
SELECT num_nom, nom_sci, num_nom_retenu ,auteur, annee, biblio_origine, nom_sci,auteur FROM bdtfx_v1_01 WHERE (nom_sci LIKE 'eliotropium') ORDER BY nom_sci ASC LIMIT 0, 1
SELECT num_nom, nom_sci, num_nom_retenu ,auteur, annee, biblio_origine, nom_sci,auteur FROM bdtfx_v1_01 WHERE (nom_sci LIKE 'eliotropium% euro%') ORDER BY nom_sci ASC LIMIT 0, 1
#
 
SELECT nom_sci, num_nom_retenu, nom_sci_html, auteur, annee, biblio_origine FROM bdtfx_v1_01 WHERE num_nom = 31468
*/
// $determ = $taxon_info_webservice->rechercherInformationsComplementairesSurNom($ligne[C_NOM_SEL]);
// permet une reconnaissance de bdtfx:nn:XXXX
$determ = $taxon_info_webservice->rechercherInfosSurTexteCodeOuNumTax(trim($ligne[C_NOM_SEL]));
 
// note: rechercherInfosSurTexteCodeOuNumTax peut ne retourner qu'une seule clef "nom_sel"
if (! $determ) {
// on supprime les noms retenus et renvoi tel quel
// on réutilise les define pour les noms d'indexes, tant qu'à faire
// XXX; tout à NULL sauf C_NOM_SEL ci-dessus ?
$espece[C_NOM_SEL_NN] = @$ligne[C_NOM_SEL_NN];
$espece[C_NOM_RET] = @$ligne[C_NOM_RET];
$espece[C_NOM_RET_NN] = @$ligne[C_NOM_RET_NN];
$espece[C_NT] = @$ligne[C_NT];
$espece[C_FAMILLE] = @$ligne[C_FAMILLE];
 
return;
}
 
// succès de la détection, mais résultat partiel
if(!isset($determ->id))
$determ = $taxon_info_webservice->effectuerRequeteInfosComplementairesSurNumNom($determ->{"nom_retenu.id"});
 
// ne devrait jamais arriver !
if(!$determ) die("erreur critique: " . __FILE__ . ':' . __LINE__);
 
// un schéma <ref>:(nt|nn):<num> (ie: bdtfx:nt:8503) a été passé
// dans ce cas on met à jour le référentiel avec celui passé dans le champ espèce
if(isset($determ->ref)) {
$referentiel = $determ->ref;
}
 
// succès de la détection
// nom_sel est remplacé, mais seulement si un motif spécial à été utilisé (bdtfx:nn:4567)
if($taxon_info_webservice->is_notation_spe) {
$espece[C_NOM_SEL] = $determ->nom_sci;
}
 
// écrasement des numéros (nomenclatural, taxonomique) saisis...
$espece[C_NOM_SEL_NN] = $determ->id;
$espece[C_NOM_RET] = RechercheInfosTaxonBeta::supprimerBiblio($determ->nom_retenu_complet);
$espece[C_NOM_RET_NN] = $determ->{"nom_retenu.id"};
$espece[C_NT] = $determ->num_taxonomique;
$espece[C_FAMILLE] = $determ->famille;
return;
// et des info complémentaires
 
/*
// GET /service:eflore:0.1/bdtfx/noms/31468?retour.champs=nom_sci,auteur,id,nom_retenu_complet,nom_retenu.id,num_taxonomique,famille
/home/raphael/eflore/projets/services/modules/0.1/bdtfx/Noms.php:280
SELECT *, nom_sci FROM bdtfx_v1_01 WHERE num_nom = '31468'
SELECT nom_sci, num_nom_retenu, nom_sci_html, auteur, annee, biblio_origine FROM bdtfx_v1_01 WHERE num_nom = 31468
SELECT nom_sci, num_nom_retenu, nom_sci_html, auteur, annee, biblio_origine FROM bdtfx_v1_01 WHERE num_nom = 86535
*/
 
 
//var_dump($complement, $espece);die;
}
 
static function detectFromNom($nom) {
$r = Cel::db()->requeter(sprintf("SELECT num_nom, num_tax_sup FROM bdtfx_v1_01 WHERE (nom_sci LIKE '%s') ".
"ORDER BY nom_sci ASC LIMIT 0, 1",
Cel::db()->proteger($nom)));
if($r) return $r;
 
Cel::db()->requeter(sprintf("SELECT num_nom, num_tax_sup FROM bdtfx_v1_01 WHERE (nom_sci LIKE '%s' OR nom LIKE '%s') ".
"ORDER BY nom_sci ASC LIMIT 0, 1",
Cel::db()->proteger($nom),
Cel::db()->proteger(str_replace(' ', '% ', $nom))));
return $r;
}
 
 
/*
* TODO: analyse rigoureuse:
* == Identifiant Commune
* - INSEE-C:\d{5}
* - \d{5}
* - \d{2}
* == Commune
* - \w+ (\d{2})
* - \w+ (\d{5})
* - \w+
*
*/
static function traiterLocalisation($ligne, Array &$localisation) {
if(empty($ligne[C_ZONE_GEO])) $ligne[C_ZONE_GEO] = NULL;
if(empty($ligne[C_CE_ZONE_GEO])) $ligne[C_CE_ZONE_GEO] = NULL;
 
$identifiant_commune = trim($ligne[C_ZONE_GEO]);
if(!$identifiant_commune) {
$departement = trim($ligne[C_CE_ZONE_GEO]);
 
if(strpos($departement, "INSEE-C:", 0) === 0) {
$localisation[C_CE_ZONE_GEO] = trim($ligne[C_CE_ZONE_GEO]);
if(array_key_exists($localisation[C_CE_ZONE_GEO], self::$cache['geo'])) {
$localisation[C_ZONE_GEO] = self::$cache['geo'][$localisation[C_CE_ZONE_GEO]];
}
else {
$nom = Cel::db()->requeter(sprintf("SELECT nom FROM cel_zones_geo WHERE code = %s LIMIT 1",
self::quoteNonNull(substr($localisation[C_CE_ZONE_GEO], strlen("INSEE-C:")))));
if($nom) $localisation[C_ZONE_GEO] = $nom[0]['nom'];
self::$cache['geo'][$localisation[C_CE_ZONE_GEO]] = @$nom[0]['nom'];
}
return;
}
 
if(!is_numeric($departement)) {
$localisation[C_CE_ZONE_GEO] = $ligne[C_CE_ZONE_GEO];
return;
}
 
$cache_attempted = FALSE;
if(array_key_exists($departement, self::$cache['geo'])) {
$cache_attempted = TRUE;
if(self::$cache['geo'][$departement][0] && self::$cache['geo'][$departement][1]) {
$localisation[C_ZONE_GEO] = self::$cache['geo'][$departement][0];
$localisation[C_CE_ZONE_GEO] = self::$cache['geo'][$departement][1];
return;
}
}
 
if(! $cache_attempted && ($resultat_commune = Cel::db()->requeter(sprintf("SELECT DISTINCT nom, CONCAT('INSEE-C:', code) AS code FROM cel_zones_geo WHERE code = %s LIMIT 1",
self::quoteNonNull($departement)))) ) {
$localisation[C_ZONE_GEO] = $resultat_commune[0]['nom'];
$localisation[C_CE_ZONE_GEO] = $resultat_commune[0]['code'];
self::$cache['geo'][$departement] = array($resultat_commune[0]['nom'], $resultat_commune[0]['code']);
return;
}
;
// if(strlen($departement) == 4) $departement = "INSEE-C:0" . $departement;
// if(strlen($departement) == 5) $departement = "INSEE-C:" . $departement;
// if(strlen($departement) <= 9) return "INSEE-C:0" . $departement; // ? ... TODO
 
$departement = trim($departement); // TODO
 
$localisation[C_CE_ZONE_GEO] = $ligne[C_CE_ZONE_GEO];
return;
}
 
 
$select = "SELECT DISTINCT nom, code FROM cel_zones_geo";
if (preg_match('/(.+) \((\d{1,5})\)/', $identifiant_commune, $elements)) {
// commune + departement : montpellier (34)
$nom_commune=$elements[1];
$code_commune=$elements[2];
if(strlen($code_commune) <= 2) {
$requete = sprintf("%s WHERE nom = %s AND code LIKE %s",
$select, self::quoteNonNull($nom_commune),
self::quoteNonNull($code_commune.'%'));
}
else {
$requete = sprintf("%s WHERE nom = %s AND code = %d",
$select, self::quoteNonNull($nom_commune),
$code_commune);
}
}
elseif (preg_match('/^(\d+|(2[ab]\d+))$/i', $identifiant_commune, $elements)) {
// Code insee seul
$code_insee_commune=$elements[1];
$requete = sprintf("%s WHERE code = %s", $select, self::quoteNonNull($code_insee_commune));
}
else {
// Commune seule (le departement sera recupere dans la colonne departement si elle est presente)
// on prend le risque ici de retourner une mauvaise Commune
$nom_commune = str_replace(" ", "%", iconv('UTF-8', 'ASCII//TRANSLIT', $identifiant_commune));
$requete = sprintf("%s WHERE nom LIKE %s", $select, self::quoteNonNull($nom_commune.'%'));
}
 
 
if(array_key_exists($identifiant_commune, self::$cache['geo'])) {
$resultat_commune = self::$cache['geo'][$identifiant_commune];
}
else {
$resultat_commune = Cel::db()->requeter($requete);
self::$cache['geo'][$identifiant_commune] = $resultat_commune;
}
// TODO: levenstein sort ?
// TODO: count résultat !
 
// cas de la commune introuvable dans le référentiel
// réinitialisation aux valeurs du fichier XLS
if(! $resultat_commune) {
$localisation[C_ZONE_GEO] = trim($ligne[C_ZONE_GEO]);
$localisation[C_CE_ZONE_GEO] = trim($ligne[C_CE_ZONE_GEO]);
} else {
$localisation[C_ZONE_GEO] = $resultat_commune[0]['nom'];
$localisation[C_CE_ZONE_GEO] = "INSEE-C:" . $resultat_commune[0]['code'];
return;
}
 
$departement = &$localisation[C_CE_ZONE_GEO];
 
if(strpos($departement, "INSEE-C:", 0) === 0) {
$localisation[C_ZONE_GEO] = $localisation[C_ZONE_GEO];
$localisation[C_CE_ZONE_GEO] = $localisation[C_CE_ZONE_GEO];
}
 
 
if(!is_numeric($departement)) {
$localisation[C_ZONE_GEO] = $localisation[C_ZONE_GEO];
$localisation[C_CE_ZONE_GEO] = $localisation[C_CE_ZONE_GEO];
}
 
if(strlen($departement) == 4) $departement = "INSEE-C:0" . $departement;
if(strlen($departement) == 5) $departement = "INSEE-C:" . $departement;
// if(strlen($departement) <= 9) return "INSEE-C:0" . $departement; // ? ... TODO
 
$departement = trim($departement); // TODO
 
$localisation[C_ZONE_GEO] = $localisation[C_ZONE_GEO];
$localisation[C_CE_ZONE_GEO] = $localisation[C_CE_ZONE_GEO];
}
 
/*
static function traiterLocalisation($ligne, Array &$localisation) {
$identifiant_commune = trim($ligne[C_ZONE_GEO]);
if(!$identifiant_commune) {
$departement = trim($ligne[C_CE_ZONE_GEO]);
goto testdepartement;
}
 
 
$select = "SELECT DISTINCT nom, code FROM cel_zones_geo";
if (preg_match('/(.*) \((\d+)\)/', $identifiant_commune, $elements)) {
// commune + departement : montpellier (34)
$nom_commune=$elements[1];
$code_commune=$elements[2];
$requete = sprintf("%s WHERE nom = %s AND code LIKE %s",
$select, self::quoteNonNull($nom_commune), self::quoteNonNull($code_commune.'%'));
}
elseif (preg_match('/^(\d+|(2[ab]\d+))$/i', $identifiant_commune, $elements)) {
// Code insee seul
$code_insee_commune=$elements[1];
$requete = sprintf("%s WHERE code = %s", $select, self::quoteNonNull($code_insee_commune));
}
else {
// Commune seule (le departement sera recupere dans la colonne departement si elle est presente)
// on prend le risque ici de retourner une mauvaise Commune
$nom_commune = str_replace(" ", "%", iconv('UTF-8', 'ASCII//TRANSLIT', $identifiant_commune));
$requete = sprintf("%s WHERE nom LIKE %s", $select, self::quoteNonNull($nom_commune.'%'));
}
$resultat_commune = Cel::db()->requeter($requete);
// TODO: levenstein sort ?
 
// cas de la commune introuvable dans le référentiel
// réinitialisation aux valeurs du fichier XLS
if(! $resultat_commune) {
$localisation[C_ZONE_GEO] = trim($ligne[C_ZONE_GEO]);
$localisation[C_CE_ZONE_GEO] = trim($ligne[C_CE_ZONE_GEO]);
} else {
$localisation[C_ZONE_GEO] = $resultat_commune[0]['nom'];
$localisation[C_CE_ZONE_GEO] = $resultat_commune[0]['code'];
}
 
$departement = &$localisation[C_CE_ZONE_GEO];
 
testdepartement:
if(strpos($departement, "INSEE-C:", 0) === 0) goto protectloc;
 
if(!is_numeric($departement)) goto protectloc; // TODO ?
if(strlen($departement) == 4) $departement = "INSEE-C:0" . $departement;
if(strlen($departement) == 5) $departement = "INSEE-C:" . $departement;
// if(strlen($departement) <= 9) return "INSEE-C:0" . $departement; // ? ... TODO
 
$departement = trim($departement); // TODO
 
protectloc:
$localisation[C_ZONE_GEO] = $localisation[C_ZONE_GEO];
$localisation[C_CE_ZONE_GEO] = $localisation[C_CE_ZONE_GEO];
}
*/
 
 
/* HELPERS */
 
// http://stackoverflow.com/questions/348410/sort-an-array-based-on-another-array
// XXX; utilisé aussi (temporairement ?) par FormateurGroupeColonne.
static function sortArrayByArray($array, $orderArray) {
$ordered = array();
foreach($orderArray as $key) {
if(array_key_exists($key, $array)) {
$ordered[$key] = $array[$key];
unset($array[$key]);
}
}
return $ordered + $array;
}
 
// retourne une BBox [N,S,E,O) pour un référentiel donné
static function getReferentielBBox($referentiel) {
if($referentiel == 'bdtfx') return Array(
'NORD' => 51.2, // Dunkerque
'SUD' => 41.3, // Bonifacio
'EST' => 9.7, // Corse
'OUEST' => -5.2); // Ouessan
return FALSE;
}
 
// ces valeurs ne sont pas inséré via les placeholders du PDO::preparedStatement
// et doivent donc être échappées correctement.
public function initialiser_colonnes_statiques() {
$this->colonnes_statiques = array_merge($this->colonnes_statiques,
Array(
"ce_utilisateur" => self::quoteNonNull($this->id_utilisateur), // peut-être un hash ou un id
"prenom_utilisateur" => self::quoteNonNull($this->utilisateur['prenom']),
"nom_utilisateur" => self::quoteNonNull($this->utilisateur['nom']),
"courriel_utilisateur" => self::quoteNonNull($this->utilisateur['courriel']),
));
 
}
 
static function initialiser_pdo_ordered_statements($colonnes_statiques) {
return Array(
// insert_ligne_pattern_ordre
sprintf('INSERT INTO cel_obs (%s, %s) VALUES',
implode(', ', array_keys($colonnes_statiques)),
implode(', ', array_diff(self::$ordre_BDD, array_keys($colonnes_statiques)))),
 
// insert_ligne_pattern_ordre
sprintf('(%s, %s ?)',
implode(', ', $colonnes_statiques),
str_repeat('?, ', count(self::$ordre_BDD) - count($colonnes_statiques) - 1))
);
}
 
static function initialiser_pdo_statements($colonnes_statiques) {
return Array(
// insert_prefix
sprintf('INSERT INTO cel_obs (%s) VALUES ',
implode(', ', self::$ordre_BDD)),
 
 
// insert_ligne_pattern, cf: self::$insert_ligne_pattern
'(' .
// 3) créé une chaîne de liste de champ à inséré en DB
implode(', ', array_values(
// 2) garde les valeurs fixes (de $colonnes_statiques),
// mais remplace les NULL par des "?"
array_map('__anonyme_5',
// 1) créé un tableau genre (nom_sel_nn => NULL) depuis self::$ordre_BDD
// et écrase certaines valeurs avec $colonnes_statiques (initilisé avec les données utilisateur)
array_merge(array_map('__anonyme_6', array_flip(self::$ordre_BDD)), $colonnes_statiques
)))) .
')'
);
}
 
// équivalent à Bdd2->proteger() (qui wrap PDO::quote),
// sans transformer NULL en ""
static function quoteNonNull($chaine) {
if(is_null($chaine)) return "NULL";
if(!is_string($chaine) && !is_integer($chaine)) {
die("erreur: " . __FILE__ . ':' . __LINE__);
}
return Cel::db()->quote($chaine);
}
 
public function erreurs_stock($errno, $errstr) {
$this->bilan[] = $errstr;
}
}
/branches/v2.3-faux/jrest/services/CelStatistique.php
New file
0,0 → 1,968
<?php
/**
* Service fournissant des urls vers des images de graphiques sur les statistiques de l'application CEL.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* Cas d'utilisation :
* /CelStatistique/TypeDeGraph : retourne le graphique demandé
* Paramêtres :
* serveur=[0-9] : retourne le graphique demandé sur le serveur numéro 0 à 9 (voir http://code.google.com/intl/fr/apis/chart/docs/making_charts.html#enhancements )
*
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright 2009
*/
class CelStatistique extends Cel {
 
/**
* Méthode appelée avec une requête de type GET.
*/
public function getElement($param) {
$graph = null;
$serveur = '';
 
if (isset($param[0])) {
$graph_demande = array_shift($param);
$methode = 'get'.$graph_demande;
if (method_exists($this, $methode)) {
$graph = $this->$methode($param);
} else {
$this->messages[] = "Ce type de graphique '$graph_demande' n'est pas disponible.";
}
} else {
$this->messages[] = "Le premier paramêtre du service CEL Statistique doit correspondre au type de graphique.";
}
 
if (!is_null($graph)) {
$serveur = (isset($_GET['serveur']) && preg_match('/^[0-9]$/', $_GET['serveur'])) ? $_GET['serveur'].'.' : '';
$url = "http://{$serveur}chart.apis.google.com/chart";
$contexte = stream_context_create(
array('http' => array(
'method' => 'POST',
'content' => http_build_query($graph),
'header' => 'Content-Type: application/x-www-form-urlencoded')));
$image = file_get_contents($url, false, $contexte);
$this->envoyer($image, 'image/png', null, false);
} else {
$info = 'Un problème est survenu : '.print_r($this->messages, true);
$this->envoyer($info);
}
}
 
private function getEvolImgLieesParMois($param) {
$utilisateur = isset($_GET['utilisateur']) ? Cel::db()->quote($_GET['utilisateur']) : null;
 
// Récupération des données
$requete = "SELECT DATE_FORMAT(date_creation, '%Y%m') AS periode, COUNT(ci.id_image) AS nbre ".
"FROM cel_obs_images coi LEFT JOIN cel_images ci ON (coi.id_image = ci.id_image) ".
"WHERE date_creation != '0000-00-00 00:00:00' ".
((isset($utilisateur)) ? " AND courriel_utilisateur = $utilisateur " : '').
'GROUP BY periode '.
'ORDER BY periode ';
 
$resulats = Cel::db()->requeter($requete);
 
$img_totale = array();
foreach ($resulats as $info) {
$img_totale[$info['periode']] = $info['nbre'];
}
 
// Trie des dates pour les étiquettes des axes
$dates = array();
$annees = array();
$les_mois = array();
$pas = 1; // intervalle de mois entre deux étiquettes
$periode = 0;
$cumul = 0;
$img_totale_cumul = array();
foreach ($img_totale as $annee_mois => $nbre) {
$annee = substr($annee_mois, 0, 4);
$mois = substr($annee_mois, 4, 2);
$mois_fmt_B = strftime('%b', strtotime("0000-$mois-01"));
$cumul += $nbre;
$img_totale_cumul[$annee_mois] = $cumul;
 
if (!isset($dates[$annee][$mois])) {
$annees[] = (!isset($dates[$annee]) ? $annee : '');
$les_mois[] = is_int($periode++ / $pas) ? $mois_fmt_B : '';
// Ajouter au tableau dates tjrs à la fin
$dates[$annee][$mois] = 1;
}
}
 
// Post traitement des données
$titre = "Évolution des images liées aux observations par mois";
$valeurs_y = implode(',', $img_totale);
$valeurs_r = implode(',', $img_totale_cumul);
$valeurs_max_y = max($img_totale);
$valeurs_max_r = max($img_totale_cumul);
$y_val_fin = $valeurs_max_y;
$y_pas = 200;
$r_val_fin = $valeurs_max_r;
$r_pas = 1000;
$etiquettes_x1 = implode('|', $les_mois);
$etiquettes_x2 = implode('|', $annees);
$etiquettes_y = 'Images';
 
// Construire de l'url de l'image
$graph = array('cht' => 'lc',
'chtt' => $titre,
'chs' => '600x200',
'chco' => '007F00,99CC00',
'chd' => 't:'.$valeurs_y.'|'.$valeurs_r,
'chds' => "0,$valeurs_max_y,0,$valeurs_max_r",
'chxt' => 'y,y,x,x,r',
'chxl' => '1:|'.$etiquettes_y.'|3:|'.$etiquettes_x2.'|2:|'.$etiquettes_x1.'',
'chxp' => '1,50|3,0',
'chxr' => "0,0,$y_val_fin,$y_pas|4,0,$r_val_fin,$r_pas",
'chm' => 'N ** ,000000,0,-1,8,1.0,ht',
'chxs' => '0,007F00|4,99CC00');
return $graph;
}
 
private function getEvolImgParMois($param) {
$utilisateur = isset($_GET['utilisateur']) ? Cel::db()->quote($_GET['utilisateur']) : null;
 
// Récupération des données
$requete = "SELECT DATE_FORMAT(date_creation, '%Y%m') AS periode, COUNT(id_image) AS nbre ".
"FROM cel_images ".
"WHERE date_creation != '0000-00-00 00:00:00' ".
((isset($utilisateur)) ? " AND courriel_utilisateur = $utilisateur " : '').
'GROUP BY periode '.
'ORDER BY periode ';
 
$resulats = Cel::db()->requeter($requete);
 
$img_totale = array();
foreach ($resulats as $info) {
$img_totale[$info['periode']] = $info['nbre'];
}
 
// Trie des dates pour les étiquettes des axes
$dates = array();
$annees = array();
$les_mois = array();
$pas = 1; // intervalle de mois entre deux étiquettes
$periode = 0;
$cumul = 0;
$img_totale_cumul = array();
foreach ($img_totale as $annee_mois => $nbre) {
$annee = substr($annee_mois, 0, 4);
$mois = substr($annee_mois, 4, 2);
$mois_fmt_B = strftime('%b', strtotime("0000-$mois-01"));
$cumul += $nbre;
$img_totale_cumul[$annee_mois] = $cumul;
 
if (!isset($dates[$annee][$mois])) {
$annees[] = (!isset($dates[$annee]) ? $annee : '');
$les_mois[] = is_int($periode++ / $pas) ? $mois_fmt_B : '';
// Ajouter au tableau dates tjrs à la fin
$dates[$annee][$mois] = 1;
}
}
 
// Post traitement des données
$titre = "Évolution du dépôt d'images par mois";
$valeurs_y = implode(',', $img_totale);
$valeurs_r = implode(',', $img_totale_cumul);
$valeurs_max_y = max($img_totale);
$valeurs_max_r = max($img_totale_cumul);
$y_val_fin = $valeurs_max_y;
$y_pas = 500;
$r_val_fin = $valeurs_max_r;
$r_pas = 1000;
$etiquettes_x1 = implode('|', $les_mois);
$etiquettes_x2 = implode('|', $annees);
$etiquettes_y = 'Images';
 
// Construire de l'url de l'image
$graph = array('cht' => 'lc',
'chtt' => $titre,
'chs' => '600x200',
'chco' => '007F00,99CC00',
'chd' => 't:'.$valeurs_y.'|'.$valeurs_r,
'chds' => "0,$valeurs_max_y,0,$valeurs_max_r",
'chxt' => 'y,y,x,x,r',
'chxl' => '1:|'.$etiquettes_y.'|3:|'.$etiquettes_x2.'|2:|'.$etiquettes_x1.'',
'chxp' => '1,50|3,0',
'chxr' => "0,0,$y_val_fin,$y_pas|4,0,$r_val_fin,$r_pas",
'chm' => 'h,C3C3C3,0,0.5,1,-1|N ** ,000000,0,-1,8,1.0,ht',
'chxs' => '0,007F00|4,99CC00');
return $graph;
}
 
private function getEvolUtilisateurParMois($param) {
// Récupération des données
$requete = 'SELECT DISTINCT courriel_utilisateur , '.
' MIN(date_creation) AS date_min, MAX(date_creation) AS date_max, '.
' COUNT(id_observation) AS obs_nbre '.
'FROM cel_obs '.
"WHERE date_creation != '0000-00-00 00:00:00' ".
" AND courriel_utilisateur LIKE '%@%' ".
'GROUP BY courriel_utilisateur '.
'ORDER BY date_min ASC ';
$resultats = Cel::db()->requeter($requete);
 
// Trie des données et des dates pour les étiquettes des axes
$dates = array();
$annees = array();
$utilisateurs = array();
$les_mois = array();
$pas = 2; // intervalle de mois entre deux étiquettes
$periode = 0;
foreach ($resultats as $enrg) {
$annee = substr($enrg['date_min'], 0, 4);
$mois = substr($enrg['date_min'], 5, 2);
$mois_fmt_B = strftime('%b', strtotime("0000-$mois-01"));
 
if (!isset($dates[$annee][$mois])) {
$annees[] = (!isset($dates[$annee]) ? $annee : '');
$les_mois[] = is_int($periode++ / $pas) ? $mois_fmt_B : '';
$utilisateurs["$annee-$mois"] = 1;
// Ajouter au tableau dates tjrs à la fin
$dates[$annee][$mois] = 1;
} else {
$utilisateurs["$annee-$mois"]++;
}
}
 
// Post traitement des données
$titre = 'Évolution des utilisateurs par mois';
$valeurs = implode(',', $utilisateurs);
$valeurs_max = max($utilisateurs);
$y_val_fin = $valeurs_max;
$y_pas = 5;
$etiquettes_x1 = implode('|', $les_mois);
$etiquettes_x2 = implode('|', $annees);
$etiquettes_y = 'Utilisateurs';
 
// Construire de l'url de l'image
$graph = array('cht' => 'lc',
'chtt' => $titre,
'chs' => '600x200',
'chco' => '0000FF',//4D89F9
'chd' => 't:'.$valeurs,
'chds' => '0,'.$valeurs_max,
'chxt' => 'y,y,x,x',
'chxl' => '1:|'.$etiquettes_y.'|3:|'.$etiquettes_x2.'|2:|'.$etiquettes_x1.'',
'chxp' => '1,50|3,0',
'chxr' => "0,0,$y_val_fin,$y_pas",
'chm' => 'h,C3C3C3,0,0.5,1,-1|N ** ,000000,0,2::2,8,1.0,ht',
'chxs' => '0,0000FF|1,0000FF');
return $graph;
}
 
private function getEvolObsParMoisGlissant($param) {
// Récupération des données
$format_date = '%Y%m%d';
$where = 'date_creation > DATE_SUB(NOW(), INTERVAL 31 DAY)';
$obs_totale = $this->executerRequeteEvol('cel_obs', 'id_observation', $format_date, $where);
 
// Tri des dates pour les étiquettes des axes
$dates = array();
$annees = array();
$annees_mois = array();
$jours = array();
foreach ($obs_totale as $annee_mois_jours => $nbre) {
$annee = substr($annee_mois_jours, 0, 4);
$mois = substr($annee_mois_jours, 4, 2);
$jour = substr($annee_mois_jours, 6, 2);
$annee_mois_fmt_B = strftime('%B %Y', mktime(0, 0, 0, $mois, 1, $annee));
 
if (!isset($dates[$annee][$mois][$jour])) {
$annees_mois[] = (!isset($dates[$annee][$mois]) ? $annee_mois_fmt_B : '');
$jours[] = $jour;
// Ajouter au tableau dates tjrs à la fin
$dates[$annee][$mois][$jour] = 1;
}
}
 
// Post traitement des données
$titre = 'Évolution des observations sur un mois glissant';
$valeurs_max = max($obs_totale);
$valeurs = implode(',', $obs_totale);
$y_val_fin = $valeurs_max;
$y_pas = round($valeurs_max / 6);
$etiquettes_x1 = implode('|', $jours);
$etiquettes_x2 = implode('|', $annees_mois);
$etiquettes_y2 = 'Observations';
 
// Construire de l'url de l'image
$graph = array('cht' => 'lc',
'chtt' => $titre,
'chs' => '600x200',
'chco' => '822013',
'chd' => 't:'.$valeurs,
'chds' => '0,'.$valeurs_max,
'chxt' => 'y,y,x,x',
'chxl' => '1:|'.$etiquettes_y2.'|2:|'.$etiquettes_x1.'|3:|'.$etiquettes_x2,
'chxp' => '0,0|1,50',
'chxr' => "0,0,$y_val_fin,$y_pas",
'chm' => 'h,C3C3C3,0,0.5,1,-1|N,000000,0,1::1,8,1.0,ht',
'chxs' => '0,822013|1,822013');
 
return $graph;
}
 
private function getEvolObsParMois($param) {
// Récupération des données
$obs_totale = $this->executerRequeteEvol('cel_obs', 'id_observation');
 
// Trie des dates pour les étiquettes des axes
$dates = array();
$annees = array();
$les_mois = array();
$pas = 3; // intervalle de mois entre deux étiquettes
$periode = 0;
$cumul = 0;
$obs_totale_cumul = array();
foreach ($obs_totale as $annee_mois => $nbre) {
$annee = substr($annee_mois, 0, 4);
$mois = substr($annee_mois, 4, 2);
$mois_fmt_B = strftime('%b', strtotime("0000-$mois-01"));
$cumul += $nbre;
$obs_totale_cumul[$annee_mois] = $cumul;
 
if (!isset($dates[$annee][$mois])) {
$annees[] = (!isset($dates[$annee]) ? $annee : '');
$les_mois[] = is_int($periode++ / $pas) ? $mois_fmt_B : '';
// Ajouter au tableau dates tjrs à la fin
$dates[$annee][$mois] = 1;
}
}
 
// Post traitement des données
$titre = 'Évolution des observations par mois';
$valeurs_y = implode(',', $obs_totale);
$valeurs_r = implode(',', $obs_totale_cumul);
$valeurs_max_y = max($obs_totale);
$valeurs_max_r = max($obs_totale_cumul);
$y_val_fin = $valeurs_max_y;
$y_pas = round(($valeurs_max_y / 6), 0);
$r_val_fin = $valeurs_max_r;
$r_pas = round(($valeurs_max_r / 6), 0);
$etiquettes_x1 = implode('|', $les_mois);
$etiquettes_x2 = implode('|', $annees);
$etiquettes_y2 = 'Observations';
$etiquettes_r2 = 'Cumul obs.';
 
// Construire de l'url de l'image
$graph = array('cht' => 'lc',
'chtt' => $titre,
'chs' => '600x200',
'chco' => '822013,F1841D',
'chd' => 't:'.$valeurs_y.'|'.$valeurs_r,
'chds' => "0,$valeurs_max_y,0,$valeurs_max_r",
'chxt' => 'y,y,x,x,r,r',
'chxl' => '1:|'.$etiquettes_y2.'|2:|'.$etiquettes_x1.'|3:|'.$etiquettes_x2.'|5:|'.$etiquettes_r2.'',
'chxp' => '1,50|3,0|5,50',
'chxr' => "0,0,$y_val_fin,$y_pas|4,0,$r_val_fin,$r_pas",
'chm' => 'N ** ,000000,0,2::2,8,1.0,ht',
'chxs' => '0,822013|1,822013|4,F1841D|5,F1841D');
return $graph;
}
 
private function getEvolObsParAn($param) {
// Récupération des données
$obs_totale = $this->executerRequeteEvol('cel_obs', 'id_observation', '%Y');
 
// Trie des dates pour les étiquettes des axes
$dates = array();
$annees = array();
foreach ($obs_totale as $annee => $nbre) {
if (!isset($dates[$annee])) {
$annees[] = $annee;
$dates[$annee] = 1;
}
}
 
// Post traitement des données
$titre = 'Évolution des observations par année';
$valeurs = implode(',', $obs_totale);
$valeurs_max = max($obs_totale);
$valeurs_min = min($obs_totale);
$y_val_deb = preg_replace('/[0-9]{2}$/', '00', $valeurs_min);
$y_val_fin = $valeurs_max;
$y_pas = round(($valeurs_max / 6), 0);
$etiquettes_x = implode('|', $annees);;
$etiquettes_y = 'Observations';
 
// Construire de l'url de l'image
$graph = array('cht' => 'lc',
'chtt' => $titre,
'chs' => '600x200',
'chco' => '822013',
'chd' => 't:'.$valeurs,
'chds' => "$valeurs_min,$valeurs_max",
'chxt' => 'y,y,x',
'chxl' => '1:|'.$etiquettes_y.'|2:|'.$etiquettes_x.'',
'chxp' => '0,0|1,50|2,0',
'chxr' => "0,$y_val_deb,$y_val_fin,$y_pas",
'chm' => 'h,C3C3C3,0,0.5,1,-1|N,000000,0,1::1,8,1.0,ht',
'chxs' => '0,822013|1,822013');
return $graph;
}
 
private function getEvolObsHisto($param) {
// Récupération des données
$obs_totale = $this->executerRequeteEvol('cel_obs', 'id_observation');
$obs_identifiee = $this->executerRequeteEvol('cel_obs', 'id_observation', "courriel_utilisateur LIKE '%@%' ");
$lignes = array('total', 'obs. identifiée');
 
// Post traitement des données
$titre = 'Évolution des observations';
$valeurs = implode(',', $obs_totale).'|'.implode(',', $obs_identifiee);
$valeurs_max = max($obs_totale);
$etiquettes = implode('|', array_keys($lignes));
 
// Construire de l'url de l'image
$graph = array('cht' => 'lc',
'chtt' => $titre,
'chs' => '500x300',
'chco' => 'FF0000,00FF00',
'chd' => 't:'.$valeurs,
'chds' => "0,$valeurs_max",
'chxt' => 'y',
'chxl' => '0:|'.$etiquettes.'',
'chm' => 'N,000000,0,-1,10');
return $graph;
}
 
private function getNbreObsIdVsTest($param) {
// Récupération des données
$obs_totale = $this->executerRequeteNombre('cel_obs', 'id_observation');
$obs_identifiee = $this->executerRequeteNombre('cel_obs', 'id_observation', "courriel_utilisateur LIKE '%@%' ");
$obs_test = $obs_totale - $obs_identifiee;
$pourcent_identifiee = round(($obs_identifiee / ($obs_totale / 100)), 2).'%';
$pourcent_anonyme = round(($obs_test / ($obs_totale / 100)), 2).'%';
 
// Post traitement des données de la base de données
$titre = "Nombre d'observations|tests vs. identifiées";
$etiquette_obs_test = "tests ($obs_test - $pourcent_anonyme)";
$etiquette_obs_id = "identifiées ($obs_identifiee - $pourcent_identifiee)";
$donnees = array($etiquette_obs_test => $obs_test, $etiquette_obs_id => $obs_identifiee);
$valeurs = implode(',', $donnees);
$etiquettes = implode('|', array_keys($donnees));
 
// Construire les paramêtres de l'url de l'image
$graph = array('cht' => 'p3',
'chtt' => $titre,
'chs' => '250x200',
'chco' => 'FF0000,00FF00',
'chd' => 't:'.$valeurs,
'chds' => "0,$obs_totale",
'chdl' => $etiquettes,
'chdlp' => 'bv|r',
'chts' => '000000,12');
return $graph;
}
 
private function getNbreObsPublicVsPrivee($param) {
// Récupération des données
$obs_totale = $this->executerRequeteNombre('cel_obs', 'id_observation');
$obs_public = $this->executerRequeteNombre('cel_obs', 'id_observation', 'transmission = 1');
$obs_privee = $obs_totale - $obs_public;
$pourcent_privee = round(($obs_privee / ($obs_totale / 100)), 2).'%';
$pourcent_public = round(($obs_public / ($obs_totale / 100)), 2).'%';
 
// Post traitement des données de la base de données
$titre = "Nombre d'observations|publiques vs. privées";
$etiquette_obs_public = "publiques ($obs_public - $pourcent_public)";
$etiquette_obs_privee = "privées ($obs_privee - $pourcent_privee)";
$donnees = array($etiquette_obs_privee => $obs_privee, $etiquette_obs_public => $obs_public);
$valeurs = implode(',', $donnees);
$etiquettes = implode('|', array_keys($donnees));
 
// Construire les paramêtres du graph
$graph = array('cht' => 'p3',
'chtt' => $titre,
'chs' => '250x200',
'chco' => 'FF0000,00FF00',
'chd' => 't:'.$valeurs,
'chds' => "0,$obs_totale",
'chdl' => $etiquettes,
'chdlp' => 'bv|r',
'chts' => '000000,12');
return $graph;
}
 
private function getNbreObsDetermineeVsInconnue($param) {
// Récupération des données
$obs_totale = $this->executerRequeteNombre('cel_obs', 'id_observation');
$obs_determinee = $this->executerRequeteNombre('cel_obs', 'id_observation', 'nom_sel_nn != 0');
$obs_inconnue = $obs_totale - $obs_determinee;
$pourcent_determinee = round(($obs_determinee / ($obs_totale / 100)), 2).'%';
$pourcent_inconnue = round(($obs_inconnue / ($obs_totale / 100)), 2).'%';
 
// Post traitement des données de la base de données
$titre = "Nombre d'observations|determinées vs. inconnues";
$etiquette_obs_determinee = "determinées ($obs_determinee - $pourcent_determinee)";
$etiquette_obs_inconnue = "non déterminées ($obs_inconnue - $pourcent_inconnue)";
$donnees = array($etiquette_obs_inconnue => $obs_inconnue, $etiquette_obs_determinee => $obs_determinee);
$valeurs = implode(',', $donnees);
$etiquettes = implode('|', array_keys($donnees));
 
// Construire les paramêtres du graph
$graph = array('cht' => 'p3',
'chtt' => $titre,
'chs' => '250x200',
'chco' => 'FF0000,00FF00',
'chd' => 't:'.$valeurs,
'chds' => "0,$obs_totale",
'chdl' => $etiquettes,
'chdlp' => 'bv|r',
'chts' => '000000,12');
return $graph;
}
 
private function getNbreObsAvecIndicationGeo($param) {
// Récupération des données
$total = $this->executerRequeteNombre('cel_obs', 'id_observation');
$where_commune = $this->creerWhereIndicationGeo('zone_geo');
$obs['commune'] = $this->executerRequeteNombre('cel_obs', 'id_observation', $where_commune);
$where_commune_id = $this->creerWhereIndicationGeo('ce_zone_geo');
$obs['commune identifiée'] = $this->executerRequeteNombre('cel_obs', 'id_observation', $where_commune_id);
$where_lieudit = $this->creerWhereIndicationGeo('lieudit');
$obs['lieu-dit'] = $this->executerRequeteNombre('cel_obs', 'id_observation', $where_lieudit);
$where_station = $this->creerWhereIndicationGeo('station');
$obs['station'] = $this->executerRequeteNombre('cel_obs', 'id_observation', $where_station);
$where_milieu = $this->creerWhereIndicationGeo('milieu');
$obs['milieu'] = $this->executerRequeteNombre('cel_obs', 'id_observation', $where_milieu);
$where_xy = $this->creerWhereIndicationGeo('latitude').' AND '.$this->creerWhereIndicationGeo('longitude');
$obs['coordonnée'] = $this->executerRequeteNombre('cel_obs', 'id_observation', $where_xy);
 
$donnees = array();
$num = 1;
foreach ($obs as $etiquette => $nbre) {
$pourcent = round(($obs[$etiquette] / ($total / 100)), 1).'%';
$legende = "$num : $etiquette ($nbre - $pourcent)";
$donnees['valeurs'][] = $nbre;
$donnees['etiquettes'][] = $num++;
$donnees['legendes'][] = $legende;
}
 
 
// Post traitement des données de la base de données
$titre = "Nombre d'observations|avec indications géographiques";
$valeurs = implode(',', $donnees['valeurs']);
$etiquettes = implode('|', $donnees['etiquettes']);
$legendes = implode('|', $donnees['legendes']);
 
// Construire les paramêtres du graph
$graph = array('cht' => 'rs',
'chtt' => $titre,
'chs' => '600x300',
'chco' => 'FFFFFF',
'chd' => 't:'.$valeurs,
'chds' => "0,$total",
'chdl' => $legendes,
'chxt' => 'x',
'chxl' => "0:|$etiquettes",
//'chxp' => '1,0,20,40,60,80,100',// Grille sous forme de cible
'chm' => 'B,FF000080,0,1.0,5.0');
return $graph;
}
 
private function creerWhereIndicationGeo($champ) {
$where = null;
if (isset($champ)) {
$where = "$champ != '000null' ".
"AND $champ != '' ".
"AND $champ IS NOT NULL ";
}
return $where;
}
 
private function getUtilisationJournaliere($param) {
// Sur quel jour, voulons nous estimer l'utilisation
$aujourdhui = date('Y-m-d');
if (isset($param[0]) && preg_match('/^[0-9]{4}(?:-[0-9]{2}){2}$/', $param[0])) {
$aujourdhui = $param[0];
}
$aujourdhui_fmt = strftime('%d %b %Y', strtotime($aujourdhui));
 
// Récupération des données
$max_obs = array();
$max_obs[] = $this->executerRequeteEvol('cel_obs', 'id_observation', '%Y%m%d',
"date_creation NOT LIKE '$aujourdhui%' ", 'date_creation');
$max_obs[] = $this->executerRequeteEvol('cel_obs', 'id_observation', '%Y%m%d',
"date_modification NOT LIKE '$aujourdhui%' ", 'date_modification');
$max_obs[] = $this->executerRequeteEvol('cel_obs', 'id_observation', '%Y%m%d',
"date_transmission NOT LIKE '$aujourdhui%' ", 'date_transmission');
$obs_aujourdhui = $this->executerRequeteNombre('cel_obs', 'id_observation',
"(date_creation LIKE '$aujourdhui%'
OR date_modification LIKE '$aujourdhui%'
OR date_transmission LIKE '$aujourdhui%') ");
 
// Cummul des obs crées, modifiées, transmises par jour
$donnees = array();
foreach ($max_obs as $obs_par_jour) {
foreach ($obs_par_jour as $annee_mois_jour => $nbre) {
if (!isset($donnees[$annee_mois_jour])) {
$donnees[$annee_mois_jour] = $nbre;
} else {
$donnees[$annee_mois_jour] += $nbre;
}
}
}
 
// Post traitement des données
$valeur = $obs_aujourdhui;
$valeur_max = 400;
if ($valeur > $valeur_max) {
$pourcentage = 100;
} else {
$pourcentage = round(($valeur / ($valeur_max / 100)), 0);
}
$etiquettes_x = $aujourdhui_fmt;
$etiquettes_y = "faible|moyenne|forte";
$titre = "Intensité d'utilisation pour le $aujourdhui_fmt";
$legende = "$valeur changements";
 
// Construire de l'url de l'image
$graph = array('cht' => 'gom',
'chtt' => $titre,
'chdl' => "$legende",
'chdlp' => 'b',
'chs' => '350x200',
'chco' => 'FFFF00,0A7318',
'chls' => '3|10',
'chma' => '0,0,0,0|300,40',
'chd' => 't:'.$pourcentage,
'chxt' => 'x,y',
'chxl' => '0:|'.$etiquettes_x.'|1:|'.$etiquettes_y.'',
'chxp' => '0,50');
return $graph;
}
 
private function getNbreObsParUtilisateur($param) {
// Récupération des données
$requete = 'SELECT courriel_utilisateur, COUNT(id_observation) AS nbre '.
'FROM cel_obs '.
'GROUP BY courriel_utilisateur ';
$utilisateurs = Cel::db()->requeter($requete);
 
// Création des classes d'utilisateurs
$classes = array('00->10' => 0, '11->50' => 0, '51->100' => 0, '101->500' => 0, '500->∞' => 0);
$donnees['Utilisateurs'] = $classes;
$valeur_max = 0;
foreach ($utilisateurs as $utilisateur) {
$id = $utilisateur['courriel_utilisateur'];
$nbre = $utilisateur['nbre'];
 
// Détermination de la classe
$classe = '';
if (0 < $nbre && $nbre <= 10) {
$classe = '00->10';
} else if (10 < $nbre && $nbre <= 50) {
$classe = '11->50';
} else if (50 < $nbre && $nbre <= 100) {
$classe = '51->100';
} else if (100 < $nbre && $nbre <= 500) {
$classe = '101->500';
} else if (500 < $nbre) {
$classe = '500->∞';
}
 
// Détermination du type d'utilisateur
if (strstr($id, '@')) {
$type = 'Utilisateurs';
// Incrémentation du tableau de données et récupration de la valeur max
$donnees[$type][$classe]++;
if ($donnees[$type][$classe] > $valeur_max) {
$valeur_max = $donnees[$type][$classe];
}
}
}
 
// Post traitement des données
$titre = "Nombre d'observations par utilisateur";
$y1_val_fin = $valeur_max;
$y1_pas = '100';
$valeurs = implode(',', $donnees['Utilisateurs']);
$etiquettes_x1 = implode('|', array_keys($classes));
$etiquettes_x2 = 'Observations';
$etiquettes_y2 = 'Utilisateurs';
$legendes = implode('|', array_keys($donnees));
 
// Construire de l'url de l'image
$graph = array('cht' => 'bvg',
'chtt' => $titre,
'chs' => '400x200',
'chco' => '00FF00,FF0000',
'chbh' => 'r,0.3,1',
'chd' => 't:'.$valeurs,
'chds' => "0,$valeur_max",
'chxt' => 'x,x,y,y',
'chxl' => '0:|'.$etiquettes_x1.'|1:|'.$etiquettes_x2.'|3:|'.$etiquettes_y2.'',
'chxp' => '1,100|3,100',
'chxr' => "2,0,$y1_val_fin,$y1_pas",
'chm' => 'h,C3C3C3,0,0.5,1,-1|N,000000,0,0::1,8,1.0,e');
//echo '<pre>'.print_r($graph,true).'</pre>';
return $graph;
}
 
private function getNbreObsParUtilisateurEtTest($param) {
// Récupération des données
$requete = 'SELECT courriel_utilisateur, COUNT(id_observation) AS nbre '.
'FROM cel_obs '.
'GROUP BY courriel_utilisateur ';
$utilisateurs = Cel::db()->requeter($requete);
 
// Création des classes d'utilisateurs
$classes = array('00->10' => 0, '11->50' => 0, '51->100' => 0, '101->500' => 0, '500->∞' => 0);
$donnees['Utilisateurs'] = $classes;
$donnees['Tests'] = $classes;
$valeur_max = 0;
foreach ($utilisateurs as $utilisateur) {
$id = $utilisateur['courriel_utilisateur'];
$nbre = $utilisateur['nbre'];
 
// Détermination de la classe
$classe = '';
if (0 < $nbre && $nbre <= 10) {
$classe = '00->10';
} else if (10 < $nbre && $nbre <= 50) {
$classe = '11->50';
} else if (50 < $nbre && $nbre <= 100) {
$classe = '51->100';
} else if (100 < $nbre && $nbre <= 500) {
$classe = '101->500';
} else if (500 < $nbre) {
$classe = '500->∞';
}
 
// Détermination du type d'utilisateur
if (strstr($id, '@')) {
$type = 'Utilisateurs';
} else {
$type = 'Tests';
}
 
// Incrémentation du tableau de données et récupration de la valeur max
$donnees[$type][$classe]++;
if ($donnees[$type][$classe] > $valeur_max) {
$valeur_max = $donnees[$type][$classe];
}
}
 
// Post traitement des données
$titre = "Nombre d'observations par utilisateur et test";
$y1_val_fin = $valeur_max;
$y1_pas = '100';
$valeurs = implode(',', $donnees['Utilisateurs']).'|'.implode(',', $donnees['Tests']);
$etiquettes_x1 = implode('|', array_keys($classes));
$etiquettes_x2 = 'Observations';
$etiquettes_y2 = 'Utilisateurs';
$legendes = implode('|', array_keys($donnees));
 
// Construire de l'url de l'image
$graph = array('cht' => 'bvg',
'chtt' => $titre,
'chs' => '400x200',
'chco' => '00FF00,FF0000',
'chbh' => 'r,0.3,1',
'chd' => 't:'.$valeurs,
'chds' => "0,$valeur_max",
'chxt' => 'x,x,y,y',
'chxl' => '0:|'.$etiquettes_x1.'|1:|'.$etiquettes_x2.'|3:|'.$etiquettes_y2.'',
'chxp' => '1,100|3,100',
'chxr' => "2,0,$y1_val_fin,$y1_pas",
'chm' => 'h,C3C3C3,0,0.5,1,-1|N,000000,0,0::1,8,1.0,e|N,000000,1,0::1,8,1.0,e',
'chdl' => $legendes,
'chdlp' => 'b');
//echo '<pre>'.print_r($graph,true).'</pre>';
return $graph;
}
 
private function getNuagePointsObsParHeureEtJourSemaine($param) {
$utilisateur = isset($_GET['utilisateur']) ? Cel::db()->quote($_GET['utilisateur']) : false;
 
// Récupération des données de la base
$requete = 'SELECT courriel_utilisateur, DATE_FORMAT(date_creation, "%w-%H") AS periode, (ROUND(LOG10(COUNT(id_observation))) + 1) AS nbre '.
'FROM cel_obs '.
'WHERE date_creation != "0000-00-00 00:00:00" '.
' AND courriel_utilisateur '.($utilisateur ? "= $utilisateur " : 'LIKE "%@%" ').
'GROUP BY periode, courriel_utilisateur ';
$infos = Cel::db()->requeter($requete);
 
// Traitement résulat requête
$observations = array();
foreach ($infos as $info) {
if (isset($observations[$info['periode']])) {
$observations[$info['periode']] += $info['nbre'];
} else {
$observations[$info['periode']] = $info['nbre'];
}
}
 
// Postraitement des données
// Jour de la semaine
$donnees['joursSemaine'] = array();
for ($njs = 0; $njs < 7; $njs++) {
$donnees['joursSemaine'][] = strftime('%A', strtotime('2010-05-'.(16+$njs)));
}
// Heure
$donnees['heures'] = array();
for ($h = 0; $h < 24; $h++) {
$heure_fmt = sprintf('%02s', $h);// Format numérique 00
$donnees['heures'][] = strftime('%H', strtotime("0000-00-00 $heure_fmt:00:00"));
}
// Nbre
$valeur_max = max($observations);
for ($njs = 0; $njs < 7; $njs++) {
for ($h = 0; $h < 24; $h++) {
$hfmt = sprintf('%02s', $h);// Format numérique 00
$periode = $njs.'-'.$hfmt;
$donnees['valeurs_x'][] = round(($h + 1) * (100 / 24), 0);
$donnees['valeurs_y'][] = round(($njs + 1) * (100 / 7), 0);
$ps = 0;
if (isset($observations[$periode])) {
$ps = round($observations[$periode] * (100 / $valeur_max), 0);
}
$donnees['valeurs_ps'][] = $ps;
}
}
//echo '<pre>'.print_r($donnees,true).'</pre>';
// Préparation des paramêtres du graph
$titre = "Nombre de création d'observation|par heure et jour de la semaine";
$valeurs = implode(',', $donnees['valeurs_x'])."|".implode(',', $donnees['valeurs_y'])."|".implode(',', $donnees['valeurs_ps']);
$etiquettes_x1 = '|'.implode('|', $donnees['heures']);
$etiquettes_x2 = 'Heures';
$etiquettes_y1 = '|'.implode('|', $donnees['joursSemaine']);
$x_axis_step_size = str_replace(',', '.', (100 / 24));
$y_axis_step_size = str_replace(',', '.', (100 / 7));
 
// Construction du tableau des paramêtres du graph
$graph = array('cht' => 's',
'chtt' => $titre,
'chs' => '400x200',
'chco' => '00FF00',
'chd' => 't:'.$valeurs,
'chxt' => 'x,x,y',
'chxr' => "0,-1,23,1|2,-1,6,1",
'chxp' => '1,100',
'chxl' => '0:|'.$etiquettes_x1.'|1:|'.$etiquettes_x2.'|2:|'.$etiquettes_y1.'',
'chg' => "$x_axis_step_size,$y_axis_step_size,1,5");
//echo '<pre>'.print_r($graph,true).'</pre>';
return $graph;
}
 
private function getNuagePointsObsAnciennete($param) {
// Récupération des données de la base
$requete = 'SELECT DISTINCT courriel_utilisateur , '.
' MIN(date_creation) AS date_min, MAX(date_creation) AS date_max, '.
' COUNT(id_observation) AS obs_nbre '.
'FROM cel_obs '.
"WHERE date_creation != '0000-00-00 00:00:00' ".
" AND courriel_utilisateur LIKE '%@%' ".
'GROUP BY courriel_utilisateur '.
'ORDER BY date_min ASC ';
$resultats = Cel::db()->requeter($requete);
 
// Trie des données
$max_obs = 0;
$max_obs_log = 0;
$max_anciennete = 0;
$donnees = array();
foreach ($resultats as $enrg) {
$tps_deb = strtotime($enrg['date_min']);
$tps_fin = strtotime($enrg['date_max']);
 
$donnee = array();
if (($tps_fin - $tps_deb) == 0) {
$donnee['anciennete'] = 1;
} else {
$donnee['anciennete'] = round((($tps_fin - $tps_deb) / 86400), 0);
}
$donnee['obs'] = $enrg['obs_nbre'];
$donnee['obs_log'] = log10($enrg['obs_nbre']);
$donnees[] = $donnee;
 
$max_obs_log = ($donnee['obs_log'] > $max_obs_log) ? $donnee['obs_log'] : $max_obs_log;
$max_obs = ($donnee['obs'] > $max_obs) ? $donnee['obs'] : $max_obs;
$max_anciennete = ($donnee['anciennete'] > $max_anciennete) ? $donnee['anciennete'] : $max_anciennete;
}
 
// Postraitement des données
foreach ($donnees as $donnee) {
$donnees['valeurs_x'][] = round($donnee['anciennete'] * (100 / $max_anciennete), 0);
$donnees['valeurs_y'][] = round($donnee['obs_log'] * (100 / $max_obs_log), 0);
$donnees['valeurs_ps'][] = 20;
}
 
// Échelle log des obs
$donnees['echelle_y1'] = array();
$pas = $max_obs_log / 100 ;
for ($i = 0 ; $i < 5 ; $i++) {
$donnees['echelle_y1'][] = round(pow(10, (($i*20) * $pas)), 0);
}
$donnees['echelle_y1'][] = $max_obs;
 
//echo '<pre>'.print_r($donnees['valeurs_x'],true).'</pre>';
// Préparation des paramêtres du graph
$titre = "Répartition des utilisateurs en fonction|du nombre d'observations et de l'ancienneté";
$valeurs = implode(',', $donnees['valeurs_x'])."|".implode(',', $donnees['valeurs_y'])."|".implode(',', $donnees['valeurs_ps']);
$etiquettes_x2 = 'Ancienneté en jours';
$etiquettes_y1 = implode('|', $donnees['echelle_y1']);
$etiquettes_y2 = 'Observations';
$x_axis_step_size = $max_anciennete;
 
// Construction du tableau des paramêtres du graph
$graph = array('cht' => 's',
'chtt' => $titre,
'chs' => '400x200',
'chco' => '0000FF',
'chxt' => 'x,x,y,y',
'chd' => 't:'.$valeurs,
'chxr' => "0,0,$x_axis_step_size|2,0,$max_obs",//|2,0,$y_axis_step_size,$pas
'chxp' => '1,100|3,100',
'chm' => 'h,C3C3C3,0,-0.2,0.2,-1',
'chxl' => '1:|'.$etiquettes_x2.'|2:|'.$etiquettes_y1.'|3:|'.$etiquettes_y2.'');//
//echo '<pre>'.print_r($graph,true).'</pre>';
return $graph;
}
 
private function executerRequeteEvol($table, $champ, $format_date = '%Y%m', $where = null, $champ_date = 'date_creation', $order_by = null, $limit = null) {
$utilisateur = isset($_GET['utilisateur']) ? Cel::db()->quote($_GET['utilisateur']) : false;
 
$requete = "SELECT DATE_FORMAT($champ_date, '$format_date') AS periode, COUNT($champ) AS nbre ".
"FROM $table ".
"WHERE $champ_date != '0000-00-00 00:00:00' ".
(($utilisateur != false) ? " AND courriel_utilisateur = $utilisateur " : '').
((is_null($where)) ? '' : " AND $where ").
'GROUP BY periode '.
((is_null($order_by)) ? '' : "ORDER BY $order_by ");
((is_null($limit)) ? '' : "LIMIT $limit ");
 
$evolution = Cel::db()->requeter($requete);
 
// Traitement du tableau
$donnees_traitees = array();
foreach ($evolution as $info) {
$donnees_traitees[$info['periode']] = $info['nbre'];
}
 
return $donnees_traitees;
}
 
private function executerRequeteNombre($table, $champ, $where = null) {
$utilisateur = null;
if (isset($_GET['utilisateur'])) {
$utilisateur = Cel::db()->quote($_GET['utilisateur']);
$where = isset($where) ? $where.' AND ' : '';
$where .= "courriel_utilisateur = $utilisateur ";
}
 
$requete = "SELECT COUNT($champ) AS nbre ".
"FROM $table ".
((isset($where)) ? "WHERE $where " : '');
 
$nbre = Cel::db()->requeterValeurUnique($requete);
return $nbre;
}
}
?>
/branches/v2.3-faux/jrest/services/CelStatistiqueTxt.php
New file
0,0 → 1,508
<?php
/**
* Service fournissant des statistiques de l'application CEL au format texte (JSON).
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* Cas d'utilisation :
* /CelStatistiqueTxt/TypeDeStat : retourne les statistiques demandées
* Paramêtres :
* utilisateur=courriel : retourne les statistiques d'un utilisateur donné.
*
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright Copyright (c) 2011, Tela Botanica (accueil@tela-botanica.org)
*/
class CelStatistiqueTxt extends Cel {
 
/**
* Méthode appelée avec une requête de type GET.
*/
public function getElement($ressources) {
$graph = null;
$serveur = '';
 
if (isset($ressources[0])) {
$this->analyserParametresUrl();
$stat_demande = array_shift($ressources);
$methode = 'get'.$stat_demande;
if (method_exists($this, $methode)) {
$this->ressources = $ressources;
$stats = $this->$methode($ressources);
} else {
$this->messages[] = "Ce type de statistiques '$stat_demande' n'est pas disponible.";
}
} else {
$this->messages[] = "La ressource du service CEL StatistiqueTxt doit indiquer le type de statistique. Ex. : .../CelStatistiqueTxt/Nombres";
}
 
if (!is_null($stats)) {
$this->envoyerJson($stats);
}
}
 
private function analyserParametresUrl() {
$this->parametres['utilisateur'] = isset($_GET['utilisateur']) ? Cel::db()->quote($this->verifierSecuriteParametreUrl($_GET['utilisateur'])) : null;
$this->parametres['num_taxon'] = isset($_GET['num_taxon']) ? Cel::db()->quote($this->verifierSecuriteParametreUrl($_GET['num_taxon'])) : null;
$this->parametres['taxon'] = isset($_GET['taxon']) ? Cel::db()->quote($this->verifierSecuriteParametreUrl($_GET['taxon'].'%')) : null;
$this->parametres['tag'] = isset($_GET['tag']) ? $this->verifierSecuriteParametreUrl($_GET['tag']) : null;
$this->parametres['start'] = isset($_GET['start']) ? $this->verifierSecuriteParametreUrl($_GET['start']) : null;
$this->parametres['limit'] = isset($_GET['limit']) ? $this->verifierSecuriteParametreUrl($_GET['limit']) : null;
}
 
private function getListeUtilisateursNbrePhotos() {
$liste = array();
 
$requete = $this->construireRequeteListeUtilisateurNbrePhoto();
if ($requete != null) {
$resultats = Cel::db()->requeter($requete);
if ($resultats != false) {
foreach ($resultats as $resultat) {
$liste[$resultat['courriel_utilisateur']] = $resultat['nbre'];
}
}
}
return $liste;
}
 
private function construireRequeteListeUtilisateurNbrePhoto() {
$select = 'SELECT co.courriel_utilisateur, COUNT(DISTINCT ci.id_image) AS nbre ';
$from = 'FROM cel_obs co '.
' LEFT JOIN cel_obs_images coi ON (coi.id_observation = co.id_observation) '.
' LEFT JOIN cel_images ci ON (coi.id_image = ci.id_image) ';
$where = 'WHERE transmission = 1 ';
$groupBy = 'GROUP BY co.courriel_utilisateur ';
$orderBy = 'ORDER BY nbre DESC ';
$limitSql = 'LIMIT 0,150 ';
 
$zero_images = false;
if (count($this->parametres) != 0) {
extract($this->parametres);
 
$filtres = array();
 
if (isset($utilisateur)) {
$filtres[] = "co.courriel_utilisateur = $utilisateur ";
}
if (isset($num_taxon)) {
$filtres[] = "nt = $num_taxon ";
}
if (isset($taxon)) {
$filtres[] = "nom_ret LIKE $taxon ";
}
if (isset($tag)) {
$limitation = $this->construireWhereTags();
if ($limitation != null) {
$filtres[] = $limitation;
} else {
$zero_images = true;
}
}
$where .= ((count($filtres) > 0) ? 'AND '.implode(' AND ', $filtres) : '');
 
if (isset($start)) {
$limitSql = str_replace('0,', "$start,", $limitSql);
}
if (isset($limit)) {
$limitSql = str_replace('150', $limit, $limitSql);
}
}
if ($zero_images) {
$requete = null;
} else {
$requete = $select.$from.$where.$groupBy.$orderBy.$limitSql;
//echo $requete;
}
return $requete;
}
 
private function construireWhereTags() {
$where = null;
if (isset($this->parametres['tag'])) {
$tag = $this->parametres['tag'];
$tag_encode = Cel::db()->quote($this->encoderMotCle(trim($tag)));
 
// Construction de la requête
$requete = 'SELECT cmc_id_mot_cle_utilisateur, cmc_id_proprietaire '.
'FROM cel_mots_cles_images '.
"WHERE cmc_id_mot_cle_general = $tag_encode ";
$elements = Cel::db()->requeter($requete);
 
if ($elements != false && count($elements) > 0) {
// Pré-construction du where de la requête
$tpl_where = '(ci_meta_mots_cles LIKE "%%%s%%" AND ci_ce_utilisateur = %s )';
$requete_where = array();
foreach ($elements as $occurence) {
$requete_where[] = sprintf($tpl_where, $occurence['cmc_id_mot_cle_utilisateur'], Cel::db()->quote($occurence['cmc_id_proprietaire']));
}
$where = ' ('.implode(" \nOR ", $requete_where).') ';
} else {
$this->debug[] = "Aucune image ne correspond à ce mot clé.";
}
}
return $where;
}
 
private function getListeTaxonsNbrePhotos() {
$requete = $this->construireRequeteListeTaxonNbrePhoto();
 
$resultats = Cel::db()->requeter($requete);
$liste = array();
if ($resultats != false) {
foreach ($resultats as $resultat) {
$liste[$resultat['nom_ret']] = $resultat['nbre'];
}
}
return $liste;
}
 
private function construireRequeteListeTaxonNbrePhoto() {
$select = 'SELECT nom_ret, COUNT(DISTINCT ci.id_image) AS nbre ';
$from = 'FROM cel_obs co '.
' LEFT JOIN cel_obs_images coi ON (coi.id_observation = co.id_observation) '.
' LEFT JOIN cel_images ci ON (coi.id_image = ci.id_image) ';
$where = 'WHERE transmission = 1 '.
" AND nom_ret != '' ";
$groupBy = 'GROUP BY nom_ret ';
$orderBy = 'ORDER BY nbre DESC ';
$limitSql = 'LIMIT 0,150 ';
 
 
if (count($this->parametres) != 0) {
extract($this->parametres);
 
$filtres = array();
 
if (isset($utilisateur)) {
$filtres[] = "co.courriel_utilisateur = $utilisateur ";
}
if (isset($num_taxon)) {
$filtres[] = "nt = $num_taxon ";
}
if (isset($taxon)) {
$filtres[] = "nom_ret LIKE $taxon ";
}
$where .= ((count($filtres) > 0) ? 'AND '.implode(' AND ', $filtres) : '');
 
if (isset($start)) {
$limitSql = str_replace('0,', "$start,", $limitSql);
}
if (isset($limit)) {
$limitSql = str_replace('150', $limit, $limitSql);
}
}
 
$requete = $select.$from.$where.$groupBy.$orderBy.$limitSql;
 
return $requete;
}
 
private function getNombres() {
 
$requete = $this->construireRequeteNbreObs();
$info['observations'] = (int) Cel::db()->requeterValeurUnique($requete);
 
$requete = $this->construireRequeteNbreObsPubliques();
$info['observationsPubliques'] = (int) Cel::db()->requeterValeurUnique($requete);
 
$requete = $this->construireRequeteNbreImg();
$info['images'] =(int) Cel::db()->requeterValeurUnique($requete);
 
$requete = $this->construireRequeteNbreImgLiees();
$info['imagesLiees'] =(int) Cel::db()->requeterValeurUnique($requete);
 
$requete = $this->construireRequeteNbreObsLiees();
$info['observationsLiees'] = (int) Cel::db()->requeterValeurUnique($requete);
 
$info['moyImagesParObs'] = ($info['observationsLiees'] > 0 ? round($info['imagesLiees']/$info['observationsLiees'], 2) : '');
 
$requete = $this->construireRequeteNbreObsParCommune();
$info['communes'] = ($resultats = Cel::db()->requeter($requete)) ? count($resultats) : '' ;
$info['observationsParCommunesMin'] = 1000;
$info['observationsParCommunesMax'] = 0;
$info['observationsParCommunesTotal'] = 0;
foreach ($resultats as $resultat) {
if ($resultat['nbre'] < $info['observationsParCommunesMin']) {
$info['observationsParCommunesMin'] = $resultat['nbre'];
}
if ($resultat['nbre'] > $info['observationsParCommunesMax']) {
$info['observationsParCommunesMax'] = $resultat['nbre'];
}
$info['observationsParCommunesTotal'] += $resultat['nbre'];
}
$info['observationsParCommunesMoyenne'] = ($info['communes'] > 0 ) ? round($info['observationsParCommunesTotal'] / $info['communes'], 2) : 0;
 
return $info;
}
 
private function construireRequeteNbreObs() {
$requete = 'SELECT COUNT(id_observation) AS nbre '.
'FROM cel_obs ';
 
if (count($this->parametres) != 0) {
$filtres = array();
extract($this->parametres);
 
if (isset($utilisateur)) {
$filtres[] = "courriel_utilisateur = $utilisateur ";
}
if (isset($num_taxon)) {
$filtres[] = "num_taxon = $num_taxon ";
}
if (isset($taxon)) {
$filtres[] = "nom_ret LIKE $taxon ";
}
 
$requete .= ((count($filtres) > 0) ? 'WHERE '.implode(' AND ', $filtres) : '');
}
 
return $requete;
}
 
private function construireRequeteNbreObsPubliques() {
$requete = 'SELECT COUNT(id_observation) AS nbre '.
'FROM cel_obs '.
"WHERE transmission = 1 ";
 
if (count($this->parametres) != 0) {
$filtres = array();
extract($this->parametres);
 
if (isset($utilisateur)) {
$filtres[] = "courriel_utilisateur = $utilisateur ";
}
if (isset($num_taxon)) {
$filtres[] = "num_taxon = $num_taxon ";
}
if (isset($taxon)) {
$filtres[] = "nom_ret LIKE $taxon ";
}
 
$requete .= ((count($filtres) > 0) ? 'AND '.implode(' AND ', $filtres) : '');
}
 
return $requete;
}
 
private function construireRequeteNbreObsParCommune() {
$requete = 'SELECT COUNT(id_observation) AS nbre '.
'FROM cel_obs '.
"WHERE zone_geo IS NOT NULL ".
" AND ce_zone_geo IS NOT NULL ";
$groupBy = 'GROUP BY zone_geo, ce_zone_geo';
 
if (count($this->parametres) != 0) {
$filtres = array();
extract($this->parametres);
 
if (isset($utilisateur)) {
$filtres[] = "courriel_utilisateur = $utilisateur ";
}
if (isset($num_taxon)) {
$filtres[] = "nt = $num_taxon ";
}
if (isset($taxon)) {
$filtres[] = "nom_ret LIKE $taxon ";
}
 
$requete .= ((count($filtres) > 0) ? 'AND '.implode(' AND ', $filtres) : '');
}
$requete .= $groupBy;
 
return $requete;
}
 
private function construireRequeteNbreImg() {
$select = 'SELECT COUNT(DISTINCT ci.id_image) AS nbre ';
$from = 'FROM cel_images ci ';
 
if (count($this->parametres) != 0) {
$filtres = array();
 
extract($this->parametres);
 
if (isset($utilisateur)) {
$filtres[] = "courriel_utilisateur = $utilisateur ";
}
if (isset($num_taxon)) {
 
$filtres[] = "nt = $num_taxon ";
}
if (isset($taxon)) {
$filtres[] = "nom_ret LIKE $taxon ";
}
if (isset($num_taxon) || isset($taxon)) {
$from .= 'LEFT JOIN cel_obs_images coi ON (coi.id_image = ci.id_image) '.
'LEFT JOIN cel_obs co ON (coi.id_observation = co.id_observation) ';
}
 
$where = ((count($filtres) > 0) ? 'WHERE '.implode(' AND ', $filtres) : '');
}
$requete = $select.$from.$where;
 
return $requete;
}
 
private function construireRequeteNbreImgLiees() {
$select = 'SELECT COUNT(DISTINCT ci.id_image) AS nbre ';
$from = 'FROM cel_obs_images coi '.
' LEFT JOIN cel_images ci ON (coi.id_image = ci.id_image) ';
 
if (count($this->parametres) != 0) {
$filtres = array();
 
extract($this->parametres);
 
if (isset($utilisateur)) {
$filtres[] = "ci.courriel_utilisateur = $utilisateur ";
}
if (isset($num_taxon)) {
$filtres[] = "nt = $num_taxon ";
}
if (isset($taxon)) {
$filtres[] = "nom_ret LIKE $taxon ";
}
 
if (isset($num_taxon) || isset($taxon)) {
$from .= 'LEFT JOIN cel_obs ON (coi.id_observation = co.id_observation) ';
}
 
$where = ((count($filtres) > 0) ? 'WHERE '.implode(' AND ', $filtres) : '');
}
 
$requete = $select.$from.$where;
return $requete;
}
 
private function construireRequeteNbreObsLiees() {
$select = 'SELECT COUNT(DISTINCT coi.id_observation) AS nbre ';
$from = 'FROM cel_obs_images coi '.
' LEFT JOIN cel_obs co ON (coi.id_observation = co.id_observation) ';
 
if (count($this->parametres) != 0) {
$filtres = array();
 
extract($this->parametres);
 
if (isset($utilisateur)) {
$filtres[] = "courriel_utilisateur = $utilisateur ";
}
if (isset($num_taxon)) {
$filtres[] = "nt = $num_taxon ";
}
if (isset($taxon)) {
$filtres[] = "nom_ret LIKE $taxon ";
}
 
$where = ((count($filtres) > 0) ? 'WHERE '.implode(' AND ', $filtres) : '');
}
 
$requete = $select.$from.$where;
 
return $requete;
}
 
 
/**
* Retourne les n principaux contributeurs depuis x jours,
* en termes d'observations ajoutées, d'images ajoutées, ou les deux
* Paramètres : "jours" (int), "nombre" (int), "critere" ("obs" ou "img" ou "")
* @return array
*/
private function getGrandsContributeurs() {
 
$nombre = 10; // les $nombre plus importants contributeurs
$jours = 7; // depuis $jours jours
$critere = null; // "obs", "img" ou null (les deux)
 
if (isset($this->parametres['nombre'])) {
$nombre = $this->parametres['nombre'];
}
if (isset($this->parametres['jours'])) {
$jours = $this->parametres['jours'];
}
if (isset($this->parametres['critere'])) {
$critere = $this->parametres['critere'];
}
 
$requete = $this->construireRequeteGrandsContributeurs($nombre, $jours, $critere);
$resultats = Cel::db()->requeter($requete);
 
$courriels = array();
foreach ($resultats as $res) {
$courriels[] = $res['courriel_utilisateur'];
}
$identites = $this->recupererUtilisateursIdentite($courriels);
foreach ($resultats as &$res) {
$res['intitule_utilisateur'] = $identites[$res['courriel_utilisateur']]['intitule'];
unset($res['courriel_utilisateur']);
unset($res['nom_utilisateur']);
unset($res['prenom_utilisateur']);
}
 
$retour = array(
'entete' => array(
'nombre' => intval($nombre),
'jours' => intval($jours),
'critere' => $critere
),
'resultats' => array()
);
$liste = array();
if ($resultats != false) {
foreach ($resultats as $resultat) {
// essayons de faire du JSON propre
if (isset($resultat['nombreImg'])) {
$resultat['nombreImg'] = intval($resultat['nombreImg']);
}
if (isset($resultat['nombreObs'])) {
$resultat['nombreObs'] = intval($resultat['nombreObs']);
}
if (isset($resultat['somme'])) {
$resultat['somme'] = intval($resultat['somme']);
}
$liste[] = $resultat; // pas de clefs afin de renvoyer une "liste" JSON, qui sera interprétée en conservant l'ordre
}
$retour['resultats'] = $liste;
}
return $retour;
}
 
private function construireRequeteGrandsContributeurs($nombre = 10, $jours = 7, $critere = null) {
$req = "";
switch ($critere) {
case "obs":
$req = "SELECT ce_utilisateur , prenom_utilisateur , nom_utilisateur , courriel_utilisateur , count(*) as nombreObs" .
" FROM cel_obs" .
" WHERE transmission = 1" .
" AND TO_DAYS(NOW()) - TO_DAYS(date_transmission) <= $jours" .
" GROUP BY ce_utilisateur ORDER BY nombreObs DESC LIMIT $nombre;";
break;
case "img":
$req = "SELECT co.ce_utilisateur , co.prenom_utilisateur , co.nom_utilisateur , co.courriel_utilisateur , count(DISTINCT ci.id_image) as nombreImg" .
" FROM cel_images ci" .
" RIGHT JOIN cel_obs_images coi ON coi.id_image = ci.id_image" .
" LEFT JOIN cel_obs co ON coi.id_observation = co.id_observation" .
" WHERE co.transmission = 1" .
" AND TO_DAYS(NOW()) - TO_DAYS(co.date_transmission) <= $jours" .
" GROUP BY co.ce_utilisateur ORDER BY nombreImg DESC LIMIT $nombre;";
break;
default:
$req = "SELECT co.ce_utilisateur , co.prenom_utilisateur , co.nom_utilisateur , co.courriel_utilisateur ," .
" count(DISTINCT ci.id_image) as nombreImg, count(DISTINCT co.id_observation) as nombreObs," .
" count(DISTINCT ci.id_image) + count(DISTINCT co.id_observation) as somme" .
" FROM cel_images ci" .
" RIGHT JOIN cel_obs_images coi ON coi.id_image = ci.id_image" .
" LEFT JOIN cel_obs co ON coi.id_observation = co.id_observation" .
" WHERE co.transmission = 1" .
" AND TO_DAYS(NOW()) - TO_DAYS(co.date_transmission) <= $jours" .
" GROUP BY co.ce_utilisateur" .
" ORDER BY somme DESC LIMIT $nombre;";
}
 
return $req;
}
}
?>
/branches/v2.3-faux/jrest/services/InventoryByDept.php
New file
0,0 → 1,155
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author David Delon <delon@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/
*/
 
/**
*
* in=utf8
* out=iso3859
*
* Liste des Nouvelles observations par departement
* A voir avec David mais ne devrait plus être utilisé
* ou fait autrement
*
*/
 
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(realpath(__FILE__))) . '/lib');
// la sortie est binaire (xls), mais OLE n'est pas compatible E_ALL en PHP-5.4
error_reporting(error_reporting() ^ E_STRICT);
require_once("lib/OLE.php");
require_once("lib/Spreadsheet/Excel/Writer.php");
 
class InventoryByDept extends Cel {
 
var $extendSpreadsheetProductor;
 
function InventoryByDept($config) {
 
parent::__construct($config);
 
// Pas d'heritage multiple en php :(
$this->extendSpreadsheetProductor = new SpreadsheetProductor();
$this->extendSpreadsheetProductor->initSpreadsheet();
}
 
//TODO : faire une fonction qui prend en paramètre un departement
function getRessource(){
 
$requete_obs = "SELECT ce_zone_geo, ce_utilisateur, courriel_utilisateur, ordre, nom_sel, nom_sel_nn, nom_ret, nom_ret_nn, nt, famille, zone_geo, date_observation," .
" lieudit, station, milieu, commentaire, transmission FROM cel_obs ".
"WHERE ce_zone_geo != '000null' AND ce_zone_geo != '' AND transmission = 1 AND nt!=0 ORDER BY ce_zone_geo, nom_ret LIMIT 50";
 
$resultat_obs = Cel::db()->requeter($requete_obs);
 
// Creating a workbook
$workbook = new Spreadsheet_Excel_Writer();
$workbook->setVersion(8);
// Creating a worksheet
$worksheet = $workbook->addWorksheet('Liste');
$worksheet->setInputEncoding('utf-8');
 
$worksheet->write(0,0,'Departement');
$worksheet->write(0,1,'Nom saisi');
$worksheet->write(0,2,'Numero nomenclatural');
$worksheet->write(0,3,'Nom retenu');
$worksheet->write(0,4,'Numero nomenclatural nom retenu');
$worksheet->write(0,5,'Numero taxonomique');
$worksheet->write(0,6,'Famille');
$worksheet->write(0,7,'Commune');
$worksheet->write(0,8,'Date Observation');
$worksheet->write(0,9,'Lieu dit');
$worksheet->write(0,10,'Station');
$worksheet->write(0,11,'Milieu');
$worksheet->write(0,12,'Commentaire');
$worksheet->write(0,13,'Observateur');
 
$i=1;
 
$observations = array();
$chercheur_infos_taxon = null;
if (is_array($resultat_obs)) {
$observations = &$resultat_obs;
$chercheur_infos_taxon = new RechercheInfosTaxonBeta($this->config);
}
 
foreach ($observations as $obs) {
 
$code_departement = $this->convertirCodeZoneGeoVersDepartement($obs['ce_zone_geo']);
$taxon_deja_vu = $chercheur_infos_taxon->taxonEstPresentDansDepartement($obs['nt'], $code_departement);
 
if (!$taxon_deja_vu) {
// Denullifiage
foreach($obs as $k=>$v) {
if (($v=="null") || ($v=="000null")) {
$obs[$k]="";
}
else {
$obs[$k]=utf8_decode($v);
}
}
 
if ($obs['date_observation']!="0000-00-00 00:00:00") {
list($year,$month,$day)= explode('-',$obs['date_observation']);
list($day)= explode(' ',$day);
$obs['date_observation']=$day."/".$month."/".$year;
}
else {
$obs['date_observation']="00/00/0000";
}
 
$worksheet->write($i,0,$code_departement);
$worksheet->write($i,1,$obs['nom_sel']);
$worksheet->write($i,2,$obs['nom_sel_nn']);
$worksheet->write($i,3,$obs['nom_ret']);
$worksheet->write($i,4,$obs['nom_ret_nn']);
$worksheet->write($i,5,$obs['nt']);
$worksheet->write($i,6,$obs['famille']);
$worksheet->write($i,7,$obs['zone_geo']);
$worksheet->write($i,8,$obs['date_observation']);
$worksheet->write($i,9,$obs['lieudit']);
$worksheet->write($i,10,$obs['station']);
$worksheet->write($i,11,$obs['milieu']);
$worksheet->write($i,12,$obs['commentaire']);
$worksheet->write($i,13,$obs['courriel_utilisateur']);
 
$i++;
}
}
 
// sending HTTP headers
$workbook->send('liste.xls');
$workbook->close();
 
exit();
}
}
 
/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log$
* Revision 1.1 2008-11-13 11:29:12 ddelon
* Reecriture gwt-ext
*
* Revision 1.2 2008-01-30 08:57:28 ddelon
* fin mise en place mygwt
*
* Revision 1.1 2007-06-06 13:31:16 ddelon
* v0.09
*
* Revision 1.3 2007-05-22 12:54:09 ddelon
* Securisation acces utilisateur
*
*
*
*/
?>
/branches/v2.3-faux/jrest/services/CelWidgetUploadImageTemp.php
New file
0,0 → 1,134
<?php
// declare(encoding='UTF-8');
/**
* Service permettant d'enregistrer dans le répertoire temporaire les images envoyées depuis le widget Saisie
*
* Cas d'utilisation :
* POST /CelWidgetUploadImageTemp : écriture d'une image dans le répertoire temporaire
*
* @author Mathias Chouet <mathias@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright © 2013, Tela-Botanica
*/
class CelWidgetUploadImageTemp extends Cel {
 
protected $projet = '';
 
public function createElement($donnees) {
$image = $_FILES['fichier']; // chaudrépare
if (isset($_GET['projet'])) {
$this->projet = $_GET['projet'];
}
$retour = $this->enregistrerImageTemporaire($image);
$this->formaterRetourAvecSquelette($retour);
}
 
private function formaterRetourAvecSquelette($retour) {
$codeRetour = true;
if (is_array($retour)) {
$squelette = 'services/squelettes/image_temp.tpl.xml';
$contenu = $this->traiterSquelettePhp($squelette, $retour);
$mime = 'text/xml';
} else {
$contenu = 'Un problème est survenu : '.print_r($retour['message'], true);
$codeRetour = false;
}
if ($codeRetour) {
$this->envoyer($contenu, $mime);
exit; // pour éviter que JRest renvoie des headers après le contenu - supporté par agathis (nginx) mais pas apache (sequoia)
} else {
return false;
}
}
 
// enregistre l'image envoyée dans le chemin de stockage temporaire, puis
// renvoie le XML attendu par le widget de saisie du CEL
public function enregistrerImageTemporaire($image) {
$retour = array(
'urlMiniature' => '',
'imageNom' => '',
'message' => '',
'debogage' => '');
$message = '';
$debogage = '';
if ($image['error'] == UPLOAD_ERR_OK) {
if (is_uploaded_file($image['tmp_name'])) {
if ($this->verifierFormatJpeg($image['tmp_name'])) {
$dossierStockage = $this->config['cel']['chemin_stockage_temp'];
 
$nomFichierOriginal = preg_replace('/[.](jpeg|jpg)$/i', '.jpg', strtolower($image['name']));
$originalChemin = $dossierStockage.'/'.$nomFichierOriginal;
$deplacementOk = move_uploaded_file($image['tmp_name'], $originalChemin);
 
if ($deplacementOk === true) {
$miniatureFichier = str_replace('.jpg', '_min.jpg', $nomFichierOriginal);
$miniatureChemin = $dossierStockage.'/'.$miniatureFichier;
 
// Parametres
$largeurIdeale = 100;
$hauteurIdeale = 100;
$qualite = 85;
 
// Calcul de la hauteur et de la largeur optimale de la miniature
$taillesImgOriginale = getimagesize($originalChemin);
$largeurOrigine = $taillesImgOriginale[0];
$hauteurOrigine = $taillesImgOriginale[1];
 
$largeurMin = $largeurIdeale;
$hauteurMin = (int) ($hauteurOrigine * ($largeurIdeale / $largeurOrigine));
if ($hauteurMin > $hauteurIdeale) {
$hauteurMin = $hauteurIdeale;
$largeurMin = (int)($largeurOrigine * ($hauteurMin / $hauteurOrigine));
}
 
// Création de la miniature
$imageOriginale = imagecreatefromjpeg($originalChemin);
$imageMiniature = imagecreatetruecolor($largeurMin, $hauteurMin);
$couleurFond = imagecolorallocate($imageMiniature, 255, 255, 255);
imagefill($imageMiniature, 0, 0, $couleurFond);
imagecopyresized($imageMiniature, $imageOriginale, 0, 0, 0, 0, $largeurMin, $hauteurMin, $largeurOrigine, $hauteurOrigine);
imagejpeg($imageMiniature, $miniatureChemin, $qualite);
imagedestroy($imageMiniature);
imagedestroy($imageOriginale);
 
// Retour des infos
$retour['urlMiniature'] = sprintf($this->config['cel']['images_temp_url'], $miniatureFichier);
$retour['imageNom'] = $nomFichierOriginal;
} else {
$message = "L'image n'a pu être déplacé sur le serveur.";
}
} else {
$message = "L'image n'est pas au format JPEG.";
}
} else {
$message = "L'image n'a pu être téléversée.";
$debogage = $message.print_r($image, true);
}
} else {
if ($image['error'] == UPLOAD_ERR_FORM_SIZE) {
$message = "L'image téléversée excède la taille maximum autorisée.".
"Veuillez modifier votre image avant de la téléverser à nouveau.";
} else {
$message = "Une erreur de transfert a eu lieu (téléversement interrompu).";
}
$debogage = "Code erreur : {$image['error']}. ".
"Voir : http://php.net/manual/fr/features.file-upload.errors.php";
}
// Retour des infos
$retour['message'] = $message;
$retour['debogage'] = $debogage;
return $retour;
}
 
// Il ne faut pas utiliser l'index type du tableau files pour tester
// si une image est en jpeg car le type renvoyé par les navigateurs
// peut varier (ex. sous ie qui renvoie image/pjpeg
private function verifierFormatJpeg($chemin) {
// get imagesize renvoie un résultat consistant par contre
$infos = getimagesize($chemin, $infos);
return (isset($infos['mime']) && $infos['mime'] == 'image/jpeg');
}
}
?>
/branches/v2.3-faux/jrest/services/InventoryObservationList.php
New file
0,0 → 1,144
<?php
/**
* PHP Version 5.2
*
* @category PHP
* @package jrest
* @author Raphaël Droz <raphael@tela-botanica.org>
* @author Aurelien Peronnet <aurelien@tela-botanica.org>
* @copyright 2010, 2013 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @link /doc/jrest/
*
* InventoryObservationList.php
* Cas d'utilisation :
* 1: Service recherche d'observations a partir de divers critères
* a: Le service recherche les observations correspondant aux critères demandés
* b: Le service renvoie la liste des observations correspondantes
*
* 2: Service modification en masse d'observations
* a: Le service recherche les observations correspondant aux identifiants donnés
* b: Le service modifie les observations correspondantes avec les infos données en paramètres
*
* 3: Service de suppression d'observations en masse
* a: Le service recherche les observations correspondant aux critères demandés
* b: Le service supprime la liste des observations correspondantes
*/
class InventoryObservationList extends Cel {
/**
* renvoie les observations correspondant au critères de filtrage
*
* uid[0] : utilisateur obligatoire
* uid[1] : criteres de filtrage de la forme critere1=valeur1&critere2=valeur2
*/
function getElement($uid)
{
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
$chercheur_observations = new RechercheObservation($this->config);
 
$numero_page = 0;
$taille_page = 50;
$criteres = array();
 
$criteres = $_GET ;
if (isset($criteres['numero_page']) && isset($criteres['limite'])) {
$numero_page = $criteres['numero_page'];
unset($criteres['numero_page']);
$taille_page = $criteres['limite'];
unset($criteres['limite']);
}
$debut = $taille_page*$numero_page ;
 
$retour = $chercheur_observations->rechercherObservations($uid[0], $criteres, $debut, $taille_page)->get();
$retour_formate = $chercheur_observations->formaterPourEnvoiCel($retour);
 
$this->envoyerJson($retour_formate);
return true;
}
 
/**
* met à jour les métadonnées d'une liste d'observations
*
* uid[0] : utilisateur obligatoire
* uid[1] : ordres des observations à modifier séparés par des virgules
* pairs : données à mettre à jour sous la forme de clés => valeurs
*/
function updateElement($uid,$pairs) {
 
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
if (!isset($uid[1])) {
//TODO: envoyer un message d'erreur
return;
}
 
$obs = array_filter(explode(',', $uid[1]), 'is_numeric');
if(count($obs) == 0) {
return;
}
$gestionnaire_observation = new GestionObservation($this->config);
if(count($obs) == 1) {
return $gestionnaire_observation->modifierObservation($uid[0], $obs[0], $pairs);
}
 
// cas de mise à jour de multiples observations:
$ret = GestionObservation::modifierMultiplesObservation($uid[0], $obs, $pairs);
if($ret === FALSE) return FALSE; // JRest::badRequest();
if($ret === 0) {
header('HTTP/1.0 304 Not Modified');
die;
}
 
header('HTTP/1.0 200 OK'); // et non pas une 201 !
// die(); // non, car incompatible avec PHPUnit
// throw(new Exception()); // non, lance une 400 (cf JRest::updateElement())
// return TRUE; // non, lance une 201
// return FALSE; // non, lance une 400
 
die; // tant pis
}
 
/**
* Supprime une liste d'observations
*
* uid[0] : utilisateur obligatoire
* uid[1] : ordres des observations à supprimer séparés par des virgules
*/
function deleteElement($uid)
{
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
if (!isset($uid[1])) {
//TODO: envoyer un message d'erreur
return;
}
$uid[1] = rtrim($uid[1],',');
$gestionnaire_observation = new GestionObservation($this->config);
$tableau_ordres = explode(',', $uid[1]);
foreach($tableau_ordres as $ordre) {
$ids_obs[] = $gestionnaire_observation->renvoyerIdPourOrdre($uid[0], $ordre);
}
$suppression_observations = $gestionnaire_observation->supprimerObservation($uid[0],$uid[1]);
$gestion_champs_etendus = new GestionChampsEtendus($this->config, 'obs');
$champs_supp = $gestion_champs_etendus->viderParLots($ids_obs);
if ($suppression_observations) {
echo "OK";
}
exit() ;
}
}
?>
/branches/v2.3-faux/jrest/services/squelettes/image_temp.tpl.xml
New file
0,0 → 1,7
<?='<?xml version="1.0" encoding="UTF-8"?>'."\n";?>
<root>
<miniature-url><?=$urlMiniature?></miniature-url>
<image-nom><?=$imageNom?></image-nom>
<message><?=$message?></message>
<debogage><?=$debogage?></debogage>
</root>
/branches/v2.3-faux/jrest/services/squelettes/opml.tpl.xml
New file
0,0 → 1,18
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";?>
<opml version="1.0">
<head>
<text/>
</head>
<body>
<outline text="CEL">
<?php foreach ($liste_flux as $flux) : ?>
<outline title="<?=$flux['titre']?>"
description="<?=$flux['description']?>"
htmlUrl="<?=$flux['url_html']?>"
xmlUrl="<?=$flux['url_xml']?>"
type="<?=$flux['type']?>"
text="<?=$flux['texte']?>"/>
<?php endforeach; ?>
</outline>
</body>
</opml>
/branches/v2.3-faux/jrest/services/squelettes/rss1.tpl.xml
New file
0,0 → 1,45
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";?>
 
<!DOCTYPE rdf:RDF [
<!ENTITY % HTMLlat1 PUBLIC
"-//W3C//ENTITIES Latin 1 for XHTML//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
%HTMLlat1;
]>
 
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns="http://purl.org/rss/1.0/">
 
<channel rdf:about="<?=$guid?>">
<title><?=$titre?></title>
<link><?=$lien_cel?></link>
<description><?=$description?></description>
<dc:publisher><?=$editeur?></dc:publisher>
<dc:date><?=$date_maj_W3C?></dc:date>
<?php if (isset($items)) : ?>
<items>
<rdf:Seq>
<?php foreach ($items as $item) : ?>
<rdf:li resource="<?=$item['guid']?>" />
<?php endforeach; ?>
</rdf:Seq>
</items>
<?php endif; ?>
 
</channel>
<?php if (isset($items)) : ?>
<?php foreach ($items as $item) : ?>
<item rdf:about="<?=$item['guid']?>">
<title><?=$item['titre']?></title>
<link><?=(isset($item['lien'])) ? $item['lien'] : 'http://www.tela-botanica.org/'?></link>
<description><?=$item['description_encodee']?></description>
<dc:date><?=$item['date_maj_W3C']?></dc:date>
</item>
<?php endforeach; ?>
<?php endif; ?>
</rdf:RDF>
/branches/v2.3-faux/jrest/services/squelettes/rss2.tpl.xml
New file
0,0 → 1,25
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title><?=$titre?></title>
<link><?=$lien_cel?></link>
<atom:link href="<?=$lien_service?>" rel="self" type="application/rss+xml" />
<description><?=$description?></description>
<?php if (isset($items)) : ?>
<?php foreach ($items as $item) : ?>
<item>
<guid><?=$item['guid']?></guid>
<title><?=$item['titre']?></title>
<? if (isset($item['lien'])) : ?>
<link><?=$item['lien']?></link>
<? endif; ?>
<description><?=$item['description_encodee']?></description>
<category><?= $item['categorie'] ?></category>
<pubDate><?=$item['date_maj_RSS']?></pubDate>
</item>
<?php endforeach; ?>
<?php endif; ?>
</channel>
</rss>
/branches/v2.3-faux/jrest/services/squelettes/doublon_defaut.tpl.html
New file
0,0 → 1,52
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Images en doublon - <?=$utilisateur?></title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<style type="text/css">
html, body{
margin:0;
padding:0;
height: 100%;
font-family: Arial;
font-size: 12px;
}
ul{
list-style-type:none;
}
.doublon{
float:left;
}
.doublon-liste{
clear:left;
}
</style>
<!-- JavaScript -->
<script type="text/javascript" src="http://www.tela-botanica.org/commun/jquery/1.4.4/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="http://www.tela-botanica.org/commun/jquery/lazyload/1.5.0/jquery.lazyload.mini.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("img").lazyload();
});
</script>
</head>
 
<body>
<h1><?=count($doublons)?> images en doublon - <?=$utilisateur?></h1>
<ul>
<?php foreach ($doublons as $doublon) : ?>
<li class="doublon-liste">
<?php foreach ($doublon as $img) : ?>
<ul class="doublon">
<li>Image : <?=$img['img_ordre']?></li>
<li>Observation(s) : <?=implode(', ', $img['obs_ordre'])?></li>
<li><img src="<?=$img['url']?>" alt="Id #<?=$img['img_id']?>"/></li>
</ul>
<?php endforeach; ?>
</li>
<?php endforeach; ?>
</ul>
</body>
</html>
/branches/v2.3-faux/jrest/services/squelettes/atom.tpl.xml
New file
0,0 → 1,35
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><?=$titre?></title>
<link href="<?=$lien_cel?>" rel="alternate" type="text/html" hreflang="fr" />
<link href="<?=$lien_service?>" rel="self" type="application/atom+xml"/>
<updated><?=$date_maj_ATOM?></updated>
<author>
<name><?=$editeur?></name>
</author>
<id><?=$guid?></id>
<rights>Copyright (c) <?=$annee_courante?>, <?=$editeur?></rights>
<generator uri="<?=$lien_service?>" version="<?=$generateur_version?>"><?=$generateur?></generator>
 
<?php if (isset($items)) : ?>
<?php foreach ($items as $item) : ?>
<entry>
<id><?=$item['guid']?></id>
<title><?=$item['titre']?></title>
<? if (isset($item['lien'])) : ?>
<link href="<?=$item['lien']?>"/>
<? endif; ?>
<updated><?=$item['date_maj_ATOM']?></updated>
<author><name><?=$item['modifier_par']?></name></author>
<content type="xhtml" xml:lang="fr">
<div xmlns="http://www.w3.org/1999/xhtml">
<?=$item['description'];?>
</div>
</content>
</entry>
<?php endforeach; ?>
<?php endif; ?>
 
</feed>
/branches/v2.3-faux/jrest/services/CelWidgetExport.php
New file
0,0 → 1,371
<?php
/**
* Service fournissant des informations concernant le CEL au format RSS1, RSS2 ou ATOM.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
* Format du service :
* /CelWidgetExport/format
* /CelWidgetExport/csv
*
* Les paramêtres :
* - "start" indique le numéro du premier item à afficher
* - "limit" nombre d'items à afficher
*
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright 2012
*/
 
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(realpath(__FILE__))) . '/lib');
// la sortie est binaire (xls), mais OLE n'est pas compatible E_ALL en PHP-5.4
error_reporting(error_reporting() & ~E_STRICT);
require_once("lib/OLE.php");
require_once("lib/Spreadsheet/Excel/Writer.php");
 
class CelWidgetExport extends Cel {
private $nom_fichier_export = 'cel_export';
// certains paramètres apparaissent plusieurs fois car ils ont des alias
// dans certains widgets
private $parametres_autorises = array(
'id_utilisateur' => 'ce_utilisateur',
'utilisateur' => 'courriel_utilisateur',
'commune' => 'zone_geo',
'zone_geo' => 'zone_geo',
'dept' => 'departement',
'departement' => 'departement',
'lieudit' => 'lieudit',
'station' => 'station',
'projet' => 'mots_cles',
'num_taxon' => 'nt',
'date_debut' => 'date_debut',
'date_fin' => 'date_fin',
'taxon' => 'taxon',
'annee' => 'annee',
'mois' => 'mois',
'jour' => 'jour',
'recherche' => 'recherche',
'id_mots_cles' => 'id_mots_cles',
'mots_cles' => 'mots_cles',
'debut' => 'debut',
'limite' => 'limite',
'format' => 'format',
'colonnes' => 'colonnes',
'transmission' => 'transmission',
'obsids' => 'obsids',
);
private $limite_decoupage_defaut = 9000;
private $format = 'csv';
public $id_utilisateur = null;
 
// un cache, initialisé par certaines fonctions de préchargement, à la manière
// de ce qui est fait par FormateurGroupeColonne
static $cache = Array();
public function getRessource() {
return $this->getElement(array());
}
/**
* Méthode appelée avec une requête de type GET.
*/
public function getElement($params = array()) {
switch(@strtolower($params[0])) {
case 'calcul':
$this->getCalcul();
break;
case 'export':
$this->getExport();
break;
default:
$this->getExport();
}
}
private function getCalcul() {
$criteres = $this->traiterParametresAutorises($_GET);
 
$criteres['transmission'] = 1;
if($this->doitEtPeutExporterObsPrivees($criteres)) {
unset($criteres['transmission']);
$this->id_utilisateur = $criteres['id_utilisateur'];
}
$chercheur_observations = new RechercheObservation($this->config);
$numero_page = isset($criteres['debut']) ? $criteres['debut'] : 0;
$limite = isset($criteres['limite']) ? $criteres['limite'] : 0;
$colonnes = @FormateurGroupeColonne::colGroupsValidation($criteres['colonnes']);
unset($criteres['limite']);
unset($criteres['debut']);
unset($criteres['format']);
unset($criteres['colonnes']);
$nb_observations = $chercheur_observations->compterObservations(null, $criteres);
$limite_decoupage = $this->calculerNbLignesMaxParFichier();
$url_telechargements = array();
$intervalle = 0;
$params_url = $criteres;
unset($params_url['transmission']);
do {
$base_url = $this->config['settings']['baseURLAbsolu'].'CelWidgetExport/export';
$params_url['debut'] = $intervalle;
$params_url['limite'] = $limite_decoupage;
$url_telechargement_fichier = $base_url;
$url_telechargements[] = $base_url.'?'.http_build_query($params_url).'&format='.$this->format.'&colonnes='.$colonnes;
$intervalle += $limite_decoupage;
$nb_observations -= $limite_decoupage;
} while($nb_observations > 0);
$this->envoyerJson($url_telechargements);
}
private function calculerNbLignesMaxParFichier() {
$limite = $this->limite_decoupage_defaut;
switch($this->format) {
case 'csv':
$limite = 20000;
break;
case 'xls':
$limite = 8000;
break;
case 'pdf':
$limite = 300;
break;
}
return $limite;
}
private function getExport() {
$criteres = $this->traiterParametresAutorises($_GET);
// ne pas faire de super-requête en cas d'absence de paramètres
// par exemple "format", au minimum, devrait être défini
if(!$criteres) die('erreur: pas de paramètre reçu');
if(!in_array($this->format, array('pdf','csv','xls'))) die('erreur: format invalide');
 
$criteres['transmission'] = 1;
if($this->doitEtPeutExporterObsPrivees($criteres)) {
unset($criteres['transmission']);
$this->id_utilisateur = $criteres['ce_utilisateur'];
}
$chercheur_observations = new RechercheObservation($this->config);
$debut = isset($criteres['debut']) ? intval($criteres['debut']) : 0;
$limite = isset($criteres['limite']) ? intval($criteres['limite']) : 0;
$groupes = @FormateurGroupeColonne::colGroupsValidation($criteres['colonnes']);
$groupes .= ',auteur';
 
if(!$groupes) die('erreur: Ne peut identifier les groupes de champs demandés.');
 
 
if($criteres['obsids']) $criteres['sql_brut'] = sprintf('id_observation IN (%s)',
implode(',', $criteres['obsids']));
unset($criteres['limite']);
unset($criteres['debut']);
unset($criteres['format']);
unset($criteres['colonnes']);
unset($criteres['obsids']);
 
$observations = $chercheur_observations->rechercherObservations(null, $criteres, $debut, $limite, TRUE)->get();
$ids = array();
foreach($observations as &$obs) {
$ids[] = $obs['id_observation'];
}
 
if($this->format == 'pdf') {
$pdf = $this->convertirEnPdf($observations);
$pdf->pdf->Output('etiquettes.pdf', 'I');
exit;
}
 
// cas XLS et CSV: on peut avoir besoin des champs étendus, des noms communs et des champs baseflor:
 
// Obtention des colonnes correspondantes aux groupes de champs
$colonnes = FormateurGroupeColonne::nomEnsembleVersListeColonnes($groupes);
 
/*
Champs étendus et noms communs, si demandés.
* Pour "nom commun", "preload" retourne NULL, car c'est le cache statique de FormateurGroupeColonne
qu'il initialise et utilise en interne sans qu'un passage par paramètre dans le contexte de CelWidgetExport
ne soit nécessaire.
* Pour les champs étendus, c'est CelWidgetExport::$cache qui est utilisé, aussi bien pour les en-têtes que
pour les données préchargées, cf self::traiterLigneEtendue()
*/
self::$cache = FormateurGroupeColonne::preload($colonnes, $this, $ids);
 
// TODO: tous les champs étendus et les paramètres supplémentaires devraient être passés en un seul
// tableau (et chaque formateur csv, xls etc... pourrait également être dans une classe à part)
switch($this->format) {
case 'csv':
$csv = $this->convertirEnCsv($observations, $colonnes);
$this->envoyerCsv($csv);
break;
case 'xls':
$xls = $this->convertirEnXls($observations, $colonnes);
$this->envoyerXls($xls);
break;
default:
}
}
protected function traiterParametresAutorises(Array $parametres) {
$parametres_traites = array();
$this->format = (isset($parametres['format']) && $parametres['format'] != '') ? $parametres['format'] : $this->format;
foreach($parametres as $cle => $valeur) {
if(is_string($valeur) && !trim($valeur)) continue;
if(isset($this->parametres_autorises[$cle])) {
$parametres_traites[$this->parametres_autorises[$cle]] = $valeur;
}
}
$parametres_traites['obsids'] = @self::traiterObsIds($parametres['obsids']);
return $parametres_traites;
}
private function envoyerCsv($csv) {
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment;filename='.$this->nom_fichier_export.'.csv');
echo $csv;
exit;
}
private function envoyerXls($workbook) {
$workbook->close();
exit;
}
private function convertirEnCsv(&$data, $colonnes) {
$chemin_temp = "php://temp";
$outstream = fopen($chemin_temp, 'r+');
 
$intitule_champs = array_merge(FormateurGroupeColonne::getIntitulesColonnes($colonnes));
// en premier car utilisé génériquement dans getLigneObservation()
if(isset($colonnes['baseflor'])) {
$intitule_champs = array_merge($intitule_champs, FormateurGroupeColonne::$baseflor_col);
}
// en second car manuellement appellé plus bas, TODO: utiliser l'API du FormateurGroupeColonne
if(isset($colonnes['etendu'])) {
$intitule_champs = array_merge($intitule_champs, array_values(self::$cache['etendu']['header']));
}
 
// header
fputcsv($outstream, $intitule_champs, ',', '"');
// lignes
foreach($data as &$ligne) {
$ligne = self::filtrerDonneesSensibles($ligne);
$ligne = FormateurGroupeColonne::getLigneObservation($ligne, $colonnes, $this);
fputcsv($outstream, $ligne, ',', '"');
}
rewind($outstream);
$csv = stream_get_contents($outstream);
fclose($outstream);
return $csv;
}
private function convertirEnXls(&$data, $colonnes) {
$this->extendSpreadsheetProductor = new SpreadsheetProductor();
$this->extendSpreadsheetProductor->initSpreadsheet();
$workbook = new Spreadsheet_Excel_Writer();
// avant la définition du titre de la worksheet !
$workbook->setVersion(8);
 
$worksheet = $workbook->addWorksheet('Liste');
$workbook->setTempDir($this->config['cel']['chemin_stockage_temp']);
$worksheet->setInputEncoding('utf-8');
$workbook->send($this->nom_fichier_export.'.xls');
$nb_lignes = 1;
 
$intitule_champs = array_merge(FormateurGroupeColonne::getIntitulesColonnes($colonnes));
// en premier car utilisé génériquement dans getLigneObservation()
if(isset($colonnes['baseflor'])) {
$intitule_champs = array_merge($intitule_champs, FormateurGroupeColonne::$baseflor_col);
}
// en second car manuellement appellé plus bas, TODO: utiliser l'API du FormateurGroupeColonne
if(isset($colonnes['etendu'])) {
$intitule_champs = array_merge($intitule_champs, array_values(self::$cache['etendu']['header']));
}
 
// header
$indice = 0;
foreach ($intitule_champs as &$intitule) {
$worksheet->write(0,$indice++,$intitule);
}
 
foreach($data as &$ligne) {
$ligne = self::filtrerDonneesSensibles($ligne);
$ligne = FormateurGroupeColonne::getLigneObservation($ligne, $colonnes, $this);
$indice = 0;
foreach($ligne as &$champ) {
$worksheet->write($nb_lignes,$indice++,$champ);
}
$nb_lignes++;
}
return $workbook;
}
private function convertirEnPdf(&$observations) {
if(count($observations) > 300) die('erreur: trop de données');
//require_once('GenerateurPDF.php');
$pdf = new GenerateurPDF();
$pdf->export($observations);
return $pdf;
}
static function filtrerDonneesSensibles($ligne) {
if(stripos($ligne['mots_cles_texte'], 'sensible') !== false) {
$ligne['latitude'] = '';
$ligne['longitude'] = '';
}
return $ligne;
}
private function doitEtPeutExporterObsPrivees($criteres) {
return isset($criteres['ce_utilisateur']) &&
$this->peutExporterObsPrivees($criteres['ce_utilisateur']);
}
private function peutExporterObsPrivees($id_utilisateur) {
$gestion_utilisateur = new User($this->config);
$utilisateur = $gestion_utilisateur->obtenirIdentiteConnectee();
return ! empty($utilisateur['id_utilisateur']) && $id_utilisateur == $utilisateur['id_utilisateur'];
}
 
static function traiterObsIds($range_param) {
if (!isset($range_param)) return NULL;
// trim() car: `POST http://url<<<"range=*"`
if (trim($range_param) == '*') return NULL;
return self::rangeToList(trim($range_param));
}
 
/*
* @param $fieldSets: un range, eg: 1-5,8,32,58-101
* @return un tableau trié, eg: 1,2,3,4,5,8,32,58,...,101
* http://stackoverflow.com/questions/7698664/converting-a-range-or-partial-array-in-the-form-3-6-or-3-6-12-into-an-arra
*/
static function rangeToList($in = '') {
$inSets = explode(',', trim($in, ','));
$outSets = array();
 
foreach($inSets as $inSet) {
list($start,$end) = explode('-', $inSet . '-' . $inSet);
// ignore les ranges trop importants
if($start > 10000000 || $end > 10000000 || abs($start-$end) > 10000) continue;
$outSets = array_merge($outSets,range($start,$end));
}
$outSets = array_unique($outSets);
$outSets = array_filter($outSets, 'is_numeric');
sort($outSets);
return $outSets;
}
}
?>
/branches/v2.3-faux/jrest/services/InventoryImportExcel.php
New file
0,0 → 1,673
<?php
// In : utf8
// Out : utf8
 
// TODO : doublons
 
/**
Octobre 2010 David Delon.
Import d'observations dans le carnet en ligne à partir d'un fichier excel chargé par l'utilisateur
et liaison d'images déjà chargee aux observations ainsi crées.
 
Nom des colonnes imposé, mais présence de toutes les colonnes non obligatoires, ordre non imposé
Aucune valeur dans les colonnes n'est obligatoire
Pour une ligne donnée, si tous les champs vides on ne fait rien, ou si seul le champ image est présent.
Si la seule différence entre deux lignes est la valeur de la colonne image, on considère que c'est la même observation à laquelle on associe plusieurs images.
Si au moins deux lignes (ou plus) sont complètement identiques on prend en compte une seule ligne (les doublons sont éliminés).
**/
 
// Nom des colonnes
 
define('COMMUNE','commune'); // soit un nom de commune, soit un code INSEE (5 chiffres), ou "nom de commune (numero departement)"
define('LIEUDIT','lieu-dit'); // Texte libre
define('STATION','station'); // Texte libre
define('MILIEU','milieu'); // Texte libre
define('LATITUDE','latitude'); // En decimal systeme WGS84
define('LONGITUDE','longitude'); // En decimal systeme WGS84
define('NOTES','notes'); // Texte libre
define('DATEOBS','date'); // date au format jj/mm/aaaa
define('ESPECE','espece'); // texte libre, nom latin, ou code nomenclatural (format BDNFFnn999999)
define('IMAGE','image'); // nom des fichiers images préalablement uploadés sur le CEL séparés par des "/"
define('DEPARTEMENT','departement'); // Texte libre
define('TRANSMETTRE','transmettre'); // "1" ou "oui", toute autre valeur (y compris vide) sera consideree comme "non""
 
 
// Resultat de l'analyse d'une ligne
define('LIGNE_VIDE',1); //
define('LIGNE_NORMALE',2); //
define('LIGNE_IMAGE_SEULEMENT',3); //
 
 
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(realpath(__FILE__))) . '/lib');
// la sortie est binaire (xls), mais OLE n'est pas compatible E_ALL en PHP-5.4
error_reporting(-1); //error_reporting() ^ E_STRICT);
require_once("ExcelReader/excel_reader2.php");
 
//TODO: refactoriser entièrement cette classe
class InventoryImportExcel extends Cel {
 
// Element constituant une observation
var $format_observation=array(COMMUNE ,LIEUDIT ,STATION , DEPARTEMENT, MILIEU ,LATITUDE ,LONGITUDE ,NOTES ,DATEOBS ,ESPECE ,TRANSMETTRE, IMAGE );
 
// Dernier numero d'ordre utilise
var $dernier_ordre = 1;
var $cpt_images_liees = 0;
var $utilisateur = array();
var $chercheur_infos_taxon;
 
/**
Constructeur
**/
function InventoryImportExcel($config) {
 
parent::__construct($config);
$this->chercheur_infos_taxon = new RechercheInfosTaxonBeta($config);
}
 
/**
Sur post
**/
function createElement($pairs) {
 
if(!isset($pairs['utilisateur']) || trim($pairs['utilisateur']) == '') {
echo '0'; exit;
}
if(!isset($_SESSION)) {session_start();}
$this->controleUtilisateur($pairs['utilisateur']);
$this->utilisateur = $this->getInfosComplementairesUtilisateur($pairs['utilisateur']);
 
foreach($_FILES as $file) { // C'est le plus simple
$infos_fichier = $file ;
}
// Chargement tableau en memoire
$data = new Spreadsheet_Excel_Reader($infos_fichier['tmp_name'], true); // false : pour menager la memoire.
$arr = array();
 
$rowcount=$data->rowcount(0);
$colcount=$data->colcount(0);
 
if ($rowcount<=1) { // TODO : retour erreur
print "Tableau vide";
exit;
}
 
// Chargement tableau
for($row=1;$row<=$rowcount;$row++)
for($col=1;$col<=$colcount;$col++)
$arr[$col][$row] = $data->val($row,$col,0); // Attention, inversion voulue
// 1 : Traitement intitules
$line = array();
 
/* Les colonnes ne sont pas forcemment dans l'ordre : on les extrait pour traitement futur */
for($col=1;$col<=$colcount;$col++) {
$colonne=strtolower($arr[$col][1]);
$colonne=trim($colonne);
$colonne=iconv('UTF-8', 'ASCII//TRANSLIT', $colonne);
switch ($colonne) { // On ne garde que les colonnes que l'on souhaite traiter
case COMMUNE:
case LIEUDIT:
case STATION:
case MILIEU:
case DEPARTEMENT:
case LATITUDE:
case LONGITUDE:
case NOTES:
case DATEOBS:
case ESPECE:
case TRANSMETTRE:
case IMAGE:
$selection=array_values($arr[$col]);
array_shift($selection); // On ne garde pas la premiere ligne, qui contient les intitules
$line[$colonne]=$selection;
break;
 
}
}
// 1 : Traitement lignes
$cpt_obs=0;
$cpt_img=0;
 
/* Recherche dernier numero d'ordre utilise : pas de mise a jour concurente a priori */
$requete = "SELECT MAX(ordre) AS ordre FROM cel_obs WHERE ce_utilisateur = ".Cel::db()->proteger($pairs['utilisateur'])." ";
$resultat = Cel::db()->requeter($requete);
 
if(is_array($resultat) && count($resultat) > 0) {
$this->dernier_ordre = $resultat[0]['ordre']; // 1 par defaut
}
 
for ($i=0;$i<=$rowcount-1;$i++) {
// On saute les eventuelles lignes vides du debut et les lignes contenant des information sur image uniquement
while ((in_array($retour_analyse=$this->analyserLigne($line,$i),array(LIGNE_IMAGE_SEULEMENT, LIGNE_VIDE))) && ($i<=$rowcount)) {
if ($retour_analyse==LIGNE_IMAGE_SEULEMENT) {
// image non rattachée à une observation
}
else {
// ligne vide
}
$i++;
}
while (($this->analyserLigne($line,$i)==LIGNE_NORMALE) && ($i<=$rowcount)) {
$id_obs = $this->traiterLigne($line,$i,$pairs['utilisateur']);
if ($this->dernier_ordre > 0) {
$cpt_obs++; // Compteur d'observations crees
}
$i++;
// On saute les lignes vide ou on traite les lignes suivantes contenant des informations sur image seulement
while ((in_array($retour_analyse=$this->analyserLigne($line,$i),array(LIGNE_IMAGE_SEULEMENT, LIGNE_VIDE))) && ($i<=$rowcount)) {
if ($retour_analyse==LIGNE_IMAGE_SEULEMENT) {
$this->traiterLigneComplement($line,$i,$pairs['utilisateur'],$id_obs); // images supplementaires
}
else {
// print "vide";
}
$i++;
}
}
}
$message = '';
if($this->cpt_images_liees > 0) {
$message = $this->cpt_images_liees.' images liees pour ';
}
$message .= $cpt_obs;
print $message;
}
 
function analyserLigne($line,$i) {
$ligne_vide=true;
$ligne_image_seulement=true;
$ligne_normale=true;
$ligne_identique_sauf_image = true;
foreach ($this->format_observation as $colonne) {
if($i < 1) {
$ligne_identique_sauf_image = false;
} else {
if($colonne!= IMAGE && isset($line[$colonne]) && isset($line[$colonne][$i - 1]) && isset($line[$colonne][$i])
&& $line[$colonne][$i - 1] != $line[$colonne][$i] && $line[$colonne][$i] != '') {
$ligne_identique_sauf_image = false;
}
}
if (isset ($line[$colonne][$i]) && $line[$colonne][$i]!='') {
if ($colonne!=IMAGE) {
$ligne_image_seulement=false;
$ligne_vide=false;
}
$ligne_vide=false;
}
}
if ($ligne_vide) {
return LIGNE_VIDE;
}
else {
if ($ligne_image_seulement || $ligne_identique_sauf_image) {
return LIGNE_IMAGE_SEULEMENT;
}
else {
return LIGNE_NORMALE;
}
}
}
 
function traiterLigne($line,$i,$utilisateur) {
// Controle donnee et insertion
$info_image=array();
$info_transmettre = "0";
$info_espece = array(
'nom_sel' => '',
'nom_sel_nn' => '',
'nom_ret' => '',
'nom_ret_nn' => '',
'nt' => '',
'famille' => ''
);
$info_commune = array('nom' => '', 'code' => '');
foreach ($this->format_observation as $colonne) {
if (isset ($line[$colonne][$i]) && $line[$colonne][$i]!='') {
switch ($colonne) { // On ne garde que les colonnes que l'on souhaite traiter
case COMMUNE:
$info_commune = $this->traiterCommune($line[COMMUNE][$i]);
break;
case LIEUDIT:
$info_lieudit = $this->traiterLieudit($line[LIEUDIT][$i]);
break;
case STATION:
$info_station = $this->traiterStation($line[STATION][$i]);
break;
case MILIEU:
$info_milieu = $this->traiterMilieu($line[MILIEU][$i]);
break;
case DEPARTEMENT:
$dpt = $this->traiterDepartement($line[DEPARTEMENT][$i]);
if(is_numeric($dpt) && strlen($dpt == 5) && $info_commune['code'] == 'NULL') {
$info_commune['code'] = $dpt;
}
break;
case LATITUDE:
$info_latitude = $this->traiterLatitude($line[LATITUDE][$i]);
break;
case LONGITUDE:
$info_longitude = $this->traiterLongitude($line[LONGITUDE][$i]);
break;
case NOTES:
$info_notes = $this->traiterNotes($line[NOTES][$i]);
break;
case DATEOBS:
$info_dateobs = $this->traiterDateObs($line[DATEOBS][$i]);
break;
case TRANSMETTRE:
$info_transmettre = $this->traiterTransmettre($line[TRANSMETTRE][$i]);
break;
case ESPECE:
// suppression des accents éventuels
$line[ESPECE][$i] = iconv('UTF-8', 'ASCII//TRANSLIT', $line[ESPECE][$i]);
$resultat_recherche_espece = $this->chercheur_infos_taxon->rechercherInfosSurTexteCodeOuNumTax(utf8_encode(trim($line[ESPECE][$i])));
if (isset($resultat_recherche_espece['en_id_nom']) && $resultat_recherche_espece['en_id_nom'] != '') {
$info_espece['nom_sel'] = $resultat_recherche_espece['nom_sel'];
$info_espece['nom_sel_nn'] = $resultat_recherche_espece['en_id_nom'];
$complement = $this->chercheur_infos_taxon->rechercherInformationsComplementairesSurNumNom($resultat_recherche_espece['en_id_nom']);
$info_espece['nom_ret'] = $complement['Nom_Retenu'];
$info_espece['nom_ret_nn'] = $complement['Num_Nom_Retenu'];
$info_espece['nt'] = $complement['Num_Taxon'];
$info_espece['famille'] = $complement['Famille'];
} else {
$info_espece['nom_sel'] = $line[ESPECE][$i];
}
case IMAGE:
if(isset($line[IMAGE])) {
$info_image=$this->traiterImage($line[IMAGE][$i],$utilisateur); // Image separee par des / + utilisateur
}
break;
}
}
else {
switch($colonne) {
case COMMUNE:
$info_commune['nom']="";
break;
case LIEUDIT:
$info_lieudit="";
break;
case STATION:
$info_station="";
break;
case MILIEU:
$info_milieu="";
break;
case DEPARTEMENT:
if (!isset ($info_commune['code']) || $info_commune['code']=='') {
$info_commune['code']="";
}
break;
case LATITUDE:
$info_latitude = "";
break;
case LONGITUDE:
$info_longitude = "";
break;
case NOTES:
$info_notes='';
break;
case TRANSMETTRE:
$info_transmettre = "0";
break;
}
}
}
$this->dernier_ordre++;
list($jour,$mois,$annee) = isset($info_dateobs) ? explode("/",$info_dateobs) : array(null,null,null);
$info_dateobs=$annee."-".$mois."-".$jour." 0:0:0";
$requete = "INSERT INTO cel_obs (".
"ce_utilisateur,prenom_utilisateur,nom_utilisateur,courriel_utilisateur,".
"ordre,".
"nom_sel,nom_sel_nn,nom_ret,nom_ret_nn,nt,famille,".
"zone_geo,ce_zone_geo,".
"date_observation,".
"lieudit,station, milieu, commentaire, transmission, ".
"date_creation,date_modification,latitude,longitude) ".
" VALUES(".Cel::db()->proteger($utilisateur).",".
Cel::db()->proteger($this->utilisateur['prenom']).",".
Cel::db()->proteger($this->utilisateur['nom']).",".
Cel::db()->proteger($this->utilisateur['courriel']).",".
Cel::db()->proteger($this->dernier_ordre).",".
Cel::db()->proteger($info_espece['nom_sel']).",".
Cel::db()->proteger($info_espece['nom_sel_nn']).",".
Cel::db()->proteger($info_espece['nom_ret']).",".
Cel::db()->proteger($info_espece['nom_ret_nn']).",".
Cel::db()->proteger($info_espece['nt']).",".
Cel::db()->proteger($info_espece['famille']).",".
Cel::db()->proteger($info_commune['nom']).",".
Cel::db()->proteger('INSEE-C:'.$info_commune['code']).",".
Cel::db()->proteger($info_dateobs).",".
Cel::db()->proteger($info_lieudit).",".
Cel::db()->proteger($info_station).",".
Cel::db()->proteger($info_milieu).",".
Cel::db()->proteger($info_notes).",".
Cel::db()->proteger($info_transmettre).",".
"now() , now(),".
Cel::db()->proteger($info_latitude).",".
Cel::db()->proteger($info_longitude).")";
$insertion = Cel::db()->executer($requete);
$requete_id_obs = 'SELECT id_observation FROM cel_obs WHERE ordre = '.Cel::db()->proteger($this->dernier_ordre).' AND ce_utilisateur = '.Cel::db()->proteger($utilisateur);
$resultat_id_obs = Cel::db()->requeter($requete_id_obs);
$id_obs = $resultat_id_obs[0]['id_observation'];
// creation lien image
foreach ($info_image as $pic) {
$requete_liaison = 'INSERT INTO cel_obs_images (id_image, id_observation ) VALUES ('.Cel::db()->proteger($pic['id_image']).', '.$id_obs.') ON DUPLICATE KEY UPDATE id_image = id_image ';
$liaison = Cel::db()->executer($requete_liaison);
if ($liaison !== false) {
$this->cpt_images_liees++;
} else {
return false;
}
}
return $id_obs;
}
 
function traiterLigneComplement($line,$i,$utilisateur, $id_obs = null) {
if(isset($line[IMAGE])) {
$info_image=$this->traiterImage($line[IMAGE][$i],$utilisateur); // Image separee par des / + utilisateur
// creation lien image
foreach ($info_image as $pic) {
$requete = 'INSERT INTO cel_obs_images (id_image, id_observation) VALUES ('.Cel::db()->proteger($pic['id_image']).', '.Cel::db()->proteger($id_obs).') ON DUPLICATE KEY UPDATE id_image = id_image' ;
$resultat_liaison = Cel::db()->executer($requete);
if ($resultat_liaison !== false) {
$this->cpt_images_liees++;
} else {
return false;
}
}
}
}
function traiterCommune($identifiant_commune) {
// Recherche correspondance sur nom, si pas unique, correspondance dep. sinon code insee
$identifiant_commune=trim($identifiant_commune);
preg_match('/(.*) \(([0-9][0-9]*)\)/',$identifiant_commune,$elements);
if (isset($elements[1])) { // commune + departement : montpellier (34)
$nom_commune=$elements[1];
$code_commune=$elements[2];
$requete="SELECT DISTINCT nom, code FROM cel_zones_geo WHERE nom = ".Cel::db()->proteger($nom_commune)." AND code LIKE ".Cel::db()->proteger($code_commune.'%');
}
else { // Code insee seul
preg_match('/([0-9][0-9]*)|(2A[0-9][0-9]*)|(2B[0-9][0-9]*)/',$identifiant_commune,$elements);
if (isset($elements[1])) { // code insee commune
$code_insee_commune=$elements[1];
$requete="SELECT DISTINCT nom, code FROM cel_zones_geo WHERE code = ".Cel::db()->proteger($code_insee_commune);
}
else { // Commune seule (le departement sera recupere dans la colonne departement si elle est presente, on prend le risque ici de retourner une mauvaise
// Commune
preg_match('/(.*)/',$identifiant_commune,$elements);
if (isset($elements[1])) { // commune
$nom_commune=$elements[1];
$nom_commune=trim($nom_commune);
$nom_commune=iconv('UTF-8', 'ASCII//TRANSLIT', $nom_commune);
$nom_commune=preg_replace("/ /","%",$nom_commune);
$requete="SELECT DISTINCT nom, code FROM cel_zones_geo WHERE nom like ".Cel::db()->proteger($nom_commune.'%');
}
}
}
$resultat_commune = Cel::db()->requeter($requete);
// cas de la commune introuvable dans le référentiel
if(!is_array($resultat_commune) || count($resultat_commune) == 0) {
$resultat_commune['nom'] = $identifiant_commune;
$resultat_commune['code'] = 'NULL';
} else {
$resultat_commune = $resultat_commune[0];
}
return $resultat_commune;
}
 
function traiterLieudit($lieudit) {
// texte libre
return trim($lieudit);
}
 
function traiterStation($station) {
// texte libre
return trim($station);
}
 
function traiterMilieu($milieu) {
// texte libre
return trim($milieu);
}
 
function traiterDepartement($departement) {
// texte libre
if(is_numeric($departement) && strlen($departement) == 4) {
$departement = "0"+$departement;
}
if(is_numeric($departement) && $departement <= 9) {
$departement = "0"+$departement;
}
return trim($departement);
}
 
function traiterLatitude($latitude) {
// verifier formal decimal + limite france ? TODO
return trim($latitude);
}
function traiterLongitude($longitude) {
// verifier format decimal + limite france ? TODO
return trim($longitude);
}
function traiterNotes($notes) {
// texte libre
return trim($notes);
}
function traiterDateObs($dateobs) {
// verifier jj/mm/aaaa sinon date vide TODO
$date = trim($dateobs);
if(!preg_match("#[0-9]{2}/[0-9]{2}/([0-9]{4}|[0-9]{2})#", $date)) {
$date = '00/00/0000';
}
return $date;
}
 
function traiterTransmettre($transmettre) {
$transmission = '0';
if (trim($transmettre) == "1" || trim($transmettre) == "oui") {
$transmission = '1';
}
return $transmission;
}
function traiterImage($images,$utilisateur) { // recherche id image de ce nom
$liste_images = explode("/",$images) ;
$row =array();
foreach($liste_images as $image) {
$image = iconv('UTF-8', 'ASCII//TRANSLIT', $image);
$requete = "SELECT * FROM cel_images WHERE ce_utilisateur = ".Cel::db()->proteger($utilisateur)." AND nom_original= ".Cel::db()->proteger($image);
$ligne = Cel::db()->requeter($requete);
if(is_array($ligne) && !empty($ligne)) {
$row[] = $ligne[0];
}
}
return $row;
}
}
 
function init_byte_map(){
$byte_map = array();
for($x=128;$x<256;++$x){
$byte_map[chr($x)]=utf8_encode(chr($x));
}
$cp1252_map=array(
"\x80"=>"\xE2\x82\xAC", // EURO SIGN
"\x82" => "\xE2\x80\x9A", // SINGLE LOW-9 QUOTATION MARK
"\x83" => "\xC6\x92", // LATIN SMALL LETTER F WITH HOOK
"\x84" => "\xE2\x80\x9E", // DOUBLE LOW-9 QUOTATION MARK
"\x85" => "\xE2\x80\xA6", // HORIZONTAL ELLIPSIS
"\x86" => "\xE2\x80\xA0", // DAGGER
"\x87" => "\xE2\x80\xA1", // DOUBLE DAGGER
"\x88" => "\xCB\x86", // MODIFIER LETTER CIRCUMFLEX ACCENT
"\x89" => "\xE2\x80\xB0", // PER MILLE SIGN
"\x8A" => "\xC5\xA0", // LATIN CAPITAL LETTER S WITH CARON
"\x8B" => "\xE2\x80\xB9", // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
"\x8C" => "\xC5\x92", // LATIN CAPITAL LIGATURE OE
"\x8E" => "\xC5\xBD", // LATIN CAPITAL LETTER Z WITH CARON
"\x91" => "\xE2\x80\x98", // LEFT SINGLE QUOTATION MARK
"\x92" => "\xE2\x80\x99", // RIGHT SINGLE QUOTATION MARK
"\x93" => "\xE2\x80\x9C", // LEFT DOUBLE QUOTATION MARK
"\x94" => "\xE2\x80\x9D", // RIGHT DOUBLE QUOTATION MARK
"\x95" => "\xE2\x80\xA2", // BULLET
"\x96" => "\xE2\x80\x93", // EN DASH
"\x97" => "\xE2\x80\x94", // EM DASH
"\x98" => "\xCB\x9C", // SMALL TILDE
"\x99" => "\xE2\x84\xA2", // TRADE MARK SIGN
"\x9A" => "\xC5\xA1", // LATIN SMALL LETTER S WITH CARON
"\x9B" => "\xE2\x80\xBA", // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
"\x9C" => "\xC5\x93", // LATIN SMALL LIGATURE OE
"\x9E" => "\xC5\xBE", // LATIN SMALL LETTER Z WITH CARON
"\x9F" => "\xC5\xB8" // LATIN CAPITAL LETTER Y WITH DIAERESIS
);
foreach($cp1252_map as $k=>$v){
$byte_map[$k]=$v;
}
return $byte_map;
}
 
function fix_latin($instr){
$byte_map = init_byte_map();
$ascii_char='[\x00-\x7F]';
$cont_byte='[\x80-\xBF]';
$utf8_2='[\xC0-\xDF]'.$cont_byte;
$utf8_3='[\xE0-\xEF]'.$cont_byte.'{2}';
$utf8_4='[\xF0-\xF7]'.$cont_byte.'{3}';
$utf8_5='[\xF8-\xFB]'.$cont_byte.'{4}';
$nibble_good_chars = "@^($ascii_char+|$utf8_2|$utf8_3|$utf8_4|$utf8_5)(.*)$@s";
 
if(mb_check_encoding($instr,'UTF-8'))return $instr; // no need for the rest if it's all valid UTF-8 already
$outstr='';
$char='';
$rest='';
while((strlen($instr))>0){
if(1==@preg_match($nibble_good_chars,$instr,$match)){
$char=$match[1];
$rest=$match[2];
$outstr.=$char;
}elseif(1==@preg_match('@^(.)(.*)$@s',$instr,$match)){
$char=$match[1];
$rest=$match[2];
$outstr.=$byte_map[$char];
}
$instr=$rest;
}
return $outstr;
}
 
function remove_accent($str) {
return supprimerAccents($str);
$a = array('À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î',
'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'ß',
'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î',
'ï', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Ā',
'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď',
'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ',
'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ',
'Į', 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ',
'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń', 'ń', 'Ņ', 'ņ', 'Ň', 'ň', 'ʼn', 'Ō', 'ō', 'Ŏ',
'ŏ', 'Ő', 'ő', 'Œ', 'œ', 'Ŕ', 'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ', 'ŝ',
'Ş', 'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 'ť', 'Ŧ', 'ŧ', 'Ũ', 'ũ', 'Ū', 'ū', 'Ŭ',
'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų', 'ų', 'Ŵ', 'ŵ', 'Ŷ', 'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż',
'ż', 'Ž', 'ž', 'ſ', 'ƒ', 'Ơ', 'ơ', 'Ư', 'ư', 'Ǎ', 'ǎ', 'Ǐ', 'ǐ', 'Ǒ', 'ǒ',
'Ǔ', 'ǔ', 'Ǖ', 'ǖ', 'Ǘ', 'ǘ', 'Ǚ', 'ǚ', 'Ǜ', 'ǜ', 'Ǻ', 'ǻ', 'Ǽ', 'ǽ', 'Ǿ', 'ǿ');
$b = array('A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I',
'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 's',
'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i',
'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', 'A', 'a',
'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', 'D', 'd',
'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', 'G', 'g',
'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i',
'IJ', 'ij', 'J', 'j', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'l', 'l',
'N', 'n', 'N', 'n', 'N', 'n', 'n', 'O', 'o', 'O', 'o', 'O', 'o', 'OE', 'oe', 'R',
'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't',
'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'W', 'w', 'Y',
'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', 'f', 'O', 'o', 'U', 'u', 'A', 'a', 'I',
'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'A', 'a', 'AE', 'ae', 'O', 'o');
return str_replace($a, $b, $str);
}
 
//TODO: déplacer les fonctions ci dessus et dessous dans une classe
// utilitaire
function supprimerAccents($str, $charset = 'UTF-8')
{
$str = htmlentities($str, ENT_NOQUOTES, $charset);
$str = preg_replace('#&([A-za-z])(?:acute|cedil|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $str);
$str = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $str); // pour les ligatures e.g. '&oelig;'
$str = preg_replace('#&[^;]+;#', '', $str); // supprime les autres caractères
 
return $str;
}
 
function cp1252_to_utf8($str) {
$cp1252_map = array ("\xc2\x80" => "\xe2\x82\xac",
"\xc2\x82" => "\xe2\x80\x9a",
"\xc2\x83" => "\xc6\x92",
"\xc2\x84" => "\xe2\x80\x9e",
"\xc2\x85" => "\xe2\x80\xa6",
"\xc2\x86" => "\xe2\x80\xa0",
"\xc2\x87" => "\xe2\x80\xa1",
"\xc2\x88" => "\xcb\x86",
"\xc2\x89" => "\xe2\x80\xb0",
"\xc2\x8a" => "\xc5\xa0",
"\xc2\x8b" => "\xe2\x80\xb9",
"\xc2\x8c" => "\xc5\x92",
"\xc2\x8e" => "\xc5\xbd",
"\xc2\x91" => "\xe2\x80\x98",
"\xc2\x92" => "\xe2\x80\x99",
"\xc2\x93" => "\xe2\x80\x9c",
"\xc2\x94" => "\xe2\x80\x9d",
"\xc2\x95" => "\xe2\x80\xa2",
"\xc2\x96" => "\xe2\x80\x93",
"\xc2\x97" => "\xe2\x80\x94",
"\xc2\x98" => "\xcb\x9c",
"\xc2\x99" => "\xe2\x84\xa2",
"\xc2\x9a" => "\xc5\xa1",
"\xc2\x9b" => "\xe2\x80\xba",
"\xc2\x9c" => "\xc5\x93",
"\xc2\x9e" => "\xc5\xbe",
"\xc2\x9f" => "\xc5\xb8"
);
return strtr(utf8_encode($str), $cp1252_map);
}
?>
/branches/v2.3-faux/jrest/services/NameMap.php
New file
0,0 → 1,80
<?php
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author David Delon <david.delon@clapas.net>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
 
/**
* NameMap.php
*
* in utf8
* out utf8
*
* Cas d'utilisation :
* Service recherche d'image a partir d'un numero nomenclatural
*
* 1: Le service recoit un référentiell et un numero nomenclatural
* 2: Le service recherche une carte disponible
*/
 
class NameMap extends Cel {
 
function getElement($uid){
$retour = array('');
if(isset($uid[0]) && isset($uid[1])) {
$uid[0] = $uid[0] != '' ? $uid[0] : 'bdtfx';
$retour = $this->obtenirCarteChorologie($uid[0], $uid[1]);
}
 
$this->envoyerJson($retour);
return true;
}
function obtenirCarteChorologie($referentiel_taxo, $nn) {
// TODO: gérer ici les cartes d'autres référentiels si celles si sont disponibles
$retour = array('');
$nns = array($nn);
$chercheur_infos_taxon = new RechercheInfosTaxonBeta($this->config, $referentiel_taxo);
$syns = $chercheur_infos_taxon->rechercherSynonymesSurNumNom($nn);
foreach($syns as $nn => $syn) {
$nns[] = $nn;
}
switch($referentiel_taxo) {
case 'bdtfx':
$url_service_chorologie = $this->config['eflore']['url_service_chorologie_carte'];
$url_service_chorologie = str_replace('{referentiel_choro}','chorodep',$url_service_chorologie);
$file = $url_service_chorologie.'/nn%3A'.implode(',',$nns).'?retour.format=587&retour=image%2Fpng';
$retour = array($file);
break;
case 'bdtxa':
// En attendant mieux
$url_service_chorologie = $this->config['eflore']['url_service_chorologie_carte'];
$url_service_chorologie = str_replace('{referentiel_choro}','bdtxa',$url_service_chorologie);
$file = $url_service_chorologie.'/nn%3A'.implode(',',$nns).'?retour.format=587&retour=image%2Fpng';
$retour = array($file);
break;
default:
break;
}
return $retour;
}
}
/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log$
* Revision 1.1 2008-01-30 08:57:28 ddelon
* fin mise en place mygwt
*
* Revision 1.1 2007-06-06 13:31:16 ddelon
* v0.09
*/
?>
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/branches/v2.3-faux/jrest/services/CelWidgetMapPoint.php
New file
0,0 → 1,1219
<?php
// declare(encoding='UTF-8');
/**
* Service fournissant une carte dynamique des obsertions publiques du CEL.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* Cas d'utilisation :
* /CelWidgetMap/Carte/Utilisateur : carte des observations publiques d'un utilisateur.
* /CelWidgetMap/Carte/Utilisateur/Projet : carte des observations publiques d'un utilisateur pour un projet.
* /CelWidgetMap/Carte/Utilisateur/Projet/dept : carte des observations publiques d'un utilisateur pour un projet sur un département.
* /CelWidgetMap/Carte/Utilisateur/Projet/dept/nt : carte des observations publiques d'un utilisateur pour un projet sur un département pour un taxon.
*
* Carte = Type de carte. Valeurs possible : defaut,
* Utilisateur = identifiant (= courriel) de l'utilisateur ou * pour tous les utilisateurs.
* Projet = mot-clé du projet
*
* @author Jean-Pascal MILCENT <jpm@clapas.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright © 2010, Jean-Pascal MILCENT
*/
// TODO : supprimer le TRIM quand les obs seront reliées correctements aux localisations (sur le code INSEE par exemple)
class CelWidgetMapPoint extends Cel {
const MARQUEUR_GROUPE = 'GROUPE';
const MARQUEUR_COMMUNE = 'COMMUNE';
const MARQUEUR_STATION = 'STATION';
/**
* Méthode appelée avec une requête de type GET.
*/
public function getElement($ressources) {
$retour = null;
if($this->parametres == null) {
$this->parametres = array();
}
extract($this->parametres);
//Chronometre::chrono("Avant groupage");
 
$action = array_shift($ressources);
if (isset($action)) {
$methode = $this->traiterNomMethodeGet($action);
if (method_exists($this, $methode)) {
$retour = $this->$methode($ressources);
} else {
$this->messages[] = "Ce type de ressource '$methode' n'est pas disponible.";
}
} else {
$this->messages[] = "Vous devez indiquer le type de ressource.";
}
 
//Chronometre::chrono("Apres traitement");
//echo Chronometre::afficherChrono();
if (is_null($retour)) {
$info = 'Un problème est survenu : '.print_r($this->messages, true);
$this->envoyer($info);
} else if (isset($retour['type']) && $retour['type'] == 'jsonVar') {
$this->envoyerJsonVar($retour['variable_js'], $retour['donnees']);
} else if (isset($retour['type']) && $retour['type'] == 'jsonP') {
$this->envoyerJsonp($retour['donnees']);
} else if (isset($retour['type']) && $retour['type'] == 'png') {
header("Content-type: image/png");
imagepng($retour['img']);
imagedestroy($retour['img']);
} else {
$this->envoyerJson($retour);
}
}
 
/**
* Les icones des groupes de stations
*/
public function getIconeGroupe($params) {
extract($this->parametres);
 
$chemin_marqueur = sprintf($this->config['settings']['cheminCelMarkerObsTpl'], $type);
$img = imagecreatefrompng($chemin_marqueur);
 
$noir = imagecolorallocate($img, 0, 0, 0);
$texte = (String) $nbre;
$x = (imagesx($img) - 6.0 * strlen($texte)) / 2;
$y = (imagesy($img) - 16) / 2;
 
imagestring($img, 3, $x, $y, $texte, $noir);
 
imagealphablending($img, false);
imagesavealpha($img, true);
 
return array('type' => 'png', 'img' => $img);
}
 
public function getTout($params) {
 
$emplacements = null;
$concatenation_id = "CONCAT(IFNULL(latitude,''),IFNULL(longitude,''), IFNULL(wgs84_latitude,''),IFNULL(wgs84_longitude,'')) ";
 
$requete = 'SELECT ce_zone_geo, zone_geo, station, '.
"mots_cles_texte, ".
"latitude, ".
"wgs84_latitude, ".
"longitude, ".
"wgs84_longitude, ".
$concatenation_id." as id_coord ".
'FROM cel_obs AS co '.
' LEFT JOIN cel_zones_geo AS l '.
' ON (l.nom = co.zone_geo AND l.id_zone_geo = co.ce_zone_geo) '.
"WHERE transmission = '1' ".
" AND (".
$this->construireWhereRectangleStationOR()." OR ".
$this->construireWhereRectangleCommuneOR().") ".
$this->construireWhereDept().
$this->construireWhereCommune().
$this->construireWhereUtilisateur().
$this->construireWhereNumTaxonAvecSousTaxons().
$this->construireWhereNomTaxon().
$this->construireWhereReferentiel().
$this->construireWhereDate().
$this->construireWhereCommentaire().
$this->construireWherePhotosSeulement().
$this->construireWhereProjet().
$this->construireWhereTag().
$this->construireWhereNombreDeJours().
' GROUP BY id_coord';
 
$resultats_emplacements = Cel::db()->requeter($requete);
$emplacements = $this->traiterEmplacements($resultats_emplacements, $this->compterObservations($params));
return $emplacements;
}
 
private function afficherRequeteFormatee($requete) {
$requete = str_replace(')',')<br />',$requete);
$requete = str_replace('(',' <br /> (',$requete);
echo '<pre>'.$requete.'</pre>';
exit;
}
 
private $nb_obs = 0;
 
private function compterObservations($params) {
$requete = 'SELECT COUNT(*) as nb '.
'FROM cel_obs AS co '.
' LEFT JOIN cel_zones_geo AS l '.
' ON (l.nom = co.zone_geo AND l.id_zone_geo = co.ce_zone_geo) '.
"WHERE transmission = '1' ".
" AND (".
$this->construireWhereRectangleStationOR()." OR ".
$this->construireWhereRectangleCommuneOR().") ".
$this->construireWhereDept().
$this->construireWhereCommune().
$this->construireWhereUtilisateur().
$this->construireWhereNumTaxonAvecSousTaxons().
$this->construireWhereNomTaxon().
$this->construireWhereReferentiel().
$this->construireWhereDate().
$this->construireWhereCommentaire().
$this->construireWherePhotosSeulement().
$this->construireWhereProjet().
$this->construireWhereTag().
$this->construireWhereNombreDeJours();
 
$resultats_nb_obs = Cel::db()->requeter($requete);
return $resultats_nb_obs[0]['nb'];
}
 
private function traiterEmplacements(&$emplacements, $nb_total_observation) {
$zoom = (int) array_key_exists('zoom', $this->parametres) ? $this->parametres['zoom'] : 11;
$distance = (int) array_key_exists('distance', $this->parametres) ? $this->parametres['distance'] : 20;
 
$marqueurs = array(
'stats' => array('stations' => 0, 'communes' => 0, 'observations' => 0),
'points' => null
);
 
if (isset($this->parametres['ne']) && $this->parametres['sw'] && ! $this->etreNull($this->parametres['ne']) && ! $this->etreNull($this->parametres['sw'])) {
$ne = $this->decomposerLatLng($this->parametres['ne']);
$sw = $this->decomposerLatLng($this->parametres['sw']);
$marqueurs['points'] = CartoGroupage::creerGroupesQuadtree($emplacements, $ne['lat'], $ne['lng'], $sw['lat'], $sw['lng'], $zoom);
 
// laisser la classe cartoGroupage compter les élements simplifie le comptage
// et permet de ne pas reparser le tableau pour compter les différents éléments
$nb_elements = CartoGroupage::getNbElements();
// les bornes servent à centrer la carte dans le cas ou l'on demande des paramètres précis
$marqueurs['stats']['coordmax'] = CartoGroupage::getBornes();
$marqueurs['stats']['stations'] = $nb_elements['stations'];
$marqueurs['stats']['communes'] = $nb_elements['communes'];
$marqueurs['stats']['observations'] = (int)$nb_total_observation;
} else {
$marqueurs['points'] = $emplacements;
}
 
return $marqueurs;
}
 
private function traiterStations($communes, $stations) {
$zoom = (int) array_key_exists('zoom', $this->parametres) ? $this->parametres['zoom'] : 11;
$distance = (int) array_key_exists('distance', $this->parametres) ? $this->parametres['distance'] : 20;
 
$marqueurs = array(
'stats' => array('stations' => 0, 'communes' => 0, 'observations' => 0),
'points' => null
);
$marqueurs['stats']['observations'] = $this->traiterNbreObs($communes) + $this->traiterNbreObs($stations);
 
$points = array();
if ($communes !== false) {
foreach ($communes as $commune) {
if (is_numeric($commune['lat']) && is_numeric($commune['lng'])) {
extract($commune);
$id = self::MARQUEUR_COMMUNE.':'.$lat.'|'.$lng;
$lata = round($lat, 5);
$lnga = round($lng, 5);
 
if (!isset($points[$id])) {
$points[$id]['id'] = $id;
$points[$id]['nom'] = $nom;
$points[$id]['lat'] = $lata;
$points[$id]['lng'] = $lnga;
$points[$id]['nbre'] = 1;
$marqueurs['stats']['communes']++;
} else {
$points[$id]['nbre']++;
}
}
}
}
if ($stations !== false) {
foreach ($stations as $station) {
if (is_numeric($station['lat']) && is_numeric($station['lng'])) {
extract($station);
$id = self::MARQUEUR_STATION.':'.$lat.'|'.$lng;
$lata = round($lat, 5);
$lnga = round($lng, 5);
$nom = $this->etreNull($nom) ? $lata.','.$lnga : $nom;
 
if (!isset($points[$id])) {
$points[$id]['id'] = $id;
$points[$id]['nom'] = $nom;
$points[$id]['lat'] = $lata;
$points[$id]['lng'] = $lnga;
$points[$id]['nbre'] = 1;
$marqueurs['stats']['stations']++;
} else {
$points[$id]['nbre']++;
}
}
}
}
 
if (isset($this->parametres['ne']) && $this->parametres['sw'] && ! $this->etreNull($this->parametres['ne']) && ! $this->etreNull($this->parametres['ne']) && ! $this->etreNull($this->parametres['sw'])) {
$ne = $this->decomposerLatLng($this->parametres['ne']);
$sw = $this->decomposerLatLng($this->parametres['sw']);
$marqueurs['points'] = CartoGroupage::creerGroupesQuadtree($points, $ne['lat'], $ne['lng'], $sw['lat'], $sw['lng'], $zoom);
} else {
$marqueurs['points'] = $points;
}
//$marqueurs['stats']['latDiff'] = abs($marqueurs['stats']['latMin'] - $marqueurs['stats']['latMax']);
//$marqueurs['stats']['lngDiff'] = abs($marqueurs['stats']['lngMin'] - $marqueurs['stats']['lngMax']);
 
return $marqueurs;
}
 
private function definirLatLngMaxMin(&$marqueurs, $lat, $lng) {
if ($lat != null && $lng != null) {
$marqueurs['stats']['latMin'] = $marqueurs['stats']['latMin'] > $lat ? $lat : $marqueurs['stats']['latMin'];
$marqueurs['stats']['lngMin'] = $marqueurs['stats']['lngMin'] > $lng ? $lng : $marqueurs['stats']['lngMin'];
$marqueurs['stats']['latMax'] = $marqueurs['stats']['latMax'] < $lat ? $lat : $marqueurs['stats']['latMax'];
$marqueurs['stats']['lngMax'] = $marqueurs['stats']['lngMax'] < $lng ? $lng : $marqueurs['stats']['lngMax'];
}
}
 
private function traiterNbreObs($resultats) {
$obs_nbre = 0;
if ($resultats !== false) {
$obs_nbre = count($resultats);
}
return $obs_nbre;
}
 
private function verifierLatLng($lat, $lng) {
$ok_lat = $this->etreLatitude($lat) ? true : false;
$ok_lng = $this->etreLongitude($lng) ? true : false;
$ok = $ok_lat && $ok_lng;
return $ok;
}
 
private function etreLatitude($lat) {
$ok = false;
//$format = preg_match('/^[-]?[0-9]+(?:[.][0-9]+|)$/', $lat) ? true : false;
$ok = ($lat >= -90 && $lat <= 90) ? true : false;
return $ok;
}
 
private function etreLongitude($lng) {
$ok = false;
//$format = preg_match('/^[-]?[0-9]+(?:[.][0-9]+|)$/', $lng) ? true : false;
$ok = ($lng >= -180 && $lng <= 180) ? true : false;
return $ok;
}
 
private function etreObsSensible($tags) {
$sensible = true;
if (stristr($tags, 'sensible') === FALSE) {
$sensible = false;
}
return $sensible;
}
 
private function communeEstDemandee() {
$station_infos = $this->decomposerParametreStation();
$commune_demandee = true;
if($station_infos['type'] == self::MARQUEUR_STATION) {
$commune_demandee = false;
}
return $commune_demandee;
}
 
/**
* Données pour l'affichage des obs d'une station
*/
public function getObservations($params) {
$resultats = array();
$total = 0;
if (isset($this->parametres['station']) && !$this->etreNull($this->parametres['station'])) {
$requete = 'SELECT SQL_CALC_FOUND_ROWS id_observation, ce_utilisateur, courriel_utilisateur, nom_utilisateur, prenom_utilisateur, '.
' nom_sel, nom_ret, nom_sel_nn, nom_ret_nn, nt, famille, '.
' lieudit, zone_geo, date_observation, milieu, commentaire, '.
' utm_secteur, utm_x, utm_y, code, date_transmission, nom_referentiel '.
'FROM cel_obs AS co '.
' LEFT JOIN cel_zones_geo AS l '.
" ON (l.nom = co.zone_geo AND l.id_zone_geo = co.ce_zone_geo) ".
"WHERE transmission = '1' ".
(($this->communeEstDemandee()) ? $this->construireWhereCommuneSansCoordonneesAvecSensibles() : $this->construireWhereCoordonneesSansSensibles()).
$this->construireWhereDept().
$this->construireWhereUtilisateur().
$this->construireWhereNumTaxonAvecSousTaxons().
$this->construireWhereNomTaxon().
$this->construireWhereReferentiel().
$this->construireWhereDate().
$this->construireWhereCommentaire().
$this->construireWherePhotosSeulement().
$this->construireWhereProjet().
$this->construireWhereTag().
$this->construireWhereNombreDeJours().
'ORDER BY nom_sel ASC '.
"LIMIT {$this->start},{$this->limit} ";
//echo $requete;exit;
$resultats = Cel::db()->requeter($requete, self::SQL_RETOUR_COMPLET, self::SQL_MODE_OBJET);
$requete = 'SELECT FOUND_ROWS()';
$total = (int) Cel::db()->requeter($requete, self::SQL_RETOUR_COLONNE);
}
 
// Post-traitement
$observations = $this->traiterObservations($resultats, $total);
$observations = $this->ajouterImagesAuxObs($observations);
$observations = $this->ajouterAuteursAuxObs($observations);
$observations = $this->supprimerIdDesObs($observations);
 
return $observations;
}
 
private function traiterObservations($donnees, $total) {
$observations = array('commune' => '', 'observations' => array(), 'observateurs' => array());
$observations['total'] = (isset($total)) ? $total : 0;
if (is_array($donnees) && count($donnees) > 0) {
foreach ($donnees as $donnee) {
//echo '<pre>'.print_r($donnee,true).'</pre>';exit;
$observation = array();
$observation['idObs'] = $donnee->id_observation;
$observation['nn'] = $this->etreNull($donnee->nom_sel_nn) ? null : $donnee->nom_sel_nn;
$observation['nomSci'] = $this->nettoyerTexte($donnee->nom_sel);
$observation['date'] = ($donnee->date_observation != '0000-00-00 00:00:00') ? $this->formaterDate($donnee->date_observation, '%d/%m/%Y') : '';
$observation['datePubli'] = $this->formaterDate($donnee->date_transmission);
$observation['lieu'] = $this->traiterLieu($donnee);
$observation['observateur'] = $donnee->courriel_utilisateur;
$observation['observateurId'] = $donnee->ce_utilisateur;
$observation['urlEflore'] = $this->getUrlEflore($donnee->nom_referentiel, $donnee->nom_sel_nn);
 
if (isset($donnee->zone_geo)) {
$observations['commune'] = $this->nettoyerTexte($donnee->zone_geo);
}
$observations['observations'][$donnee->id_observation] = $observation;
 
if (! array_key_exists($donnee->ce_utilisateur, $observations['observateurs'])) {
$observations['observateurs'][$donnee->courriel_utilisateur] = $donnee->courriel_utilisateur;
}
}
}
return $observations;
}
 
private function traiterLieu($donnee) {
$lieu = array();
if (!$this->etreNull($donnee->lieudit)) {
$lieu[] = $donnee->lieudit;
}
if (!$this->etreNull($donnee->milieu)) {
$lieu[] = $donnee->milieu;
}
return implode(', ', $lieu);
}
 
private function chargerImages(Array $obs_ids) {
// Récupération des données au format Json
$service = 'CelImage/liste-ids?obsId='.implode(',', $obs_ids);
$url = sprintf($this->config['settings']['baseURLServicesCelTpl'], $service);
$json = $this->getRestClient()->consulter($url);
$donnees = json_decode($json);
 
// Post-traitement des données
$images = $this->traiterImages($donnees);
 
return $images;
}
 
private function traiterImages($donnees) {
$images = array();
if (count($donnees) > 0) {
foreach ($donnees as $id_obs => $id_images) {
foreach ($id_images as $id_img) {
$urls['idImg'] = $id_img;
$urls['guid'] = sprintf($this->config['settings']['guidImgTpl'], $id_img);
$urls['miniature'] = $this->getUrlImage($id_img, 'CXS');
$urls['normale'] = $this->getUrlImage($id_img, 'XL');
$images[$id_obs][] = $urls;
}
}
}
return $images;
}
 
private function ajouterImagesAuxObs($observations) {
$images = $this->chargerImages(array_keys($observations['observations']));
foreach ($observations['observations'] as $id => $infos) {
if(isset($images[$id])) {
$infos['images'] = $images[$id];
$observations['observations'][$id] = $infos;
}
}
return $observations;
}
 
private function ajouterAuteursAuxObs($observations) {
$observateurs = $this->recupererUtilisateursIdentite(array_keys($observations['observateurs']));
unset($observations['observateurs']);
foreach ($observations['observations'] as $id => $infos) {
$courriel = strtolower($infos['observateur']);
if(isset($observateurs[$courriel])) {
$infos['observateur'] = $observateurs[$courriel]['intitule'];
$infos['observateurId'] = $observateurs[$courriel]['id'];
}
$observations['observations'][$id] = $infos;
}
return $observations;
}
 
private function supprimerIdDesObs($observations) {
// Le tableau de sortie ne doit pas avoir les id des obs en clé car sinon Jquery Template ne fonctionne pas
$observationSansId = $observations;
unset($observationSansId['observations']);
foreach ($observations['observations'] as $id => $infos) {
$observationSansId['observations'][] = $infos;
}
return $observationSansId;
}
 
/**
* Liste des taxons présents sur la carte
*/
public function getTaxons($params) {
$json = null;
 
$requete = 'SELECT SQL_CALC_FOUND_ROWS DISTINCT nom_ret, nom_ret_nn, nt, famille '.
'FROM cel_obs AS co '.
' LEFT JOIN cel_zones_geo AS l '.
' ON (l.nom = co.zone_geo AND l.id_zone_geo = co.ce_zone_geo) '.
"WHERE transmission = '1' ".
" AND nom_ret != '' ".
$this->construireWhereDept().
$this->construireWhereCommune().
$this->construireWhereUtilisateur().
$this->construireWhereNumTaxon().
$this->construireWhereNomTaxon().
$this->construireWhereReferentiel().
$this->construireWhereDate().
$this->construireWhereCommentaire().
$this->construireWherePhotosSeulement().
$this->construireWhereProjet().
$this->construireWhereTag().
$this->construireWhereNombreDeJours().
'ORDER BY nom_ret ASC '.
"LIMIT {$this->start},{$this->limit} ";
//$this->debug[] = $requete;
$resultats = Cel::db()->requeter($requete, self::SQL_RETOUR_COMPLET, self::SQL_MODE_OBJET);
//echo $requete;exit;
$requete = 'SELECT FOUND_ROWS()';
$taxons['total'] = (int) Cel::db()->requeter($requete, self::SQL_RETOUR_COLONNE);
 
// Post-traitement
$taxons['taxons'] = $this->traiterTaxons($resultats);
 
return $taxons;
}
 
private function traiterTaxons($donnees) {
$taxons = array();
if (is_array($donnees) && count($donnees) > 0) {
foreach ($donnees as $donnee) {
if (!isset($taxons[$donnee->nt]) && ! $this->etreNull($donnee->nom_ret)) {
$taxon = array();
$taxon['nn'] = $donnee->nom_ret_nn;
$taxon['nt'] = $donnee->nt;
$taxon['nom'] = $this->nettoyerTexte($donnee->nom_ret);
$taxon['famille'] = $this->nettoyerTexte($donnee->famille);
$taxons[$donnee->nt] = $taxon;
}
}
}
$taxons = array_values($taxons);
return $taxons;
}
 
private function construireWhereCoordonnees() {
$sql = '';
// Récupération des coordonnées depuis l'id station
extract($this->decomposerParametreStation());
if (isset($type)) {
if ($type == self::MARQUEUR_COMMUNE) {
$lat = Cel::db()->proteger($lat.'%');
$lng = Cel::db()->proteger($lng.'%');
$sql = " AND wgs84_latitude LIKE $lat AND wgs84_longitude LIKE $lng ";
} else if ($type == self::MARQUEUR_STATION) {
$lat = Cel::db()->proteger($lat.'%');
$lng = Cel::db()->proteger($lng.'%');
$sql = " AND (latitude LIKE $lat AND longitude LIKE $lng) ";
}
}
return $sql;
}
 
private function construireWhereCoordonneesSansSensibles() {
$sql = '(';
// Récupération des coordonnées depuis l'id station
extract($this->decomposerParametreStation());
if (isset($type)) {
if ($type == self::MARQUEUR_COMMUNE) {
$lat = Cel::db()->proteger($lat);
$lng = Cel::db()->proteger($lng);
$sql = " AND wgs84_latitude LIKE $lat AND wgs84_longitude LIKE $lng ";
} else if ($type == self::MARQUEUR_STATION) {
$lat = Cel::db()->proteger($lat.'%');
$lng = Cel::db()->proteger($lng.'%');
$sql = " AND (latitude LIKE $lat AND longitude LIKE $lng) ";
}
}
$sql .= ' AND (mots_cles_texte IS NULL OR mots_cles_texte NOT LIKE "%sensible%" ) ';
return $sql;
}
 
private function construireWhereCommentaire() {
$sql = '';
list($type, $commentaire) = $this->decomposerParametreCommentaire();
if (!$this->etreNull($commentaire)) {
$commentaire = Cel::db()->proteger('%'.$commentaire.'%');
switch ($type) {
case '*' :
$sql = $this->obtenirConditionPourCommentaires($commentaire);
$sql = " AND (commentaire LIKE $commentaire OR ($sql)) ";
break;
case 'observation' :
$sql = " AND commentaire LIKE $commentaire ";
break;
case 'photo' :
$sql = ' AND '.$this->obtenirConditionPourCommentaires($commentaire).' ';
break;
case 'photo.meta' :
$sql = ' AND '.$this->obtenirConditionPourCommentaireMeta($commentaire).' ';
break;
case 'photo.utilisateur' :
$sql = ' AND '.$this->obtenirConditionPourCommentaireUtilisateur($commentaire).' ';
break;
default:
$sql = " AND commentaire LIKE $commentaire ";
}
}
return $sql;
}
 
 
private function construireWhereNomTaxon() {
$sql = '';
list($type, $nom) = $this->decomposerParametreTaxon();
if (!$this->etreNull($nom)) {
$nom = Cel::db()->proteger($nom.'%');
switch ($type) {
case '*' :
$sql = " AND (nom_ret LIKE $nom OR nom_sel LIKE $nom OR famille LIKE $nom) ";
break;
case 'retenu' :
$sql = " AND nom_ret LIKE $nom ";
break;
case 'selectionne' :
$sql = " AND nom_sel LIKE $nom ";
break;
case 'famille' :
$sql = " AND famille LIKE $nom ";
break;
default:
$sql = " AND nom_ret LIKE $nom ";
}
}
return $sql;
}
 
private function construireWhereReferentiel() {
$sql = '';
extract($this->parametres);
if (isset($referentiel) && !$this->etreNull($referentiel)) {
$referentiel = Cel::db()->proteger($referentiel.'%');
$sql = ' AND co.nom_referentiel LIKE '.$referentiel.' ';
}
return $sql;
}
 
private function construireWhereDate() {
$sql = '';
// Récupération des coordonnées depuis l'id station
list($type, $date) = $this->decomposerParametreDate();
 
if (!$this->etreNull($date)) {
$date = Cel::db()->proteger($date.'%');
switch ($type) {
case '*' :
$sql = " AND (
date_observation LIKE $date
OR date_creation LIKE $date
OR date_modification LIKE $date
OR date_transmission LIKE $date) ";
break;
case 'observation' :
$sql = " AND date_observation LIKE $date ";
break;
case 'creation' :
$sql = " AND date_creation LIKE $date ";
break;
case 'modification' :
$sql = " AND date_modification LIKE $date ";
break;
case 'transmission' :
$sql = " AND date_transmission LIKE $date ";
break;
case 'photo' :
$sql = $this->obtenirConditionPourDatePhoto($date);
break;
case 'ajout' :
$sql = $this->obtenirConditionPourDateAjout($date);
break;
case 'liaison' :
$sql = $this->obtenirConditionPourDateLiaison($date);
break;
default:
$sql = " AND date_observation LIKE $date ";
}
}
return $sql;
}
 
private function obtenirConditionPourDatePhoto($date) {
$observations = $this->obtenirObsLieesImg('date.photo', $date);
if (is_null($observations)) {
$this->debug[] = "Aucune observation n'est liée à une photo prise à la date : $date";
}
$sql = $this->assemblerObsEnConditionSql($observations);
return $sql;
}
 
private function obtenirConditionPourDateLiaison($date) {
$observations = $this->obtenirObsLieesImg('date.liaison', $date);
if (is_null($observations)) {
$this->debug[] = "Aucune observation n'a été liée à une image à à la date : $date";
}
$sql = $this->assemblerObsEnConditionSql($observations);
return $sql;
}
 
private function obtenirConditionPourDateAjout($date) {
$observations = $this->obtenirObsLieesImg('date.ajout', $date);
if (is_null($observations)) {
$this->debug[] = "Aucune observation n'est liée à une image ajoutée à la date : $date";
}
$sql = $this->assemblerObsEnConditionSql($observations);
return $sql;
}
 
private function obtenirConditionPourCommentaireMeta($commentaire) {
$observations = $this->obtenirObsLieesImg('commentaire.meta', $commentaire);
if (is_null($observations)) {
$this->debug[] = "Aucune observation n'est liée à une image dont le commentaire des méta-données correspond à : $commmentaire";
}
$operateur = '';
$sql = $this->assemblerObsEnConditionSql($observations, $operateur);
return $sql;
}
 
private function obtenirConditionPourCommentaireUtilisateur($commentaire) {
$observations = $this->obtenirObsLieesImg('commentaire.utilisateur', $commentaire);
if (is_null($observations)) {
$this->debug[] = "Aucune observation n'est liée à une image dont le commentaire des utilisateur correspond à : $commmentaire";
}
$operateur = '';
$sql = $this->assemblerObsEnConditionSql($observations, $operateur);
return $sql;
}
 
private function obtenirConditionPourCommentaires($commentaire) {
$observations = $this->obtenirObsLieesImg('commentaire.*', $commentaire);
if (is_null($observations)) {
$this->debug[] = "Aucune observation n'est liée à une image dont un des commentaires correspond à : $commmentaire";
}
$operateur = '';
$sql = $this->assemblerObsEnConditionSql($observations, $operateur);
return $sql;
}
 
/**
* Récupération des identifiant d'utilisateur et des ordres des observations correspondant à une date.
* Retour sous forme de tableau : array[identifiant] = array(ordre, ordre...);
*/
private function obtenirObsLieesImg($type, $param) {
// Construction de la requête
$requete = 'SELECT DISTINCT co.id_obs, ci.ce_utilisateur AS utilisateur '.
'FROM cel_images '.
' LEFT JOIN cel_obs_images coi '.
' ON (ci.id_image = coi.id_image) '.
' LEFT JOIN cel_obs AS co '.
' ON (coi.id_observation = co.id_observation) '.
' LEFT JOIN cel_zones_geo AS l '.
' ON (l.nom = co.zone_geo AND l.id_zone_geo = co.ce_zone_geo) '.
"WHERE transmission = '1' ".
($type == 'date.photo' ? " AND (ci_meta_date_time LIKE ".str_replace('-', ':', $param)." OR ci_meta_date LIKE $param) " : '').
($type == 'date.ajout' ? " AND ci_meta_date_ajout LIKE $param " : '').
($type == 'date.liaison' ? " AND coi_date_liaison LIKE $param " : '').
($type == 'commentaire.meta' ? " AND ci_meta_comment LIKE $param " : '').
($type == 'commentaire.utilisateur' ? " AND ci_meta_user_comment LIKE $param " : '').
($type == 'commentaire.*' ? " AND (ci_meta_comment LIKE $param OR ci_meta_user_comment LIKE $param) " : '').
$this->construireWhereCoordonnees().
$this->construireWhereDept().
$this->construireWhereCommune().
$this->construireWhereUtilisateur().
$this->construireWhereNumTaxon().
$this->construireWhereNomTaxon().
$this->construireWhereReferentiel().
$this->construireWhereProjet().
$this->construireWhereTag().
'ORDER BY utilisateur ASC, ordre ASC';
//$this->debug[] = $requete;
//die($requete);
$resultats = Cel::db()->requeter($requete);
 
$observations = null;
if ($resultats != false) {
$observations = array();
foreach ($resultats as $occurence) {
$utilisateur = $occurence['utilisateur'];
$ordre = $occurence['ordre'];
if (!array_key_exists($utilisateur, $observations)) {
$observations[$utilisateur] = array();
}
if (!array_key_exists($ordre, $observations[$utilisateur])) {
$observations[$utilisateur][$ordre] = $ordre;
}
}
}
return $observations;
}
 
private function assemblerObsEnConditionSql($observations, $operateur = 'AND') {
$sql = '';
if ($observations != null) {
// Pré-construction du where de la requête
$tpl_where = "(identifiant = '%s' AND ordre IN (%s))";
foreach ($observations as $utilisateur => $ordres) {
$morceaux_requete[] = sprintf($tpl_where, $utilisateur, implode(',', $ordres));
}
if (count($morceaux_requete) > 0) {
$sql = implode(" \nOR ", $morceaux_requete);
}
} else {
// Nous voulons que la requête ne retourne rien
$sql = "identifiant = '' AND ordre = ''";
}
$sql = " $operateur ($sql) ";
return $sql;
}
 
private function construireWhereRectangleStation() {
$sql = '';
if (isset($this->parametres['ne']) && isset($this->parametres['sw']) && ! $this->etreNull($this->parametres['ne']) && ! $this->etreNull($this->parametres['sw'])) {
$ne = $this->decomposerLatLng($this->parametres['ne']);
$sw = $this->decomposerLatLng($this->parametres['sw']);
 
$latMin = $sw['lat'];
$lngMin = $sw['lng'];
 
$latMax = $ne['lat'];
$lngMax = $ne['lng'];
 
// ATTENTION : latitude correspond bien à la LATITUDE!
$sql = " AND (latitude != 0 AND longitude != 0) ".
" AND latitude > $latMin ".
" AND latitude < $latMax ".
" AND longitude > $lngMin ".
" AND longitude < $lngMax ";
}
return $sql;
}
 
private function construireWhereRectangleStationOR() {
$sql = '';
if (isset($this->parametres['ne']) && isset($this->parametres['sw']) && ! $this->etreNull($this->parametres['ne']) && ! $this->etreNull($this->parametres['sw'])) {
$ne = $this->decomposerLatLng($this->parametres['ne']);
$sw = $this->decomposerLatLng($this->parametres['sw']);
 
$latMin = $sw['lat'];
$lngMin = $sw['lng'];
 
$latMax = $ne['lat'];
$lngMax = $ne['lng'];
 
$sql = "( (latitude != 0 AND longitude != 0) ".
" AND latitude BETWEEN $latMin AND $latMax ".
" AND longitude BETWEEN $lngMin AND $lngMax )";
 
/*$sql = " MBRWithin(mon_point, GeomFromText('POLYGON((".$latMin.' '.$lngMin.','.
$latMax.' '.$lngMin.','.
$latMax.' '.$lngMax.','.
$latMax.' '.$lngMin.','.
$latMin.' '.$lngMin."))')) "; */
}
return $sql;
}
 
private function construireWhereRectangleCommune() {
$sql = '';
if (isset($this->parametres['ne']) && isset($this->parametres['sw']) && ! $this->etreNull($this->parametres['ne']) && ! $this->etreNull($this->parametres['sw'])) {
$ne = $this->decomposerLatLng($this->parametres['ne']);
$sw = $this->decomposerLatLng($this->parametres['sw']);
 
$latMin = $sw['lat'];
$lngMin = $sw['lng'];
 
$latMax = $ne['lat'];
$lngMax = $ne['lng'];
 
$sql = "AND wgs84_longitude != 0 AND wgs84_latitude != 0 ".
" AND wgs84_latitude BETWEEN $latMin AND $latMax ".
" AND wgs84_longitude BETWEEN $lngMin AND $lngMax ";
}
return $sql;
}
 
private function construireWhereRectangleCommuneOR() {
$sql = '';
if (isset($this->parametres['ne']) && isset($this->parametres['sw']) && ! $this->etreNull($this->parametres['ne']) && ! $this->etreNull($this->parametres['sw'])) {
$ne = $this->decomposerLatLng($this->parametres['ne']);
$sw = $this->decomposerLatLng($this->parametres['sw']);
 
$latMin = $sw['lat'];
$lngMin = $sw['lng'];
 
$latMax = $ne['lat'];
$lngMax = $ne['lng'];
 
$sql = "( wgs84_longitude != 0 AND wgs84_latitude != 0 ".
" AND wgs84_latitude BETWEEN $latMin AND $latMax ".
" AND wgs84_longitude BETWEEN $lngMin AND $lngMax )";
 
/*$sql = " MBRWithin(point_commune, GeomFromText('POLYGON((".$latMin.' '.$lngMin.','.
$latMax.' '.$lngMin.','.
$latMax.' '.$lngMax.','.
$latMax.' '.$lngMin.','.
$latMin.' '.$lngMin."))')) ";*/
}
return $sql;
}
 
private function construireWhereDept() {
$sql = '';
// Récupération des coordonnées depuis l'id station
extract($this->parametres);
if (isset($dept) && !$this->etreNull($dept)) {
$valeurs_a_proteger = explode(',',trim($dept));
foreach ($valeurs_a_proteger as $valeur) {
$valeurs_protegees[] = '(ce_zone_geo LIKE '.Cel::db()->quote('INSEE-C:'.$valeur.'%').') ';
}
$valeurs = implode(' OR ', $valeurs_protegees);
$sql = " AND ($valeurs) ";
}
return $sql;
}
 
private function construireWhereCommune() {
$sql = '';
// Récupération des coordonnées depuis l'id station
extract($this->parametres);
if (isset($this->parametres['commune']) && !$this->etreNull($commune)) {
$commune = Cel::db()->proteger($commune);
$sql = " AND zone_geo LIKE $commune";
}
if (isset($this->parametres['zonegeo']) && !$this->etreNull($zonegeo)) {
$zonegeo = Cel::db()->proteger($zonegeo);
$sql = " AND ce_zone_geo = $zonegeo";
}
return $sql;
}
 
private function construireWhereCommuneSansCoordonneesAvecSensibles() {
$sql = '';
// Récupération des coordonnées depuis l'id station
extract($this->parametres);
if (isset($this->parametres['commune']) && !$this->etreNull($commune)) {
$commune = Cel::db()->proteger($commune);
$sql = " AND zone_geo LIKE $commune";
$sql .= " AND (
(
(latitude = '000null' OR latitude = '' OR latitude = 0 OR latitude IS NULL) ".
" AND (longitude = '000null' OR longitude = '' OR longitude = 0 OR longitude IS NULL)".
')'.
' OR mots_cles_texte LIKE "%sensible%"'.
') ';
 
}
if (isset($this->parametres['zonegeo']) && !$this->etreNull($zonegeo)) {
$zonegeo = Cel::db()->proteger($zonegeo);
$sql = " AND ce_zone_geo = $zonegeo";
}
return $sql;
}
 
 
private function construireWherePhotosSeulement() {
$sql = '';
if (isset($this->parametres['photos']) && $this->parametres['photos'] == 1) {
$sql = 'AND co.id_observation IN (SELECT DISTINCT id_observation FROM cel_obs_images) ';
}
return $sql;
}
 
private function construireWhereUtilisateur() {
$sql = '';
// TODO tester si l'on recoit un id, un mail ou bien un nom ou prenom
// pour en faire une fonction polyvalente
extract($this->parametres);
if (isset($this->parametres['utilisateur']) && !$this->etreNull($utilisateur)) {
$utilisateur = Cel::db()->proteger($utilisateur);
$sql = " AND co.courriel_utilisateur = $utilisateur ";
}
return $sql;
}
 
 
private function construireWhereNumTaxon() {
$sql = '';
// Récupération des coordonnées depuis l'id station
extract($this->parametres);
if (isset($this->parametres['num_taxon']) && !$this->etreNull($num_taxon)) {
$num_taxon = Cel::db()->proteger($num_taxon);
$sql = " AND nt = $num_taxon ";
}
return $sql;
}
 
private function construireWhereNumTaxonAvecSousTaxons() {
$sql = '';
// Récupération des coordonnées depuis l'id station
extract($this->parametres);
if (isset($this->parametres['num_taxon']) && !$this->etreNull($num_taxon)) {
$sous_taxons = $this->obtenirSousTaxons($this->parametres['num_taxon']);
$num_taxon = Cel::db()->proteger($num_taxon);
if(!empty($sous_taxons)) {
$sql_in_sous_tax = implode(',', $sous_taxons);
$sql = " AND (nt = $num_taxon OR ".
"nom_sel_nn IN (".$sql_in_sous_tax.") OR ".
"nom_ret_nn IN (".$sql_in_sous_tax.") ".
") ";
}
else {
$sql = " AND nt = $num_taxon ";
}
}
return $sql;
}
 
private function obtenirSousTaxons($nt) {
$referentiel = 'bdtfx';
if(isset($this->parametres['referentiel']) && $this->parametres['referentiel'] != "" && $this->parametres['referentiel'] != '*') {
$referentiel = $this->parametres['referentiel'];
}
$nn_sous_taxons = array();
$sous_taxons = $this->obtenirSousTaxonsPourNt($referentiel, $nt);
foreach($sous_taxons as $sous_tax) {
$nn_sous_taxons[] = $sous_tax['num_nom'];
}
return $nn_sous_taxons;
}
 
private function construireWhereProjet() {
$sql = '';
// Récupération des coordonnées depuis l'id station
extract($this->parametres);
$projet_sql = isset($projet) ? $this->getSqlWhereProjet($projet) : null;
if (!$this->etreNull($projet_sql)) {
$sql = " AND ($projet_sql) ";
}
return $sql;
}
 
/**
* Traitement de $projet pour construction du filtre dans la requête
*/
private function getSqlWhereProjet($projet) {
$sql = null;
if (isset($projet) && !$this->etreNull($projet)) {
$sql = 'co.mots_cles_texte LIKE '.Cel::db()->proteger('%'.$projet.'%');
}
return $sql;
}
 
private function construireWhereTag() {
$sql = '';
extract($this->parametres);
$tag_sql = isset($tag) ? $this->getSqlWhereObsAvecImagesTaguees($tag) : null;
if (!$this->etreNull($tag_sql)) {
$sql = " AND ($tag_sql) ";
}
return $sql;
}
 
private function construireWhereNombreDeJours() {
$sql = null;
extract($this->parametres);
if (isset($nbjours) && !$this->etreNull($nbjours)) {
$sql = ' AND DATEDIFF(CURDATE(),co.date_creation) <= '.Cel::db()->proteger($nbjours).' ';
}
return $sql;
}
 
/**
* Traitement de $tag pour construction du filtre dans la requête
*/
private function getSqlWhereObsAvecImagesTaguees($tag) {
$sql = null;
if (isset($tag) && !$this->etreNull($tag)) {
$tag_sql = $this->getSqlWhereMotsCles($tag);
// Construction de la requête
$requete = 'SELECT DISTINCT coi.id_observation AS id_obs, ci.ce_utilisateur AS utilisateur '.
'FROM cel_images ci'.
' LEFT JOIN cel_obs_images coi'.
' ON (ci.id_image = coi.id_image) '.
' LEFT JOIN cel_obs AS co '.
' ON (coi.id_observation = co.id_observation) '.
' LEFT JOIN cel_zones_geo AS l '.
" ON (l.nom = co.zone_geo AND l.id_zone_geo = co.ce_zone_geo) ".
"WHERE transmission = '1' ".
$this->construireWhereCoordonnees().
$this->construireWhereUtilisateur().
$this->construireWhereNumTaxon().
$this->construireWhereNomTaxon().
$this->construireWhereReferentiel().
$this->construireWhereProjet().
(!$this->etreNull($tag_sql) ? "AND ($tag_sql) " : '').
'ORDER BY utilisateur ASC, ci.ordre ASC';
//$this->debug[] = $requete;
//die($requete);
$elements_tag = Cel::db()->requeter($requete);
 
$requete_tag = array();
if ($elements_tag != false && count($elements_tag) > 0) {
 
$filtres = array();
foreach ($elements_tag as $occurence) {
$utilisateur = $occurence['utilisateur'];
$id_obs = $occurence['id_obs'];
if (!array_key_exists($utilisateur, $filtres)) {
$filtres[$utilisateur] = array();
}
if (!array_key_exists($id_obs, $filtres[$utilisateur])) {
$filtres[$utilisateur][$id_obs] = $id_obs;
}
}
 
// Pré-construction du where de la requête
$tpl_where = "(id_observation IN (%s))";
foreach ($filtres as $utilisateur => $id_obs) {
$requete_tag[] = sprintf($tpl_where, implode(',', $id_obs));
}
 
} else {
$this->messages[] = "Aucune observation ne possède d'images avec ce mot-clé.";
}
if (count($requete_tag) > 0) {
$sql = implode(" \nOR ", $requete_tag);
}
}
return $sql;
}
 
/**
* Traitement de $tag pour construction du filtre dans la requête
*/
private function getSqlWhereMotsCles($tag) {
$sql = null;
$mots_cles = $this->decomposerParametreTag($tag);
$requete_projet = $this->getSqlWhereMotsClesImages($mots_cles);
$sql = $requete_projet;
//$this->debug[] = $sql;
return $sql;
}
 
/**
* Traitement de $tag pour construction du filtre dans la requête
*/
private function getSqlWhereMotsClesImages($mots_cles_encodes) {
$where_mots_cles_images = array();
foreach ($mots_cles_encodes['motsClesEncodesProteges'] as $mot_cle_encode) {
$where_mots_cles_images[] = "ci.mots_cles_texte LIKE $mot_cle_encode";
}
$where_mots_cles_images = implode(' '.$mots_cles_encodes['type'].' ', $where_mots_cles_images);
return $where_mots_cles_images;
}
 
private function decomposerParametreTag($tags) {
 
$mots_cles = array('type' => null, 'motsCles' => null, 'motsClesEncodesProteges' => null);
if (preg_match('/.+OU.+/', $tags)) {
$mots_cles['type'] = 'OR';
$mots_cles['motsCles'] = explode('OU', $tags);
} else if (preg_match('/.+ET.+/', $tags)) {
$mots_cles['type'] = 'AND';
$mots_cles['motsCles'] = explode('ET', $tags);
} else {
$mots_cles['motsCles'][] = $tags;
}
 
foreach ($mots_cles['motsCles'] as $mot) {
$mots_cles['motsClesEncodesProteges'][] = Cel::db()->quote('%'.$mot.'%');
}
$this->debug[] = $mots_cles;
return $mots_cles;
}
 
private function decomposerLatLng($coord) {
$lat_lng = array();
if (isset($coord)) {
list($lat, $lng) = explode('|', $coord);
$lat_lng = array('lat' => $lat, 'lng' => $lng);
}
return $lat_lng;
}
 
private function decomposerParametreStation() {
$station_infos = array();
if (isset($this->parametres['station'])) {
$station = $this->parametres['station'];
$this->debug[] = $station;
@list($type, $coord) = explode(':', $station);
@list($lat, $lng) = explode('|', $coord);
 
$station_infos = array('type' => $type, 'lat' => $lat, 'lng' => $lng);
}
return $station_infos;
}
 
private function decomposerParametreDate() {
$date_infos = array(null,null);
if (isset($this->parametres['date'])) {
$date = $this->parametres['date'];
if (strpos($date, ':')) {
list($type, $date) = explode(':', $date);
} else {
$type = 'observation';
}
 
$date = str_replace('/', '-', $date);
if (preg_match('/(^[0-9]{2})-([0-9]{2})-([0-9]{4}$)/', $date, $matches)) {
$date = $matches[3].'-'.$matches[2].'-'.$matches[1];
}
 
$date_infos = array($type, $date);
}
return $date_infos;
}
 
private function decomposerParametreTaxon() {
$nom_infos = array(null,null);
if (isset($this->parametres['taxon'])) {
$taxon = $this->parametres['taxon'];
if (strpos($taxon, ':')) {
$nom_infos = explode(':', $taxon);
} else {
$nom_infos = array('retenu', $taxon);
}
}
return $nom_infos;
}
 
private function decomposerParametreCommentaire() {
$commentaire_infos = array(null,null);
if (isset($this->parametres['commentaire'])) {
$commentaire = $this->parametres['commentaire'];
if (strpos($commentaire, ':')) {
$commentaire_infos = explode(':', $commentaire);
} else {
$commentaire_infos = array('observation', $commentaire);
}
}
return $commentaire_infos;
}
}
?>
/branches/v2.3-faux/jrest/services/InventoryKeywordTree.php
New file
0,0 → 1,92
<?php
class InventoryKeywordTree extends Cel {
//TODO : verifications des paramètres
public static $gestion_mots_cles = null;
private function getGestionMotsCles($mode) {
if(self::$gestion_mots_cles == null) {
self::$gestion_mots_cles = new GestionMotsClesChemin($this->config, $mode);
}
return self::$gestion_mots_cles;
}
public function getElement($uid) {
// Controle detournement utilisateur
$id_utilisateur = $uid[1] ;
$this->controleUtilisateur($uid[1]);
$arbre = $this->getGestionMotsCles($uid[0])->obtenirArbre($id_utilisateur);
$this->envoyerJson($arbre);
return TRUE; // compat: pourquoi renvoyer true si vide ?
}
public function updateElement($uid, $pairs) {
$id_utilisateur = $uid[1];
$this->controleUtilisateur($uid[1]);
$id_mot_cle = $pairs['id'];
$action = $pairs['action'];
if ($action == 'modification') {
$nouveau_nom = $pairs['motcle'];
$modification = $this->getGestionMotsCles($uid[0])->renommerMotCle($id_mot_cle, $nouveau_nom);
} else if ($action == 'deplacement') {
$id_pere = $pairs['parent'];
$modification = $this->getGestionMotsCles($uid[0])->deplacerMotCle($id_mot_cle, $id_pere, $id_utilisateur);
}
$modification = ($modification !== false);
if($modification) {
$this->envoyer("OK");
}
return $modification;
}
public function createElement($pairs) {
// Controle detournement utilisateur
$this->controleUtilisateur($pairs['identifiant']);
$mode = $pairs['mode'];
if($mode != 'obs' && $mode != 'images') {
return;
}
$id_utilisateur = $pairs['identifiant'];
$mot_cle = $pairs['motcle'];
$id_parent = $pairs['parent'];
$id_nouveau_mot_cle = $this->getGestionMotsCles($mode)->insererParIdParent($mot_cle, $id_parent, $id_utilisateur);
if($id_nouveau_mot_cle !== false) {
// on sort de self::createElement ==> JRest::(get|post) ==> JRest->created() qui fait header().
// or si nous dépassons ini_get(output_buffering) nous ne pouvons plus réécrire le code de retour
// HTTP, de plus, si ini_get(output_buffering) == off, nous enverrions un warning.
// d'où ce clone de JRest::created();
header('HTTP/1.0 201 Created');
echo $id_nouveau_mot_cle;
exit;
} else {
// cf ci-dessus: JRest::badRequest
header('HTTP/1.0 400 Bad Request');
exit;
}
}
public function deleteElement($uid) {
$mode = $uid[0];
$id_utilisateur = $uid[1];
$id_mot_cle = $uid[2];
$suppression = $this->getGestionMotsCles($mode)->supprimerMotCleParId($id_mot_cle, $id_utilisateur);
if($suppression) {
$this->envoyer("OK");
}
}
}
?>
/branches/v2.3-faux/jrest/services/InventoryKeyWordImageLink.php
New file
0,0 → 1,53
<?php
/**
* @category PHP
* @package jrest
* @author Aurélien Peronnet <aurelien@tela-botania.org>
* @author Raphaël Droz <raphael@tela-botania.org>
* @copyright 2010, 2013 Tela-Botanica
* @license Licence CECILL <http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
*
* Service de liaisons de mots clés à des images.
* Le service lie une ou plusieurs mots clés à une ou plusieurs images
*/
 
class InventoryKeyWordImageLink extends Cel {
public function createElement($pairs) {
// Controle detournement utilisateur
$this->controleUtilisateur($pairs['ce_utilisateur']);
if (!isset($pairs['mots_cles']) || !isset($pairs['images']) || !isset($pairs['ce_utilisateur'])) {
return;
}
$ids_images = array_filter(explode(',', $pairs['images']));
$ids_mots_cles = array_filter(explode(',', $pairs['mots_cles']));
// Pour le moment on ne peut que supprimer les mots clés et ajouter les nouveaux à cause du fonctionnement
// de l'arbre de mots clés des images
$gestion_mots_cles = new GestionMotsClesChemin($this->config,'images');
$gestion_mots_cles->supprimerToutesLiaisonsPourIdsElementsLies($ids_images);
$liaison = true;
if(!empty($ids_mots_cles)) {
$liaison = $gestion_mots_cles->lierParTableaux($ids_mots_cles, $ids_images, $pairs['ce_utilisateur']);
}
foreach($ids_images as $id_element_lie) {
//TODO: que faire si la régénération d'index texte échoue ?
$r_index = GestionMotsClesChemin::regenererIndexTexteMotCle($id_element_lie, 'images');
}
return $liaison;
}
 
public function deleteElement($uid){
// n'est jamais appelée car pour supprimer les mots clés d'une image
// on appelle createElement avec des mots clés vides
// car les mots clés images ne fonctionnent pas pareil que ceux des obs
// dans l'interface
}
}
?>
/branches/v2.3-faux/jrest/services/InventoryKeyWordObsLink.php
New file
0,0 → 1,55
<?php
/**
* @package jrest
* @author Aurélien Peronnet <aurelien@tela-botania.org>
* @copyright 2010, 2013 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
*
* Service de liaisons de mots clés à des observations.
* Le service lie une ou plusieurs mots clés à une ou plusieurs observations
*/
 
class InventoryKeyWordObsLink extends Cel {
public function getElement($uid) { }
public function createElement($pairs) {
// Controle detournement utilisateur
$this->controleUtilisateur($pairs['ce_utilisateur']);
if (!isset($pairs['mots_cles']) || !isset($pairs['observations']) || !isset($pairs['ce_utilisateur'])) {
return;
}
$ids_obs = explode(',',$pairs['observations']);
$ids_mots_cles = explode(',',$pairs['mots_cles']);
$gestion_mots_cles = new GestionMotsClesChemin($this->config,'obs');
$liaison_mot_cle = $gestion_mots_cles->lierParTableaux($ids_mots_cles, $ids_obs, $pairs['ce_utilisateur']);
foreach($ids_obs as $id_element_lie) {
$r_index = GestionMotsClesChemin::regenererIndexTexteMotCle($id_element_lie, 'obs');
}
return $liaison_mot_cle;
}
 
public function deleteElement($uid){
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
if (!isset($uid[0]) || !isset($uid[1]) || !isset($uid[2])) {
return FALSE;
}
$id_utilisateur = $uid[0];
$ids_obs = explode(',',$uid[1]);
$ids_mots_cles = explode(',', GestionMotsClesChemin::nettoyerMotsClesAvantSuppression($uid[2]));
$gestion_mots_cles = new GestionMotsClesChemin($this->config, 'obs');
 
$suppression_liaisons = $gestion_mots_cles->supprimerLiaisonsMotsCles($ids_mots_cles, $ids_obs, $id_utilisateur);
foreach($ids_obs as $id_element_lie) {
$r_index = GestionMotsClesChemin::regenererIndexTexteMotCle($id_element_lie, 'obs');
}
}
}
/branches/v2.3-faux/jrest/services/CelSyndicationObservation.php
New file
0,0 → 1,585
<?php
/**
* Service fournissant des informations concernant le CEL au format RSS1, RSS2 ou ATOM.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
* Format du service :
* /CelSyndicationObservation/liste-des-flux
* /CelSyndicationObservation/opml
* /CelSyndicationObservation/par-defaut/(rss1|rss2|atom)?start=0&limit=150
* /CelSyndicationObservation/pour-admin/(rss1|rss2|atom)?start=0&limit=150
* /CelSyndicationObservation/par-mots-cles/(rss1|rss2|atom)/mot-cle?start=0&limit=150
* /CelSyndicationObservation/par-commune/(rss1|rss2|atom)/nom-commune?start=0&limit=150
*
* Les paramêtres :
* - "start" indique le numéro du premier item à afficher
* - "limit" nombre d'items à afficher
*
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright 2010
*/
class CelSyndicationObservation extends Cel {
 
private $parametres_origines = null;
private $format = null;
private $service = null;
private $squelette = null;
private $squelette_dossier = null;
private $auteurs = array();
private $flux = array();
private $criteres = array(
'utilisateur' => 'courriel_utilisateur',
'commune' => 'zone_geo',
'dept' => 'ce_zone_geo',
'taxon' => 'nom_ret',
'num_taxon' => 'nt',
'commentaire' => 'commentaire',
'date' => 'date_observation',
'motcle' => 'tags',
'projet' => 'mots-cles');
 
/**
* Méthode appelée avec une requête de type GET.
*/
public function getElement($params = array()) {
// Initialisation des variables
$this->parametres_origines = $params;
$info = array();
$contenu = '';
 
if (! $this->etreFluxAdmin() || $this->authentifierAdmin()) {
// Pré traitement des paramêtres
$pour_bdd = false;
$p = $this->traiterParametres(array('service', 'format'), $params, $pour_bdd);
extract($p);
$this->parametres = $params;
$this->squelette_dossier = dirname(__FILE__).DIRECTORY_SEPARATOR.'squelettes'.DIRECTORY_SEPARATOR;
 
// Récupération de la liste des flux
$this->chargerListeDesFlux();
 
// Chargement du bon type de service demandé
if (isset($service)) {
$this->service = $this->traiterNomService($service);
$methode = $this->getNomMethodeService();
if (method_exists($this, $methode)) {
if (isset($format) && preg_match('/^(?:rss1|rss2|atom)$/i', $format)) {
// Mise en minuscule de l'indication du format
$this->format = strtolower($format);
// Définition du fichier squelette demandé
$this->squelette = $this->squelette_dossier.$this->format.'.tpl.xml';
} else if (isset($this->flux[$this->service])) {
$this->format = '';
$this->messages[] = "Le service CEL Syndication nécessite d'indiquer en second paramètre le format : rss1, rss2 ou atom.";
}
 
if (!isset($this->flux[$this->service]) || isset($this->format)) {
// Suppression des paramêtres inutile pour le reste des méthodes
array_shift($this->parametres);
array_shift($this->parametres);
 
// Récupération du contenu à renvoyer
$contenu = $this->$methode();
}
} else {
$this->messages[] = "Le type d'information demandé '$this->service' n'est pas disponible.";
}
} else {
$this->messages[] = "Le service CEL Syndication Observation nécessite d'indiquer en premier paramètre le type d'information demandé.";
}
}
 
// Envoie sur la sortie standard
$encodage = 'utf-8';
$mime = $this->getTypeMime();
$formatage_json = $this->getFormatageJson();
$this->envoyer($contenu, $mime, $encodage, $formatage_json);
}
 
private function getUrlBase() {
$url_base = sprintf($this->config['settings']['baseURLAbsolu'], get_class($this).'/');
return $url_base;
}
 
private function getUrlServiceBase() {
$url_service = $this->getUrlBase().implode('/', $this->parametres_origines);
return $url_service;
}
 
private function traiterNomService($nom) {
$nom = strtolower($nom);
return $nom;
}
 
private function getNomMethodeService() {
$methode = '';
$service_formate = str_replace(' ', '', ucwords(implode(' ', explode('-', $this->service))));
$methode = 'getService'.$service_formate;
return $methode;
}
 
private function getTypeMime() {
$mime = '';
$test = isset($this->format) ? $this->format : $this->service;
switch ($test) {
case 'atom' :
$mime = 'application/atom+xml';
break;
case 'rss1' :
case 'rss2' :
$mime = 'application/rss+xml';
break;
case 'opml' :
$mime = 'text/x-opml';
break;
default:
$mime = 'text/html';
}
return $mime;
}
 
private function getFormatageJson() {
$json = false;
switch ($this->service) {
case 'liste-des-flux' :
$json = true;
break;
default:
$json = false;
}
return $json;
}
 
private function getFlux($nom) {
return isset($this->flux[$nom]) ? $this->flux[$nom] : array();
}
 
private function setFlux($nom, $titre, $description) {
$url_base = $this->getUrlBase();
$formats = array('atom', 'rss2', 'rss1');
$flux = array();
foreach ($formats as $format) {
$url = $url_base.$nom.'/'.$format;
$flux[$format] = $url;
}
$this->flux[$nom] = array('titre' => $titre, 'description' => $description, 'urls' => $flux);
}
 
private function chargerListeDesFlux() {
$this->setFlux('par-defaut', 'Flux de syndication des observations publiques du CEL',
'Ce flux fournit des informations sur les observations du CEL.');
$this->setFlux('par-mots-cles', 'Flux de syndication obsolète',
"Ce flux est désormais accessible via le flux multicriteres/atom/M?tag='mot-cle'.");
$this->setFlux('par-commune','Flux de syndication obsolète',
"Ce flux est désormais accessible via le flux multicriteres/atom/M?commune='commune'.");
$this->setFlux('multicriteres','Flux de syndication des nouvelles observations publiques du CEL '.
'filtrées par un ou plusieurs critères',
"Ce flux fournit des informations sur les nouvelles observations du CEL filtrées par ".
"auteur (mail), commune (nom), departement (code postal), taxon (nom scientifique), commentaire, projet ".
"et/ou date.");
}
 
private function getServiceListeDesFlux() {
return $this->flux;
}
 
private function getServiceOpml() {
$donnees = array();
$id = 1;
foreach ($this->flux as $flux_nom => $flux){
$info = array();
$info['type'] = 'atom';
$info['titre'] = $flux['titre'];
$info['texte'] = "CEL - Obs - $flux_nom";
$info['description'] = $flux['description'];
$info['url_xml'] = $this->getUrlBase().$flux_nom.'/atom';
$info['url_html'] = $this->config['settings']['aideCelUrl'].'FluxSyndication';
$donnees['liste_flux'][] = $info;
}
 
$this->squelette = $this->squelette_dossier.'opml.tpl.xml';
$contenu = Cel::traiterSquelettePhp($this->squelette, $donnees);
return $contenu;
}
 
private function getServiceParDefaut() {
// Construction de la requête
$requete = (isset($this->distinct) ? 'SELECT DISTINCT' : 'SELECT').' * '.
'FROM cel_obs '.
(($this->etreFluxAdmin()) ? '' : 'WHERE transmission = 1 ').
'ORDER BY '.(isset($this->orderby) && (!is_null($this->orderby)) ? $this->orderby : 'date_modification DESC').' '.
"LIMIT $this->start,$this->limit ";
 
$elements = Cel::db()->requeter($requete);
 
// Création du contenu
$contenu = $this->executerService($elements);
return $contenu;
}
 
private function getServiceParMotsCles() {
$infos=array();
$infos[0]['nom_sel_nn'] = '';
$infos[0]['date_modification'] = '2011-06-28';
$donnees = $this->construireDonneesCommunesAuFlux($infos);
$donnees['items'][0]['guid'] = 0;
$donnees['items'][0]['description'] = 'Ce flux est devenu obsolète. Veuillez utiliser le flux '.
'<b>http://www.tela-botanica.org/eflore/cel2/jrest/CelSyndicationObservation/multicriteres/atom?projet=';
if (isset($this->parametres[0])) {
$donnees['items'][0]['description'] .= $this->parametres[0].'</b>';
} else {
$donnees['items'][0]['description'] .= '</b>';
}
$donnees['items'][0]['titre'] = '';
$contenu = Cel::traiterSquelettePhp($this->squelette, $donnees);
return $contenu;
}
 
private function getServiceParCommune() {
$infos=array();
$infos[0]['nom_sel_nn'] = '';
$infos[0]['date_modification'] = '2011-06-28';
$donnees = $this->construireDonneesCommunesAuFlux($infos);
$donnees['items'][0]['guid'] = 0;
$donnees['items'][0]['description'] = 'Ce flux est devenu obsolète. Veuillez utiliser le flux '.
'<b>http://www.tela-botanica.org/eflore/cel2/jrest/CelSyndicationObservation/multicriteres/atom?commune=';
if (isset($this->parametres[0])) {
$donnees['items'][0]['description'] .= $this->parametres[0].'</b>';
} else {
$donnees['items'][0]['description'] .= '</b>';
}
$donnees['items'][0]['titre'] = '';
$contenu = Cel::traiterSquelettePhp($this->squelette, $donnees);
return $contenu;
}
 
private function getServiceMultiCriteres() {
$contenu = '';
if (isset($_GET['debut'])) $this->start = $_GET['debut'];
if (isset($_GET['limite'])) $this->limit = $_GET['limite'];
 
$this->limit = ($this->limit < 1000) ? $this->limit : 1000;// Pour éviter les abus !
 
// Construction de la requête
$requete = (isset($this->distinct) ? 'SELECT DISTINCT' : 'SELECT').' * '.
'FROM cel_obs '.
'WHERE 1 AND '.(($this->etreFluxAdmin()) ? '' : ' transmission = 1 AND ');
 
if ($this->estUneRechercheGenerale()) {
$chaine_requete = $_GET['recherche'];
$requete .= $this->creerSousRequeteRechercheGenerale($chaine_requete);
} else {
$criteres = $this->traiterCriteresMultiples($_GET) ;
if (!empty($criteres)) {
$requete .= $this->creerSousRequeteRechercheParCriteres($criteres);
}
}
$requete = rtrim($requete, 'AND ');
$requete .= ' ORDER BY '.(isset($this->orderby) && (!is_null($this->orderby)) ? $this->orderby :
'date_modification DESC, zone_geo ASC').' '.
"LIMIT $this->start,$this->limit ";
 
$elements = Cel::db()->requeter($requete);
 
// Création du contenu
if ($elements != false && count($elements) > 0) {
$contenu = $this->executerService($elements);
} else {
$this->messages[] = "Aucune observation disponible.";
}
 
return $contenu;
}
 
private function creerSousRequeteRechercheParCriteres($criteres) {
$requete = '';
foreach ($criteres as $pair) {
$nom_valeur = explode("=",$pair);
if (sizeof($nom_valeur) != 0) {
switch ($nom_valeur[0]) {
case "ci_limite" : $this->limit = Cel::db()->quote($nom_valeur[1]); break;
case "commentaire" : $mots_comment_liste = explode(" " , $nom_valeur[1]);
foreach($mots_comment_liste as $mot_comment) {
$mot_comment = trim($mot_comment) ;
$requete .= $nom_valeur[0].' LIKE '.Cel::db()->quote('%'.$mot_comment.'%').' AND ';
}
break;
case "date_observation" :
$nom_valeur[1] = str_replace('/', '-', $nom_valeur[1]);
if (preg_match('/(^[0-9]{2})-([0-9]{2})-([0-9]{4}$)/', $nom_valeur[1], $matches)) {
$nom_valeur[1] = $matches[3].'-'.$matches[2].'-'.$matches[1];
}
$requete .= $nom_valeur[0].'='.Cel::db()->quote($nom_valeur[1]).' AND '; break;
case "ce_zone_geo" :
$requete .= ' ('.$nom_valeur[0].' LIKE "INSEE-C:'.$nom_valeur[1].'%") AND '; break;
case "nom_ret" :
if ($nom_valeur[1] == "indetermine") $nom_valeur[1] = 'null';
$requete .= ' ('.$nom_valeur[0].' LIKE "%'.$nom_valeur[1].'%" OR nom_sel LIKE "%'.
$nom_valeur[1].'%") AND '; break;
case "mots-cles" : $requete .= $this->creerSousRequeteMotsCles($nom_valeur[1]).' AND '; break;
case "tags" : $requete .= $this->creerSousRequeteTags($nom_valeur[1]).' AND '; break;
default : $requete .= $nom_valeur[0].' = "'.$nom_valeur[1].'" AND '; break;
}
}
}
$requete = rtrim($requete,' AND ');
return $requete;
}
 
private function creerSousRequeteMotsCles($mot_cle) {
$requete = '';
if (preg_match('/.*OU.*/', $mot_cle)) {
$mots_cles_tab = explode('OU',$mot_cle);
foreach($mots_cles_tab as $mot_cle_item) {
$requete .= '(mots_cles_texte LIKE '.Cel::db()->proteger('%'.$mot_cle_item.'%').') OR ';
}
$requete = '('.rtrim($requete,'OR ').') ';
} else if (preg_match('/.*ET.*/', $mot_cle)) {
$mots_cles_tab = explode('ET',$mot_cle);
foreach($mots_cles_tab as $mot_cle_item) {
$requete .= '(mots_cles_texte LIKE '.Cel::db()->proteger('%'.$mot_cle_item.'%').') AND ';
}
$requete = '('.rtrim($requete, 'AND ').') ';
} else {
$requete = "(mots_cles_texte LIKE ".Cel::db()->proteger('%'.$mot_cle.'%').') ';
}
return $requete;
}
 
private function creerSousRequeteTags($tag) {
$requete = '(id_observation IN (SELECT id_observation FROM cel_obs_images coi INNER JOIN cel_images ci ON coi.id_image = ci.id_image WHERE ';
$where = '';
if (preg_match('/.*OU.*/', $tag)) {
$mots_cles_tab = explode('OU',$tag);
foreach($mots_cles_tab as $mot_cle_item) {
$where .= '(ci.mots_cles_texte LIKE '.Cel::db()->proteger('%'.$mot_cle_item.'%').') OR ';
}
$where .= '('.rtrim($where,'OR ').') ';
} else if (preg_match('/.*ET.*/', $tag)) {
$mots_cles_tab = explode('ET',$tag);
foreach($mots_cles_tab as $mot_cle_item) {
$where .= '(ci.mots_cles_texte LIKE '.Cel::db()->proteger('%'.$mot_cle_item.'%').') AND ';
}
$where .= '('.rtrim($where, 'AND ').') ';
} else {
$where .= "(ci.mots_cles_texte LIKE ".Cel::db()->proteger('%'.$tag.'%').') ';
}
$requete .= $where.' ))';
return $requete;
}
 
private function traiterCriteresMultiples($tableau_criteres) {
$tableau_criteres_pour_bdd = array();
 
foreach($tableau_criteres as $nom_critere => $valeur_critere) {
if (isset($this->criteres[$nom_critere])) {
$tableau_criteres_pour_bdd[] = $this->criteres[$nom_critere].'='.$valeur_critere;
}
}
return $tableau_criteres_pour_bdd;
}
 
private function creerSousRequeteRechercheGenerale($chaine_requete) {
$requete = '';
if (trim($chaine_requete) != '') {
$chaine_requete = strtolower($chaine_requete);
$chaine_requete = str_replace(' ', '_', $chaine_requete);
$requete = ' ('.
'nom_ret LIKE "'.$chaine_requete.'%"'.
' OR '.
'nom_sel LIKE "'.$chaine_requete.'%"'.
' OR '.
'zone_geo LIKE "'.$chaine_requete.'%" '.
' OR '.
'ce_zone_geo LIKE "'.$chaine_requete.'%" '.
' OR '.
'ce_zone_geo LIKE "INSEE-C:'.$chaine_requete.'%" '.
' OR '.
'courriel_utilisateur LIKE "'.$chaine_requete.'%" '.
' OR '.
'mots_cles_texte LIKE "'.$chaine_requete.'%" '.
') ';
}
return $requete;
}
 
private function estUneRechercheGenerale() {
return isset($_GET['recherche']);
}
 
private function executerService($elements) {
$contenu = '';
if (is_array($elements)) {
// Prétraitement des données
$donnees = $this->construireDonneesCommunesAuFlux($elements);
$ids_observations = array();
foreach ($elements as $element) {
$identifiants[$element['courriel_utilisateur']] = $element['courriel_utilisateur'];
$ids_observations[] = $element['id_observation'];
}
$gestion_champs_etendus = new GestionChampsEtendus($this->config, 'obs');
$champs_etendus = $gestion_champs_etendus->consulterParLots($ids_observations);
$this->auteurs = $this->creerAuteurs($identifiants);
foreach ($elements as $element) {
$element['obs_etendue'] = isset($champs_etendus[$element['id_observation']]) ? $champs_etendus[$element['id_observation']] : array();
$donnees['items'][] = $this->construireDonneesCommunesAuxItems($element);
}
 
// Création du contenu à partir d'un template PHP
if (isset($this->squelette)) {
$contenu = Cel::traiterSquelettePhp($this->squelette, $donnees);
}
}
return $contenu;
}
 
private function construireDonneesCommunesAuFlux($observations) {
$donnees = $this->getFlux($this->service);
$donnees['guid'] = $this->getUrlServiceBase();
$donnees['titre'] = 'Flux des observations du CEL';
$donnees['lien_service'] = $this->creerUrlService();
$donnees['lien_cel'] = $this->config['settings']['baseURLAbsolu'];
$donnees['editeur'] = $this->config['settings']['editeur'];
$derniere_info_en_date = reset($observations);
$date_modification_timestamp = strtotime($derniere_info_en_date['date_modification']);
$donnees['date_maj_RSS'] = date(DATE_RSS, $date_modification_timestamp);
$donnees['date_maj_ATOM'] = date(DATE_ATOM, $date_modification_timestamp);
$donnees['date_maj_W3C'] = date(DATE_W3C, $date_modification_timestamp);
$donnees['annee_courante'] = date('Y');
$donnees['generateur'] = 'CEL - Jrest - CelSyndicationObservation';
$donnees['generateur_version'] = (preg_match('/([0-9]+)/', '$Revision$', $match)) ? $match[1] : '0';
return $donnees;
}
 
private function construireDonneesCommunesAuxItems($observation) {
$item = array();
$date_modification_timestamp = $this->convertirDateHeureMysqlEnTimestamp($observation['date_modification']);
$item['date_maj_simple'] = strftime('%A %d %B %Y à %H:%M', $date_modification_timestamp);
$item['date_maj_RSS'] = date(DATE_RSS, $date_modification_timestamp);
$item['date_maj_ATOM'] = date(DATE_ATOM, $date_modification_timestamp);
$item['date_maj_W3C'] = date(DATE_W3C, $date_modification_timestamp);
$item['date_creation_simple'] = strftime('%A %d %B %Y à %H:%M', strtotime($observation['date_creation']));
$item['titre'] = $this->creerTitre($observation);
$item['guid'] = $this->creerGuidItem($observation);
$item['lien'] = $this->creerLienItem($observation);
$item['categorie'] = $this->creerCategorie($item);
$item['description'] = $this->creerDescription(Cel::protegerCaracteresHtmlDansChamps($observation), $item);
$item['description_encodee'] = htmlspecialchars($this->creerDescription($observation, $item));
$item['modifier_par'] = $observation['id_observation'];
return $item;
}
 
private function creerTitre($obs) {
$date = ($obs['date_observation'] != '0000-00-00 00:00:00') ? 'le '.date("d/m/Y", strtotime($obs['date_observation'])) : '' ;
$nom_plante = $obs['nom_sel'].' [nn'.$obs['nom_sel_nn'].']';
$lieu = $obs['zone_geo'].' ('.$obs['ce_zone_geo'].')';
$utilisateur = $this->getIntituleAuteur($obs['courriel_utilisateur']);
$titre = "$nom_plante à $lieu par $utilisateur $date";
$titre = $this->nettoyerTexte($titre);
return $titre;
}
 
private function creerGuidItem($element) {
$guid = sprintf($this->config['settings']['guidObsTpl'], $element['id_observation']);
return $guid;
}
 
private function creerLienItem($element) {
$lien = null;
if ($element['nom_sel_nn'] != 0) {
$lien = $this->getUrlEflore($element['nom_referentiel'], $element['nom_sel_nn'], 'cel');
}
return $lien;
}
 
private function creerDescription($obs, $item) {
$id_obs = $obs['id_observation'];
$famille = $obs['famille'];
$nom_saisi = $obs['nom_sel'];
$nom_retenu = $obs['nom_ret'];
$auteur = $this->getIntituleAuteur($obs['courriel_utilisateur']);
$auteur_mail = $obs['courriel_utilisateur'];
$mots_cles_obs = $obs['mots_cles_texte'];
$lien_correction = sprintf($this->config['settings']['phpEditUrlTpl'], $obs['id_observation']);
$lieu = $obs['zone_geo'].' ('.$this->convertirCodeZoneGeoVersCodeInsee($obs['ce_zone_geo']).') > '.$obs['lieudit'].' > '.$obs['station'];
$milieu = $obs['milieu'];
$coordonnees = ($this->etreNull($obs['latitude']) && $this->etreNull($obs['longitude'])) ? '' : $obs['latitude'].'/'.$obs['longitude'];
$commentaire = $obs['commentaire'];
$date_observation = ($obs['date_observation'] != '0000-00-00 00:00:00') ? $this->formaterDate($obs['date_observation'], '%A %d %B %Y') : '';
$date_transmission = $this->formaterDate($obs['date_transmission']);
$date_modification = $this->formaterDate($obs['date_modification']);
$date_creation = $this->formaterDate($obs['date_creation']);
$transmission = $obs['transmission'] == 1 ? "oui ($date_transmission)" : 'non';
 
$description = '<h2>'."Observation #$id_obs de $nom_saisi".'</h2>'.
'<ul>'.
'<li>'.'Famille : '.$famille.'</li>'.
'<li>'.'Nom saisi : '.$nom_saisi.'</li>'.
'<li>'.'Nom retenu : '.$nom_retenu.'</li>'.
'<li>'.'Observée le : '.$date_observation.'</li>'.
'<li>'.'Lieu : '.$lieu.'</li>'.
'<li>'.'Milieu : '.$milieu.'</li>'.
(($this->etreFluxAdmin()) ? '<li>Coordonnées (Lat/Long) : '.$coordonnees.'</li>' : '').
'<li>'.'Commentaire : '.$commentaire.'</li>'.
'<li>'.'Mots-clés : '.$mots_cles_obs.'</li>'.
(($this->etreFluxAdmin()) ? '<li>Transmis (= public) : '.$transmission.'</li>' : '').
'<li>Modifiée le : '.$date_modification.'</li>'.
'<li>Créée le : '.$date_creation.'</li>'.
'<li>'.'Par : '.
(($this->etreFluxAdmin()) ? '<a href="mailto:'.$auteur_mail.'">'.$auteur.'</a>' : $auteur).
'</li>'.
$this->creerDescriptionChampsEtendus($obs, $item).
(($this->etreFluxAdmin()) ? '<li><a href="'.$lien_correction.'">Corriger cette observation</a></li>' : '').
'</ul>';
$description = $this->nettoyerTexte($description);
return $description;
}
 
private function creerDescriptionChampsEtendus($obs, $item) {
$champs_etendus = '';
foreach($obs['obs_etendue'] as $cle => &$champ) {
$champs_etendus .= '<li>'.$champ->label.' : '.$champ->valeur.' </li>';
}
 
if($champs_etendus != '') {
$champs_etendus = '<li> Champs supplémentaires : <ul>'.$champs_etendus.'</ul></li>';
}
return $champs_etendus;
}
 
private function creerCategorie($element) {
$categorie = '';
$categorie = 'Observation';
$categorie = $this->nettoyerTexte($categorie);
return $categorie;
}
 
private function etreFluxAdmin() {
return (isset($_GET['admin']) && $_GET['admin'] == '1') ? true : false;
}
 
private function creerUrlService() {
$url_service = $this->getUrlServiceBase();
if (count($_GET) > 0) {
$parametres_get = array();
foreach ($_GET as $cle => $valeur) {
$parametres_get[] = $cle.'='.$valeur;
}
$url_service .= '?'.implode('&amp;', $parametres_get);
}
return $url_service;
}
 
private function getIntituleAuteur($courriel) {
$courriel = strtolower($courriel);
if(isset($this->auteurs[$courriel])) {
$intitule = $this->auteurs[$courriel];
} else {
$intitule = $courriel;
}
return $intitule;
}
}
/branches/v2.3-faux/jrest/services/InventoryPDF.php
New file
0,0 → 1,248
<?php
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author David Delon <david.delon@clapas.net>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
 
 
/** Constante stockant l'URL de la page d'accueil de Photoflora.*/
define('EF_URL_PHOTOFLORA', 'http://photoflora.free.fr/');
/** Constante stockant l'URL de la page de Photoflora affichant toutes les images d'un taxon donn.es.*/
define('EF_URL_PHOTOFLORA_TAXON', EF_URL_PHOTOFLORA.'FiTax.php?NumTaxon=%s');
/** Constante stockant l'URL du dossier de photoflora contenant les images miniatures.*/
define('EF_URL_PHOTOFLORA_IMG_MIN', 'http://www.tela-botanica.org/~photoflo/photos/%s/min/%s');
/** Constante stockant l'URL du dossier de photoflora contenant les images normale.*/
define('EF_URL_PHOTOFLORA_IMG_MAX', 'http://www.tela-botanica.org/~photoflo/photos/%s/max/%s');
/** Constante stockant l'expression r.guli.re r.cup.rant l'abr.viation du photographe et le nom du fichier.*/
define('EF_URL_PHOTOFLORA_REGEXP', '/\/photos\/([^\/]+)\/max\/(.+)$/');
/** Constante stockant l'URL du service XML de Photoflora.*/
define('EF_URL_PHOTOFLORA_SERVICE', EF_URL_PHOTOFLORA.'ef_photoflora.php?nt=%s');
 
/**
* InventoryPDF.php
*
* in : utf8
* out : iso8859
*
* Formatage pdf d'un releve (a revoir)
*/
class InventoryPDF extends Cel {
 
var $extendPDFProductor;
function InventoryPDF($config) {
 
parent::__construct($config);
 
$this->config=$config;
// Pas d'heritage multiple en php :(
$this->extendPDFProductor = new PDFProductor();
$this->extendPDFProductor->initPDF();
}
/**
* uid[0] : utilisateur obligatoire
* uid[1] : si absent : valeur 'all' (commune)
* uid[2] : si absent : valeur 'all' (date)
* uid[3] : si absent : valeur 'all' (recherche libre)
* uid[4] : si absent : valeur 'all' (station)
*/
function getElement($uid){
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
if (!isset($uid[1]) || $uid[1]=="" || $uid[1]=="all" ) {
$uid[1]="all";
$requete_location="";
}
else {
$requete_location=" AND location= ".Cel::db()->proteger($uid[1])." ";
}
if (!isset($uid[2]) || $uid[2]=="" || $uid[2]=="all") {
$uid[2]="all";
$requete_date="";
}
else {
$requete_date=" AND date_observation= ".Cel::db()->proteger($uid[2])." ";
}
if (!isset($uid[3]) || $uid[3]=="" || $uid[3]=="all") {
$uid[3]="all";
$requete_libre="";
}
else {
$requete_libre=" AND (nom_sel LIKE ".Cel::db()->proteger('%'.$uid[3].'%').
" OR nom_ret LIKE ".Cel::db()->proteger('%'.$uid[3].'%').
" OR station LIKE ".Cel::db()->proteger('%'.$uid[3].'%').
" OR commentaire LIKE ".Cel::db()->proteger('%'.$uid[3].'%');
}
 
if (!isset($uid[4]) || $uid[4]=="" || $uid[4]=="all") {
$uid[4]="all";
$requete_station="";
}
else {
$requete_station=" AND station= ".Cel::db()->proteger($uid[4])." ";
}
$value=array();
$requete="SELECT ce_utilisateur, ordre, nom_sel, nom_sel_nn, nom_ret, nom_ret_nn, nt, famille, zone_geo, date_observation," .
" station, commentaire, transmission FROM cel_obs WHERE ce_utilisateur = ".Cel::db()->proteger($uid[0])." " .
$requete_location.
$requete_date.
$requete_libre.
$requete_station.
" ORDER BY ordre ";
$resultat_requete = Cel::db()->requeter($requete);
$observations = array();;
if(is_array($resultat_requete)) {
$observations = $resultat_requete;
}
// Set up the pdf object.
$pdf = &File_PDF::factory(array('orientation' => 'P', 'format' => 'A4'));
// DesActivate compression.
$pdf->setCompression(false);
$pdf->setMargins(0, 0);
// Enable automatic page breaks.
$pdf->setAutoPageBreak(true);
// Start the document.
$pdf->open();
// Start a page.
$pdf->addPage();
$pdf->setFont('Times', '' , 12);
$i=1;
$tempfn = tempnam("","");
foreach ($observations as $obs) {
// Denullifiage
foreach($obs as $k=>$v) {
if (($v=="null") || ($v=="000null")) {
$obs[$k]="";
}
else {
$obs[$k]=utf8_decode($v);
}
}
if ($obs['date_observation']!="0000-00-00 00:00:00") {
list($year,$month,$day)= explode('-',$obs['date_observation']);
list($day)= explode(' ',$day);
$obs['date_observation']=$day."/".$month."/".$year;
}
else {
$obs['date_observation']="00/00/0000";
}
$text= $obs['nom_sel']." ".$obs['nom_sel_nn']." ".$obs['nom_ret']." ".$obs['nom_ret_nn']." ".$obs['nt']." ".
$obs['famille']." ".$obs['zone_geo']." ".$obs['ce_zone_geo']." ".$obs['date_observation']." ".$obs['station'];
$obs['commentaire'];
$pdf->write(10, $text."\n");
$projet_photo = 'photoflora';
$tab_retour[$projet_photo]=chercherIllustrationsServiceXml(sprintf(EF_URL_PHOTOFLORA_SERVICE, $obs['nt']));
$url_miniature ='';
foreach ($tab_retour[$projet_photo] as $cle => $illustration) {
if (preg_match(EF_URL_PHOTOFLORA_REGEXP, $illustration['about'], $match)) {
$abreviation = $match[1];
$fichier = $match[2];
$url_miniature = sprintf(EF_URL_PHOTOFLORA_IMG_MIN, $abreviation, $fichier);;
// Priorite aux images en png
if (strstr($fichier, '.png')) {
break;
}
}
}
 
if ($url_miniature!='') {
list($debut,$ext)=explode("\.",basename($url_miniature));
$temp = fopen($tempfn, "w");
$buf=file_get_contents($url_miniature);
fwrite($temp,$buf);
fclose($temp);
$pdf->image($tempfn,10,($i*10),0,0,$ext);
}
$i++;
}
echo $pdf->output("Rapport");
}
}
 
function chercherIllustrationsServiceXml($url)
{
return analyserFichierRdf($url);
}
function analyserFichierRdf($chemin)
{
$aso_info = array();
$dom = new DOMDocument();
$dom->validateOnParse = true;
if (preg_match('/^http:\/\//', $chemin)) {
$dom->loadXML(file_get_contents($chemin));
} else {
$dom->load($chemin);
}
$tab_infos = array();
foreach ($dom->getElementsByTagNameNS('http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'Description') as $rdf_description) {
$aso_info['about'] = $rdf_description->getAttribute('about');
$aso_info['dc:identifier'] = $rdf_description->getAttribute('identifier');
$aso_info['dc:title'] = utf8_decode($rdf_description->getAttribute('title'));
$aso_info['dc:creator'] = utf8_decode($rdf_description->getAttribute('creator'));
$aso_info['dc:contributor'] = utf8_decode($rdf_description->getAttribute('contributor'));
$aso_info['dc:publisher'] = utf8_decode($rdf_description->getAttribute('publisher'));
$aso_info['dc:type'] = utf8_decode($rdf_description->getAttribute('type'));
$aso_info['dc:format'] = utf8_decode($rdf_description->getAttribute('format'));
if (function_exists('date_default_timezone_set')) {
date_default_timezone_set('Europe/Paris');
}
if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $rdf_description->getAttribute('created'))) {
$aso_info['dcterms:created'] = date('j-m-Y � H:i:s', strtotime($rdf_description->getAttribute('created')));
} else {
$aso_info['dcterms:created'] = $rdf_description->getAttribute('created');
}
$aso_info['dcterms:dateSubmitted'] = utf8_decode($rdf_description->getAttribute('dateSubmitted'));
$aso_info['dcterms:spatial'] = utf8_decode($rdf_description->getAttribute('spatial'));
$aso_info['dcterms:licence'] = utf8_decode($rdf_description->getAttribute('licence'));
$tab_infos[$rdf_description->getAttribute('identifier')] = $aso_info;
}
 
return $tab_infos;
}
 
/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log$
* Revision 1.2 2008-01-30 08:57:28 ddelon
* fin mise en place mygwt
*
* Revision 1.1 2007-06-06 13:31:16 ddelon
* v0.09
*
* Revision 1.4 2007-05-22 12:54:09 ddelon
* Securisation acces utilisateur
*
*/
?>
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/branches/v2.3-faux/jrest/services/InventoryUserList.php
New file
0,0 → 1,73
<?php
/**
* Liste des utilisateurs du cel, par défaut les 50 premiers
* ou bien commencant par la chaine fournie en paramètre
* in : utf8
* out : utf8
*
* @category PHP
* @package jrest
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @copyright © 2010-2014 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
*/
class InventoryUserList extends Cel {
 
function getElement($uid) {
$this->controleUtilisateur($uid[0]);
 
$requete_utilisateurs ='SELECT DISTINCT id_utilisateur, courriel FROM cel_utilisateurs '.
$this->construireRequeteConditionTableUtilisateurs($uid).' '.
'UNION '.
'SELECT DISTINCT ce_utilisateur as id_utilisateur, courriel_utilisateur as courriel '.
'FROM cel_obs '.
$this->construireRequeteConditionTableObs($uid).' '.
'LIMIT 0,50';
 
$utilisateurs = Cel::db()->requeter($requete_utilisateurs);
 
$liste_utilisateurs = array();
if ($utilisateurs) {
foreach ($utilisateurs as $utilisateur) {
$liste_utilisateurs[] = $utilisateur;
}
}
usort($liste_utilisateurs, 'trierUtilisateurs');
 
$this->envoyerJson($liste_utilisateurs);
return true;
}
 
private function construireRequeteConditionTableUtilisateurs($params) {
$condition = '';
if (isset($params[1]) && $params[1] != null && $params[1] != '*') {
$condition .= ' WHERE courriel LIKE '.Cel::db()->proteger($params[1].'%');
}
return $condition;
}
 
private function construireRequeteConditionTableObs($params) {
$condition = '';
if (isset($params[1]) && $params[1] != null && $params[1] != '*') {
$condition .= ' WHERE courriel_utilisateur LIKE '.Cel::db()->proteger($params[1].'%');
}
return $condition;
}
}
 
function trierUtilisateurs($val1, $val2) {
if (strstr($val1['courriel'], '@')) {
if (strstr($val2['courriel'], '@')) {
return strcmp($val1['courriel'], $val2['courriel']);
} else {
return -1;
}
} else {
if (strstr($val2['courriel'], '@')) {
return 1;
} else {
return strcmp($val1['courriel'], $val2['courriel']);
}
}
}
?>
/branches/v2.3-faux/jrest/services/InventoryImport.php
New file
0,0 → 1,60
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author David Delon <david.delon@clapas.net>
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
/**
* InventoryImport.php
*
* in : utf8
* out : utf8
*
* Cas d'utilisation :
* Service importation releve en cours
*
* 1 : L'utilisateur à traiter est communique au service
* 2 : Les releves associés à la session en cours sont transferés à l'utilisateur identifié
*/
class InventoryImport extends Cel {
 
function getElement($uid){
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
$id_session_temporaire = session_id();
$gestionnaire_observation = new GestionObservation($this->config);
$migration_compte_a_compte = $gestionnaire_observation->migrerObservations($id_session_temporaire, $uid[0]);
$retour = false;
if($migration_compte_a_compte) {
$retour = 'OK';
}
echo $retour;
exit;
}
}
/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log$
* Revision 1.3 2008-01-30 08:57:28 ddelon
* fin mise en place mygwt
*
* Revision 1.2 2007-05-22 12:54:09 ddelon
* Securisation acces utilisateur
*
* Revision 1.1 2007-05-21 18:12:20 ddelon
* Gestion des importations locale de releves
*/
?>
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/branches/v2.3-faux/jrest/services/CelImageDoublon.php
New file
0,0 → 1,149
<?php
// declare(encoding='UTF-8');
/**
* Service fournissant une liste d'images doublon pour l'utilisateur qui s'authentifie.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* Cas d'utilisation :
* /CelImageDoublon/Sortie : images doublon de l'utilisateur authentifié.
*
* Sortie = Type de sortie : html ou json. Par défaut : html
*
* Utilisateur :
* identifiant (= courriel) de l'utilisateur récupéré via une identification HTTP.
*
* @author Jean-Pascal MILCENT <jpm@clapas.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright © 2010, Jean-Pascal MILCENT
*/
class CelImageDoublon extends Cel {
 
/**
* Méthode appelée avec une requête de type GET.
*/
public function getElement($params) {
$parametres = $this->traiterParametres(array('mode', 'utilisateur'), $params, false);
extract($parametres);
$contenu = '';
 
if ($this->authentifierUtilisateur()) {
$retour = null;
 
if (isset($mode)) {
$methode = $this->traiterNomMethodeGet($mode);
if (method_exists($this, $methode)) {
$retour = $this->$methode($parametres);
} else {
$service = get_class($this);
$this->messages[] = "Ce type de mode '$mode' pour le service '$service' n'est pas disponible.";
}
} else {
$this->messages[] = "Vous devez indiquer un type de mode.";
}
 
if (is_null($retour)) {
$contenu = 'Un problème est survenu : '.print_r($this->messages, true);
} else {
if ($retour['type'] == 'widget') {
$squelette = dirname(__FILE__).DIRECTORY_SEPARATOR.'squelettes'.DIRECTORY_SEPARATOR.$retour['squelette'].'.tpl.html';
$contenu = $this->traiterSquelettePhp($squelette, $retour['donnees']);
} else if ($retour['type'] == 'json') {
$contenu = $retour['donnees'];
}
}
}
 
// Envoie sur la sortie standard
$encodage = 'UTF-8';
$mime = 'text/html';
$formatage_json = (isset($retour) && $retour['type'] == 'json') ? true : false;
$this->envoyer($contenu, $mime, $encodage, $formatage_json);
}
 
/**
* Carte par défaut
*/
private function getDoublonHtml($parametres) {
 
$widget = null;
$utilisateur_mail = Cel::getAuthIdentifiant();
$utilisateur_infos = new User($this->config);
$utilisateur = $utilisateur_infos->obtenirUtilisateurSiExiste($utilisateur_mail);
$utilisateur = $utilisateur['id_utilisateur'];
 
// Création des infos du widget
$widget['type'] = 'widget';
$widget['donnees']['utilisateur'] = $utilisateur_mail;
$widget['donnees']['doublons'] = $this->getImagesDoublon($utilisateur);
$widget['squelette'] = 'doublon_defaut';
 
return $widget;
}
 
/**
* Images en doublon d'un utilisateur
*/
private function getImagesDoublon($utilisateur) {
$doublons = null;
 
if (isset($utilisateur)) {
// Un utilisateur en particulier
$requete = 'SELECT id_image, ordre, nom_original, md5 '.
'FROM cel_images '.
"WHERE ce_utilisateur = '$utilisateur' ";
 
$images = Cel::db()->requeter($requete);
 
// Traitement
$doublons = array();
$images_doublons_id = array();
$md5 = array();
foreach ($images as $img) {
if (!isset($md5[$img['md5']])) {
$md5[$img['md5']] = array(
'url' => $this->getUrlImage($img['id_image'], 'CXS'),
'obs_ordre' => array(),
'img_ordre' => $img['ordre'],
'img_id' => $img['id_image']);
} else {
if (!isset($doublons[$img['md5']])) {
$id_img = $md5[$img['md5']]['img_id'];
$doublons[$img['md5']][$id_img] = $md5[$img['md5']];
$images_doublons_id[] = Cel::db()->quote($id_img);
}
 
$doublons[$img['md5']][$img['id_image']] = array(
'url' => $this->getUrlImage($img['id_image'], 'CXS'),
'obs_ordre' => array(),
'img_ordre' => $img['ordre'],
'img_id' => $img['id_image']);
$images_doublons_id[] = Cel::db()->quote($img['id_image']);
}
}
 
if (count($images_doublons_id) > 0) {
$requete = 'SELECT cim.id_image, nom_original, md5, co.ordre as ordre_obs '.
'FROM cel_images AS cim '.
' LEFT JOIN cel_obs_images AS coi '.
' ON (coi.id_image = cim.id_image) '.
' LEFT JOIN cel_obs AS co '.
' ON (coi.id_observation = co.id_observation) '.
"WHERE cim.ce_utilisateur = '$utilisateur' ".
' AND cim.id_image IN ('.implode(',', $images_doublons_id).')';
 
$infos = Cel::db()->requeter($requete);
 
foreach ($infos as $info) {
if (isset($doublons[$info['md5']][$info['id_image']]) && ! $this->etreNull($info['ordre_obs'])) {
$doublons[$info['md5']][$info['id_image']]['obs_ordre'][] = $info['ordre_obs'];
}
}
}
}
 
return $doublons;
}
}
/branches/v2.3-faux/jrest/services/InventoryImportMail.php
New file
0,0 → 1,209
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* Service d'import d'image à partir de mails
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
*/
Class InventoryImportMail extends Cel {
 
/**
* Appelée en mode client, lit le mail envoyé sur l'entrée stdin
* et le stocke dans le dossier temporaire en attendant
* qu'une tache périodique associée traite les mails en attente
*
* @param array $params les paramètres du script client, l'utilisateur est indiqué avec le paramètre -s
*/
public function stockerMailCli($params)
{
$contenu_mail = file_get_contents('php://stdin');
 
$parametres_ajout = array();
$parametres_ajout['mail_utilisateur'] = $params['-s'];
 
$stockage = $this->stockerMailTemporaire($parametres_ajout, $contenu_mail);
if($stockage) {
$message_attente = 'Votre messsage a été reçu, et est en attente de traitement, '.
'vous recevrez un message lorsque celui-ci aura été effectué';
mail($parametres_ajout['mail_utilisateur'],'Votre message est en attente de traitement',$message_attente);
} else {
$message_echec = 'Votre messsage a été reçu, mais il n\'a pas pu être stocké';
mail($parametres_ajout['mail_utilisateur'],'Problème lors de reception du message',$message_echec);
}
exit;
}
private function stockerMailTemporaire($parametres_ajout, $contenu_mail) {
$expediteur = $parametres_ajout['mail_utilisateur'];
$nom_fichier_temp = $this->fabriquerNomTemporaireStockageMail($expediteur);
$dossier_stockage_temp = $this->config['chemin_stockage_temp'];
$chemin_stockage_image_temp = $dossier_stockage_temp.'/mails/';
return file_put_contents($chemin_stockage_image_temp.$nom_fichier_temp);
}
/**
* Appelée en mode client, lit le mail envoyé sur l'entrée stdin
* extrait les images en pièces jointes, et les ajoute au cel de l'utilisateur
* expediteur
*
* @param array $params les paramètres du script client, l'utilisateur est indiqué avec le paramètre -s
*/
public function traiterMailCli($params)
{
 
$contenu_mail = file_get_contents('php://stdin');
 
$parametres_ajout = array();
$parametres_ajout['mail_utilisateur'] = $params['-s'];
 
$ids_stockage = $this->traiterMail($parametres_ajout, $contenu_mail);
foreach($ids_stockage as $nom_image => $id_stockage) {
if($id_stockage) {
mail($parametres_ajout['mail_utilisateur'],'Votre image a été ajoutée au Carnet en ligne','Votre image '.$nom_image.' a été ajoutée avec succès');
} else {
mail($parametres_ajout['mail_utilisateur'],'Problème lors de l\'ajout au Carnet en ligne','Votre image '.$nom_image.' n\'a pas pu être ajoutée');
}
}
exit();
}
/**
* Traite le mail fourni en paramètre extrait les images en pièces jointes,
* et les ajoute au cel de l'utilisateur expediteur
*
* @param array $params les paramètres du script client, l'utilisateur est indiqué dans la case 'identifiant'
*/
public function traiterMail($params, $contenu_mail)
{
$pieces_jointes = $this->extrairePiecesJointes($contenu_mail);
 
$stockeur_image = new InventoryImage($this->config);
$ids = array();
$infos_utilisateur = $this->getInfosComplementairesUtilisateurPourMail($params['mail_utilisateur']);
$params['ce_utilisateur'] = $infos_utilisateur['id_utilisateur'];
foreach($pieces_jointes as $piece_jointe) {
$nouvel_id_image = $stockeur_image->ajouterImageSurDdEtBdd($params, $piece_jointe);
if($nouvel_id_image)
{
$ids[$piece_jointe['name']] = $nouvel_id_image;
}
else
{
$ids[$piece_jointe['name']] = false;
}
}
// TODO: permettre la création d'observations liées aux images à partir du mail
// et d'une syntaxe simple à définir
return $ids;
}
/**
* Appelée en mode client, parse le dossier ou sont stockés les mails
* extrait les images en pièces jointes, et les ajoute au cel de l'utilisateur
*
*/
public function parserDossierMail()
{
$dossier_stockage_temp = $this->config['chemin_stockage_temp'];
$chemin_stockage_image_temp = $dossier_stockage_temp.'/mails/';
foreach (new DirectoryIterator($chemin_stockage_image_temp) as $fichier_a_stocker) {
if($fichier_ou_dossier->isDot()) {
continue;
}
$chemin_fichier = $fichier_a_stocker->getPathname();
$nom_fichier = $fichier_ou_dossier->getFilename();
$expediteur_mail = $this->obtenirExpediteurPourNomTemporaireMail($nom_fichier);
$contenu_mail = file_get_contents($chemin_fichier);
$parametres = array('courriel_utilisateur' => $expediteur_mail);
$this->traiterMail($parametres, $contenu_mail);
unlink($chemin_fichier);
}
}
private function extrairePiecesJointes($mail) {
 
$pieces_jointes = array();
$args['include_bodies'] = true;
$args['decode_bodies'] = true;
$args['decode_headers'] = true;
$args['input'] = $mail;
$dossier_stockage_temp = $this->config['chemin_stockage_temp'];
$tableau_mail_decode = Mail_mimeDecode::decode($args);
foreach ($tableau_mail_decode->parts as $partie) {
if ($partie->ctype_primary == 'image' && $partie->ctype_secondary == 'jpeg') {
$informations = array();
$nom_original = $partie->ctype_parameters['name'];
$fichier = $partie->body;
$hash = md5(time());
$chemin_temp = $dossier_stockage_temp.'/images/'.$hash.'.jpg';
$temp = fopen($chemin_temp,'w+');
fwrite($temp,$fichier);
fclose($temp);
chmod($chemin_temp, 0777);
$informations = array('tmp_name' => $chemin_temp,'name' => $nom_original,'type' => 'image/jpeg','size' => filesize($chemin_temp));
$pieces_jointes[] = $informations;
}
}
 
return $pieces_jointes;
}
private function fabriquerNomTemporaireStockageMail($expediteur) {
return time().'_'.$expediteur;
}
private function obtenirExpediteurPourNomTemporaireMail($nom_temp) {
$chaine_separee = explode('_', $nom_temp,1);
$nom_expediteur = false;
if($chaine_separee && count($chaine_separee) > 1) {
$nom_expediteur = $chaine_separee[1];
}
return $nom_expediteur;
}
}
?>
/branches/v2.3-faux/jrest/services/InventoryImageListPublic.php
New file
0,0 → 1,74
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author Aurélien Peronnet <aurelien@tela-botania.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
/**
* in : utf8
* out : utf8
*
* Service recherche d'images publique a partir de divers critères
*
*/
class InventoryImageListPublic extends Cel {
const start_defaut = 0;
const limit_defaut = 100;
const tri_defaut = 'ci.date_creation';
const dir_defaut = 'DESC';
 
function getRessource() {
}
 
function getElement($uid)
{
// restriction aux observations publiques
$criteres = array('transmission' => '1');
if($uid[0] != '*' && empty($_GET)) {
header("content-type: application/json");
$images_json = json_encode(array());
print $images_json;
exit() ;
}
$this->start = isset($_GET['start']) ? $_GET['start'] : self::start_defaut;
$this->limit = isset($_GET['limit']) ? $_GET['limit'] : self::limit_defaut;
$criteres['mots_cles'] = isset($_GET['tag']) ? $_GET['tag'] : null;
$criteres['auteur'] = isset($_GET['auteur']) ? $_GET['auteur'] : null;
$criteres['zone_geo'] = isset($_GET['commune']) ? $_GET['commune'] : null;
$criteres['taxon'] = isset($_GET['taxon']) ? $_GET['taxon'] : null;
$criteres['ce_zone_geo'] = isset($_GET['dept']) ? $_GET['dept'] : null;
$criteres['famille'] = isset($_GET['famille']) ? $_GET['famille'] : null;
$criteres['recherche'] = isset($_GET['recherche']) ? $_GET['recherche'] : null;
$criteres['tri'] = isset($_GET['tri']) ? $_GET['tri'] : self::tri_defaut;
$criteres['dir'] = isset($_GET['dir']) ? $_GET['dir'] : self::dir_defaut;
$chercheur_images = new RechercheImage($this->config);
$total = $chercheur_images->compterImages(null, $criteres);
$images = $chercheur_images->rechercherImages(null, $criteres, $this->start, $this->limit);
 
$resultat = array('total' => $total,'images' => $images);
$images_json = json_encode($resultat) ;
$images_json = str_replace('\u0000','',$images_json);
 
header("content-type: application/json") ;
print $images_json ;
exit() ;
}
}
?>
/branches/v2.3-faux/jrest/services/InventoryImageList.php
New file
0,0 → 1,104
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
 
/**
* InventoryImageList.php
*
* in : utf8
* out : utf8
*
* Service recherche, et de suppression multiple d'images a partir de divers critères
*
*/
class InventoryImageList extends Cel {
 
/**
* Recherche les images correspondant aux critères passés en paramètres
* uid[0] : utilisateur obligatoire
* $_GET : critères de filtrage de la forme critère1=valeur1;critère2=valeur2
*/
function getElement($uid)
{
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
$chercheur_images = new RechercheImage($this->config);
 
$numero_page = 0;
$taille_page = 50;
$criteres = array();
 
$criteres = $_GET;
if (isset($criteres['numero_page']) && isset($criteres['limite'])) {
$numero_page = $criteres['numero_page'];
unset($criteres['numero_page']);
$taille_page = $criteres['limite'];
unset($criteres['limite']);
}
 
$debut = $taille_page*$numero_page ;
 
$retour = $chercheur_images->rechercherImagesEtObservationAssociees($uid[0], $criteres, $debut, $taille_page);
$retour = $chercheur_images->formaterPourEnvoiCel($retour);
 
$retour_encode = json_encode($retour) ;
$retour_encode = $this->nettoyerCaracteresNuls($retour_encode);
 
header("content-type: application/json") ;
print $retour_encode ;
exit() ;
}
 
private function nettoyerCaracteresNuls($chaine) {
return str_replace('\u0000','',$chaine);
}
 
/**
* Méthode appelée avec une requête de type DELETE.
* Supprime les infos sur l'image et le fichier correspondant à l'ordre passé en parametre
* Supporte la suppression multiple en passant plusieurs numéros séparés par des virgules
*
* @param int uid[0] id utilisateur
* @param string uid[1] : ordre(s) image(s) obligatoire(s) séparés par des virgules
*
*/
function deleteElement($uid){
 
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
 
if (!isset($uid[1]) || !$this->EstUneSuiteIdentifiantsImage($uid[1])) {
return;
}
 
$ids_images = rtrim($uid[1], ',');
$ids_images = explode(',',$ids_images);
 
$gestionnaire_image = new GestionImage($this->config);
$suppression_image = $gestionnaire_image->supprimerImage($ids_images);
 
$this->envoyer('OK');
exit;
}
 
private function estUneSuiteIdentifiantsImage($chaine) {
$chaine = rtrim($chaine,',');
// un ensemble d'identifiants est une suite d'identifiants séparés par des virgules
// avec ou sans virgule terminale
$reg_exp = "/^(([0-9])+,)*([0-9])+$/";
 
return preg_match($reg_exp, $chaine);
}
}
?>
/branches/v2.3-faux/jrest/services/CoordSearch.php
New file
0,0 → 1,238
<?php
/**
* Service recherche de commune par coordonnées et vice versa
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
*/
class CoordSearch extends Cel {
 
private $adresse_service_geonames = null;
private $adresse_service_local = null;
 
private $nom_service_geocoding = null;
private $nom_service_reverse_geocoding = null;
 
function CoordSearch($config) {
 
parent::__construct($config);
 
$this->adresse_service_geonames = $this->config['cel']['url_service_geo_geonames'];
$this->adresse_service_local = $this->config['cel']['url_service_geo_local'];
 
$this->nom_service_geocoding = $this->config['cel']['nom_service_geocoding_geonames'];
$this->nom_service_reverse_geocoding = $this->config['cel']['nom_service_reverse_geocoding_geonames'];
}
 
/**
* Recherche de coordonnées suivant ce qui est fourni
*
* $uid[0] = latitude (ou * si recherche coordonnées d'une commune)
* $uid[1] = longitude (ou * si recherche coordonnées d'une commune)
* $uid[2] = commune (ou * si recherche d'une commune correspondant à des coordonnées)
* $uid[3] = code_postal (ou * si recherche d'une commune correspondant à des coordonnées)
* $uid[4] = code_pays (ou * si recherche d'une commune correspondant à des coordonnées, par défaut vaut FR)
*/
function getElement($uid){
 
$header = '';
$retour = array();
 
$params = $this->traiterParametres($uid);
 
if ($this->estUneRequeteReverseGeocoding($params)) {
 
$informations_communes = $this->effectuerRequeteReverseGeocodingCartoOsm($params['lat'], $params['lon']);
 
if (!$informations_communes) {
$informations_communes = $this->effectuerRequeteReverseGeocodingGeonames($params['lat'], $params['lon']);
}
 
$header = 'Content-Type: application/json; charset=UTF-8';
$retour = json_encode($informations_communes) ;
 
} elseif ($this->estUneRequeteGeocoding($params)) {
 
$informations_coord = $this->chercherCentroideCommuneBdd($params['commune'],$params['code_postal']);
if(!$informations_coord) {
$informations_coord = $this->effectuerRequeteGeocodingGeonames($params['commune'],$params['code_postal'],$params['code_pays']);
}
 
$header = 'Content-Type: application/json; charset=UTF-8';
$retour = json_encode($informations_coord);
 
} else {
 
$header = 'HTTP/1.0 400 Bad Request';
$retour = 'Commune ou Coordonnées non spécifiées' ;
}
 
header($header);
echo $retour;
}
 
protected function traiterParametres($params) {
 
$lat = $this->affecterValeurParametreOuDefaut($params, 0, '*');
$lng = $this->affecterValeurParametreOuDefaut($params, 1, '*');
 
$commune = $this->affecterValeurParametreOuDefaut($params, 2, '*');
$code_postal = $this->affecterValeurParametreOuDefaut($params, 3, '*');
 
$code_pays = $this->affecterValeurParametreOuDefaut($params, 4, 'FR');
 
return array('lat' => $lat, 'lon' => $lng, 'commune' => $commune,
'code_postal' => $code_postal, 'code_pays' => $code_pays);
}
 
private function affecterValeurParametreOuDefaut($params, $indice, $valeur_si_non_present) {
return isset($params[$indice]) ? str_replace('"','',urldecode($params[$indice])) : $valeur_si_non_present;
}
 
private function estUneRequeteReverseGeocoding($params) {
 
return ($params['lat'] != '*' && $params['lon'] != '*');
}
 
private function estUneRequeteGeocoding($params) {
return ($params['commune'] != '*');
}
 
private function effectuerRequeteReverseGeocodingCartoOsm($lat, $lon) {
 
$infos_commune_json = @file_get_contents($this->adresse_service_local."?lat=".$lat."&lon=".$lon);
$infos_commune = json_decode($infos_commune_json);
 
$retour = false;
 
if ($this->estUnRetourOsmValide($infos_commune)) {
$retour = array('nom' => $infos_commune->nom, 'code_insee' => $infos_commune->codeINSEE);
}
 
return $retour;
}
 
private function estUnretourOsmValide($retour) {
return (is_a($retour,'stdClass') && property_exists($retour,'nom') && property_exists($retour,'codeINSEE'));
}
 
private function effectuerRequeteReverseGeocodingGeonames($lat, $lon) {
 
$infos_commune_json = @file_get_contents($this->adresse_service_geonames.
$this->nom_service_reverse_geocoding.
"?lat=".urlencode($lat)."&lng=".urlencode($lon).
"&style=full");
$objet_retour = json_decode($infos_commune_json);
 
$retour = false;
if($this->estUnRetourReverseGeocodingGeonamesValide($objet_retour)) {
$retour = array('nom' => $objet_retour->geonames[0]->adminName4, 'code_insee' => $objet_retour->geonames[0]->adminCode4);
}
 
return $retour;
}
 
private function estUnRetourReverseGeocodingGeonamesValide($retour) {
 
$valide = false;
 
if (is_a($retour,'stdClass') && property_exists($retour,'geonames')
&& is_array($retour->geonames) && count($retour->geonames) > 0) {
$objet_resultats = $retour->geonames[0];
if (property_exists($objet_resultats,'adminName4') && property_exists($objet_resultats,'adminCode2')) {
$valide = true;
}
}
 
return $valide;
}
 
private function chercherCentroideCommuneBdd($commune, $departement) {
 
$commune_formatee = str_replace(' ','_',$commune);
$commune_formatee = str_replace('-','_',$commune_formatee);
 
if(strlen($departement) > 2) {
$departement = substr($departement,0,2);
}
$requete_selection_commune = 'SELECT utm_x, utm_y, utm_secteur, code FROM cel_zones_geo '.
'WHERE nom LIKE '.Cel::db()->proteger($commune_formatee).' AND code LIKE '.Cel::db()->proteger($departement.'%');
 
$commune_coordonnees = Cel::db()->requeter($requete_selection_commune);
 
$retour = false;
 
if($commune_coordonnees && is_array($commune_coordonnees) && count($commune_coordonnees) > 0) {
 
$lat_lon = $this->convertirUtmVersLatLong($commune_coordonnees[0]['utm_x'],$commune_coordonnees[0]['utm_y'],$commune_coordonnees[0]['utm_secteur']);
 
$retour = array('lat' => (float)$lat_lon['lat'],
'lng' => (float)$lat_lon['lng'],
'nom' => $commune,
'code_insee' => $commune_coordonnees[0]['code']
);
 
}
 
return $retour;
}
 
private function convertirUtmVersLatLong($x, $y, $sector) {
 
$lat_long = array();
 
$convertisseur = new gPoint();
$convertisseur->setUTM($x, $y, $sector);
$convertisseur->convertTMtoLL();
$lat_long['lat'] = str_replace(',','.',$convertisseur->Lat());
$lat_long['lng'] = str_replace(',','.',$convertisseur->Long());
 
return $lat_long;
}
 
private function effectuerRequeteGeocodingGeonames($commune, $code_postal, $code_pays) {
 
$requete = $this->adresse_service_geonames.
$this->nom_service_geocoding.
"?placename_startsWith=".urlencode($commune);
 
if($code_postal != '*') {
$requete .= "&postalcode_startsWith=".urlencode($code_postal);
}
$requete .= "&country=".urlencode($code_pays)."&maxRows=10" ;
 
$coord_json = @file_get_contents($requete);
$objet_retour = json_decode($coord_json);
 
$retour = false;
 
if($this->estUnRetourGeocodingGeonamesValide($objet_retour)) {
$retour = array('lat' => $objet_retour->postalCodes[0]->lat,
'lng' => $objet_retour->postalCodes[0]->lng,
'nom' => $objet_retour->postalCodes[0]->placeName,
'code_insee' => $objet_retour->postalCodes[0]->postalCode
);
}
 
return $retour;
}
 
private function estUnRetourGeocodingGeonamesValide($retour) {
$valide = false;
 
if (is_a($retour,'stdClass') && property_exists($retour,'postalCodes')
&& is_array($retour->postalCodes) && count($retour->postalCodes) > 0) {
$objet_resultats = $retour->postalCodes[0];
if (property_exists($objet_resultats,'lat') && property_exists($objet_resultats,'lng')) {
$valide = true;
}
}
 
return $valide;
}
}
?>
/branches/v2.3-faux/jrest/services/.
New file
Property changes:
Added: svn:ignore
+MigrationImages.php
+MigrationMotsCles.php
+MigrationObs.php
+Test.php