New file |
0,0 → 1,388 |
<?php |
// declare(encoding='UTF-8'); |
/** |
* Le web service image récupère toutes les données de la table del_obs_images |
* pour retourner une liste d'images associée à la détermination la plus probable |
* avec la possibilité de ne renvoyer que les images les mieux notées pour un protocole donné |
* |
* @category php 5.2 |
* @package del |
* @subpackage images |
* @author Aurélien Peronnet <aurelien@tela-botanica.org> |
* @copyright Copyright (c) 2012, 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: Bdd.php 403 2012-02-22 14:35:20Z aperonnet $ |
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images |
*/ |
|
class ListeImagesDeterminationsProbables { |
|
private $imageIds = array(); |
private $conteneur; |
private $navigation; |
private $masque; |
private $gestionBdd; |
private $bdd; |
private $parametres = array(); |
private $ressources = array(); |
private $tri = 'date_transmission'; |
private $directionTri = 'desc'; |
private $protocole_defaut = null; |
private $valeur_vote_min_defaut = null; |
|
public function __construct(Conteneur $conteneur = null) { |
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur; |
$this->conteneur->chargerConfiguration('config_determinations.ini'); |
$this->navigation = $conteneur->getNavigation(); |
$this->masque = $conteneur->getMasque(); |
$this->gestionBdd = $conteneur->getGestionBdd(); |
$this->bdd = $this->gestionBdd->getBdd(); |
} |
|
/** |
* Méthode principale de la classe. |
* Lance la récupération des images dans la base et les place dans un objet ResultatService |
* pour l'afficher. |
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2) |
* @param array $parametres les paramètres situés après le ? dans l'url |
* */ |
public function consulter($ressources, $parametres) { |
$this->initialiserRessourcesEtParametres($ressources, $parametres); |
|
// Gestion des configuration du script |
$this->configurer(); |
$this->verifierConfiguration(); |
|
$this->verifierParametres(); |
|
$this->initialiserTri(); |
|
// Lancement du service |
$liaisons = $this->chargerLiaisons(); |
$total = 0; |
if(!empty($liaisons)) { |
$total = $this->compterImages(); |
$images = $this->chargerImage($liaisons); |
$images = $this->chargerPropositionPlusProbable($images); |
} else { |
$images = $liaisons; |
} |
|
$this->navigation->setTotal($total); |
|
// Mettre en forme le résultat et l'envoyer pour affichage |
$resultat = new ResultatService(); |
$resultat->corps = array('entete' => $this->conteneur->getEntete(), 'resultats' => $images); |
|
return $resultat; |
} |
|
private function initialiserRessourcesEtParametres($ressources, $parametres) { |
$this->ressources = $ressources; |
$this->parametres = $parametres; |
|
if(!isset($parametres['masque.protocole'])) { |
$this->parametres['masque.protocole'] = $this->protocole_defaut; |
} |
if(!isset($parametres['masque.valeur_vote_min'])) { |
$this->parametres['masque.valeur_vote_min'] = $this->valeur_vote_min_defaut; |
} |
} |
|
private function verifierParametres() { |
$erreurs = array(); |
$tableau_protocoles = explode(',',$this->conteneur->getParametre('protocoles_possibles')); |
|
if(isset($this->parametres['masque.protocole']) && |
(!is_numeric($this->parametres['masque.protocole']) || |
!in_array($this->parametres['masque.protocole'], $tableau_protocoles) |
)) { |
$erreurs[] = '- la valeur pour le protocole doit être un entier compris dans les numéros de protocole existants '.$this->conteneur->getParametre('protocoles_possibles'); |
} |
|
if(isset($this->parametres['masque.valeur_min_vote']) && |
(!is_numeric($this->parametres['masque.valeur_min_vote']) || |
$this->parametres['masque.valeur_min_vote'] < 0 || |
$this->parametres['masque.valeur_min_vote'] > 5 |
)) { |
$erreurs[] = '- la valeur minimum de valeur des votes doit être un entier compris entre 0 et 5 '; |
} |
|
if (!empty($erreurs)) { |
$e = 'Erreur lors de l\'analyse des parametres du service : '."\n"; |
$e .= implode("\n", $erreurs); |
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR); |
} |
} |
|
private function initialiserTri() { |
$this->tri = isset($this->parametres['tri']) ? $this->parametres['tri'] : $this->tri; |
$this->directionTri = isset($this->parametres['ordre']) ? $this->parametres['ordre'] : $this->directionTri; |
} |
/*------------------------------------------------------------------------------- |
CONFIGURATION DU SERVICE |
--------------------------------------------------------------------------------*/ |
/** |
* Configuration du service en fonction du fichier de config config_del.ini |
* */ |
public function configurer() { |
$this->mappingFiltre = $this->conteneur->getParametre('mapping_masque'); |
$this->mappingObservation = $this->conteneur->getParametre('mapping_observation'); |
$this->mappingVotes = $this->conteneur->getParametre('mapping_votes'); |
} |
|
/** |
* Vérifier que le service est bien configuré |
* */ |
public function verifierConfiguration() { |
|
$erreurs = array(); |
$tris_possibles = $this->conteneur->getParametre('protocoles_possibles'); |
if (empty($tris_possibles)) { |
$erreurs[] = '- le fichier de configuration ne contient pas le parametre protocoles_possibles ou celui-ci est vide ;'; |
} |
//TODO: ajouter des vérifications si le web service s'étoffe |
|
if (!empty($erreurs)) { |
$e = 'Erreur lors de la configuration : '."\n"; |
$e .= implode("\n", $erreurs); |
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR); |
} |
} |
|
private function remplacerParJokerCaractere($valeurMasque) { |
return str_replace(array('-',' '), '_', $valeurMasque); |
} |
//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. 'œ' |
$str = preg_replace('#&[^;]+;#', '', $str); // supprime les autres caractères |
|
return $str; |
} |
|
/*------------------------------------------------------------------------------- |
CHARGEMENT DES IMAGES |
--------------------------------------------------------------------------------*/ |
/** |
* Chargement depuis la bdd de toutes les liaisons entre images et observations |
* */ |
private function chargerLiaisons() { |
|
$champs = array('dob.id_observation as id_observation', 'nom_ret', 'nom_ret_nn', 'nt', 'famille', 'ce_zone_geo', 'zone_geo', |
'lieudit', 'station', 'milieu', 'date_observation', 'dob.mots_cles_texte as mots_cles_texte', 'dob.commentaire as commentaire', |
'di.mots_cles_texte as mots_cles_texte_image ', 'date_transmission', 'di.id_image as id_image', 'di.ce_utilisateur as ce_utilisateur', |
'prenom', 'nom', 'courriel', 'nom_original'); |
|
$requeteLiaisons = 'SELECT DISTINCT SQL_CALC_FOUND_ROWS '.implode(', ',$champs).', '. |
'AVG(dvote.valeur) as moyenne_votes '. |
'FROM '.$this->gestionBdd->formaterTable('del_obs_image', 'doi'). |
'INNER JOIN del_image di '. |
'ON doi.id_image = di.id_image '. |
'INNER JOIN del_observation dob '. |
'ON doi.id_observation = dob.id_observation '. |
'INNER JOIN del_utilisateur du '. |
'ON du.id_utilisateur = di.ce_utilisateur '. |
'LEFT JOIN del_image_vote dvote '. |
'ON doi.id_image = dvote.ce_image '. |
($this->parametres['masque.protocole'] != null ? 'AND dvote.ce_protocole = '.$this->parametres['masque.protocole'].' ' : ' '); |
$requeteLiaisons .= 'GROUP BY dvote.ce_image '. |
($this->parametres['masque.valeur_vote_min'] != null ? 'HAVING AVG(dvote.valeur) >= '.$this->parametres['masque.valeur_vote_min'].' ' : ' '). |
'ORDER BY moyenne_votes'; |
$requeteLiaisons .= $this->gestionBdd->getLimitSql(); |
return $this->bdd->recupererTous($requeteLiaisons); |
} |
|
private function doitJoindreTableVotes() { |
return ($this->tri == 'votes'); |
} |
|
private function getTri() { |
$order = ''; |
if($this->doitJoindreTableVotes()) { |
$order = ' GROUP BY dvote.ce_image, dob.id_observation ORDER BY total_votes '.$this->directionTri.', date_transmission desc '; |
} else { |
$order = ' ORDER BY '.$this->tri.' '.$this->directionTri.' '; |
} |
return $order; |
} |
|
/** |
* Compter le nombre total d'images dans la base pour affichage dans entete. |
* */ |
private function compterImages() { |
$requete = 'SELECT FOUND_ROWS() AS nbre '; |
$resultats = $this->bdd->recuperer($requete); |
return (int) $resultats['nbre']; |
} |
|
/** |
* Retourner un tableau d'images formaté en fonction des liaisons trouvées |
* @param $liaisons les liaisons de la table del_obs_images |
* */ |
private function chargerImage($liaisons) { |
$images = array(); |
foreach ($liaisons as $liaison) { |
$idObs = $liaison['id_observation']; |
$idImage = $liaison['id_image']; |
// On enregistre l'ID de l'obs pour n'effectuer qu'une seule requête par la suite |
$this->obsIds[] = $idObs; |
$index = $liaison['id_image'].'-'.$liaison['id_observation']; |
$images[$index] = array( |
'id_image' => $idImage, |
'id_observation' => $idObs, |
'auteur.intitule' => $liaison['prenom'].' '.$liaison['nom'], |
'binaire.href' => $this->formaterLienImage($idImage), |
'determination.famille' => $liaison['famille'], |
'determination.ns' => $liaison['nom_ret'], |
'determination.nn' => $liaison['nom_ret_nn'], |
'determination.nt' => $liaison['nt'], |
'date_observation' => $liaison['date_observation'], |
'localite' => $this->formaterLieu($liaison) |
); |
} |
return $images; |
} |
|
/** |
* Charger les votes pour chaque image |
* */ |
private function chargerPropositionPlusProbable($images) { |
|
$requetePropositions = 'SELECT * FROM '. |
'del_commentaire '. |
'WHERE ce_observation IN ('.implode(',', $this->obsIds).') '. |
'AND nom_sel IS NOT NULL '; |
|
$requeteVotes = 'SELECT ce_proposition, valeur, ce_utilisateur '. |
'FROM del_commentaire_vote '. |
'WHERE ce_proposition IN ('. |
'SELECT id_commentaire FROM '. |
'del_commentaire '. |
'WHERE ce_observation IN ('.implode(',', $this->obsIds).') '. |
'AND nom_sel IS NOT NULL'. |
') '. |
'ORDER BY ce_proposition'; |
|
$resultatsPropositions = $this->bdd->recupererTous($requetePropositions); |
$resultatsVotes = $this->bdd->recupererTous($requeteVotes); |
|
$propositions = array(); |
$votes = array(); |
|
foreach($resultatsVotes as $vote) { |
if(!isset($votes[$vote['ce_proposition']])) { |
$votes[$vote['ce_proposition']] = 0; |
} |
$valeur = ($vote['valeur'] == 1) ? 1 : -1; |
$votes[$vote['ce_proposition']] += is_numeric($vote['ce_utilisateur']) ? 3*$valeur : $valeur; |
} |
|
foreach($resultatsPropositions as $proposition) { |
$id_proposition = $proposition['id_commentaire']; |
$id_obs = $proposition['ce_observation']; |
|
if(isset($votes[$id_proposition])) { |
$score = $votes[$id_proposition]; |
} else { |
$score = -1; |
} |
|
$proposition['valeur'] = $score; |
|
if(!isset($propositions[$id_obs])) { |
$propositions[$id_obs] = $proposition; |
} else { |
$score_ancienne_proposition = $propositions[$id_obs]['valeur']; |
$propositions[$id_obs] = ($score >= $score_ancienne_proposition) ? |
$proposition : $propositions[$id_obs]; |
} |
} |
|
foreach ($images as $id => $image) { |
if ($this->doitRemplacerObservationParProposition($propositions, $image)) { |
$id_obs = $image['id_observation']; |
$images[$id]['determination.famille'] = $propositions[$id_obs]['famille']; |
$images[$id]['determination.ns'] = $propositions[$id_obs]['nom_ret']; |
$images[$id]['determination.nn'] = $propositions[$id_obs]['nom_ret_nn']; |
$images[$id]['determination.nt'] = $propositions[$id_obs]['nt']; |
} |
|
$images[$id]['url_fiche_eflore'] = $this->formaterUrlFicheEflore($images[$id]['determination.nn']); |
} |
|
return $images; |
} |
|
private function doitRemplacerObservationParProposition($propositions, $image) { |
return ((isset($propositions[$image['id_observation']]) && |
$propositions[$image['id_observation']] != null && |
$propositions[$image['id_observation']]['nom_ret_nn'] != 0) && |
($propositions[$image['id_observation']]['valeur'] > 0 || |
$image['determination.nn'] == 0) |
); |
} |
|
/*------------------------------------------------------------------------------- |
FORMATER ET METTRE EN FORME |
--------------------------------------------------------------------------------*/ |
|
/** |
* Formater une observation depuis une ligne liaison |
* @param $liaison liaison issue de la recherche |
* @return $observation l'observation mise en forme |
* */ |
private function formaterObservation($liaison) { |
$observation = array(); |
|
foreach ($this->mappingObservation as $nomOriginal => $nomFinal) { |
$observation[$nomFinal] = $liaison[$nomOriginal]; |
} |
|
return $observation; |
} |
|
/** |
* Formater le lien de l'image en fonction du fichier de config et de l'identifiant de l'image |
* */ |
private function formaterLienImage($idImage) { |
$idImage = sprintf('%09s', $idImage); |
$url = $this->conteneur->getParametre('url_images'); |
$urlImage = str_replace('%s', $idImage, $url); |
return $urlImage; |
} |
|
private function formaterLieu($image) { |
$lieu = $image['zone_geo']; |
if($image['ce_zone_geo'] != '') { |
$id_zone_geo = $image['ce_zone_geo']; |
if(strpos($image['ce_zone_geo'], 'INSEE-C:') === 0) { |
$id_zone_geo = str_replace('INSEE-C:', '', $image['ce_zone_geo']); |
$id_zone_geo = (strlen($id_zone_geo) >= 5) ? substr($id_zone_geo, 0, 2) : $id_zone_geo; |
} |
|
$lieu .= ' ('.$id_zone_geo.')'; |
} |
return $lieu; |
} |
|
private function formaterUrlFicheEflore($num_nom) { |
$url = $this->conteneur->getParametre('url_fiche_eflore'); |
return sprintf($url, $num_nom); |
} |
|
private function proteger($valeur) { |
if (is_array($valeur)) { |
return $this->bdd->protegerTableau($valeur); |
} else { |
return $this->bdd->proteger($valeur); |
} |
} |
} |
?> |