Subversion Repositories eFlore/Applications.del

Rev

Rev 1813 | Rev 1907 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php
// declare(encoding='UTF-8');
/**
 * Web service récupèrant toutes les données de la table del_obs_images
 * pour retourner une liste d'images associées à la détermination la plus probable.
 *
 * Possibilité de ne renvoyer que les images les mieux notées pour un protocole donné.
 *
 * @category   DEL
 * @package    Services
 * @subpackage Determinations
 * @version    0.1
 * @author     Mathias CHOUET <mathias@tela-botanica.org>
 * @author     Jean-Pascal MILCENT <jpm@tela-botanica.org>
 * @author     Aurelien 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>
 * @copyright  1999-2014 Tela Botanica <accueil@tela-botanica.org>
 */

class ListeImagesDeterminationsProbables {

        private $indexImagesIds = array();
        private $conteneur;
        private $navigation;
        private $bdd;

        private $erreurs = array();
        private $parametres = array();
        private $protocoles = array();

        private $resultats = array();
        private $propositions = array();
        private $votes = array();

        public function __construct(Conteneur $conteneur = null) {
                $this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
                $this->navigation = $conteneur->getNavigation();
                $this->bdd = $this->conteneur->getBdd();
                $this->chargerProtocoles();
        }

        private function chargerProtocoles() {
                $requete = 'SELECT id_protocole FROM del_image_protocole -- '.__FILE__.' : '.__LINE__;
                $resultats = $this->bdd->recupererTous($requete);
                if ($resultats) {
                        foreach ($resultats as $infos) {
                                $this->protocoles[] = $infos['id_protocole'];
                        }
                        sort($this->protocoles);
                }
        }

        public function consulter($parametres) {
                $this->parametres = $parametres;
                $this->verifierParametres();

                // Lancement du service
                $infos = $this->chargerInfos();
                $this->modifierEnteteTotal();
                if ($infos) {
                        $this->traiterResultats($infos);
                        $this->completerResutlats();
                }

                // Mettre en forme le résultat et l'envoyer pour affichage
                $resultat = new ResultatService();
                $resultat->corps = array('entete' => $this->navigation->getEntete(), 'resultats' => $this->resultats);
                return $resultat;
        }

        private function verifierParametres() {
                $this->verifierParamProtocole();
                $this->verifierParamVote();

                if (!empty($this->erreurs)) {
                        $msg = "Erreur de configuration :\n".implode("\n\n", $this->erreurs);
                        throw new Exception($msg, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
                }
        }

        private function verifierParamProtocole() {
                if (isset($this->parametres['masque.protocole'])) {
                        $protocoleExistant = in_array($this->parametres['masque.protocole'], $this->protocoles);

                        if (!is_numeric($this->parametres['masque.protocole']) || $protocoleExistant === false) {
                                $protocolesListe = implode(', ', $this->protocoles);
                                $msg = "La valeur pour le protocole doit être un entier compris dans les numéros de protocole ".
                                        "existants : $protocolesListe";
                                $this->erreurs[] = $msg;
                        }
                }
        }

        private function verifierParamVote() {
                if (isset($this->parametres['masque.valeur_min_vote'])) {
                        $minVote = $this->parametres['masque.valeur_min_vote'];
                        if (!is_numeric($minVote) || ($minVote < 0 && $minVote > 5)) {
                                $this->erreurs[] = "La valeur minimum de valeur des votes doit être un entier compris entre 0 et 5.";
                        }
                }
        }

        private function chargerInfos() {
                $whereClause = $this->getClauseWhere();
                $depart = $this->navigation->getDepart();
                $limite = $this->navigation->getLimite();

                $requete = 'SELECT SQL_CALC_FOUND_ROWS di.id_observation AS id_observation, nom_referentiel, nom_ret, '.
                        'nom_ret_nn, nt, famille, ce_zone_geo, zone_geo, lieudit, station, milieu, date_observation, '.
                        'di.mots_cles_texte AS mots_cles_texte, di.commentaire AS commentaire, '.
                        'di.i_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, di.nom_utilisateur, di.prenom_utilisateur, '.
                        'di.courriel_utilisateur, nom_original, ce_protocole, moyenne, nb_votes, nb_tags '.
                        'FROM v_del_image AS di '.
                        '       LEFT JOIN del_utilisateur AS du '.
                        '               ON du.id_utilisateur = IF(LENGTH(di.ce_utilisateur) > 5, 0, di.ce_utilisateur) '.
                        '       LEFT JOIN del_image_stat AS ds ON (di.id_image = ds.ce_image) '.
                        "$whereClause ".
                        'GROUP BY id_image '.
                        'ORDER BY moyenne '.
                        "LIMIT $depart, $limite ".
                        ' -- '.__FILE__.' : '.__LINE__;
                // TODO : optimisation voir http://www.tela-botanica.org/wikini/DevInformatiques/wakka.php?wiki=AppliDelOptmisationVues
                return $this->bdd->recupererTous($requete);
        }

        private function getClauseWhere() {
                $where = array();
                if (isset($this->parametres['masque.protocole'])) {
                        $protocoleIdP = $this->bdd->proteger($this->parametres['masque.protocole']);
                        $where[] = "ds.ce_protocole = $protocoleIdP ";
                }
                if (isset($this->parametres['masque.valeur_vote_min'])) {
                        $voteP = $this->bdd->proteger($this->parametres['masque.valeur_vote_min']);
                        $where[] = "moyenne >= $voteP";
                }
                return (count($where) > 0) ? 'WHERE '.implode(' AND ', $where).' ' : '';
        }

        private function modifierEnteteTotal() {
                $requete = 'SELECT FOUND_ROWS() AS nbre -- '.__FILE__.' : '.__LINE__;
                $compte = $this->bdd->recuperer($requete);
                $total = ($compte !== false) ? (int) $compte['nbre'] : 0;
                $this->navigation->setTotal($total);
        }

        /**
        * Retourner un tableau d'images formaté en fonction des liaisons trouvées
        * @param $infos les infos sur les images et observations
        * */
        private function traiterResultats($infos) {
                foreach ($infos as $info) {
                        $idImage = $info['id_image'];
                        $index = $this->formaterIndexResultat($info);

                        $this->obsIds[] = $info['id_observation'];
                        $this->indexImagesIds[$idImage] = $index;
                        $this->resultats[$index] = array(
                                'id_image' => $idImage,
                                'id_observation' => $info['id_observation'],
                                'auteur.intitule' => $this->formaterIntituleAuteur($info),
                                'binaire.href' => $this->formaterBinaireHref($info),
                                'determination.famille' => $info['famille'],
                                'determination.referentiel' => $info['nom_referentiel'],
                                'determination.ns' => $info['nom_ret'],
                                'determination.nn' => $info['nom_ret_nn'],
                                'determination.nt' => $info['nt'],
                                'date_observation' => $info['date_observation'],
                                'localite' => $this->formaterLieu($info),
                                'mots_cles_image_cel' => $this->formaterMotsClesCel($info),
                                'mots_cles_image_del' => ''
                        );
                }
        }

        private function formaterIndexResultat($infos) {
                return $infos['id_image'].'-'.$infos['id_observation'];
        }

        private function formaterIntituleAuteur($infos) {
                if ($infos['ce_utilisateur'] == 0) {
                        $infos['prenom'] = $infos['prenom_utilisateur'];
                        $infos['nom'] = $infos['nom_utilisateur'];
                }
                $intitule = $infos['prenom'].' '.$infos['nom'];
                return $intitule;
        }

        private function formaterBinaireHref($infos) {
                return sprintf($this->conteneur->getParametre('determinations.url_image_tpl'), $infos['id_image']);
        }

        private function formaterLieu($infos) {
                $lieuFormate = '';
                if ($infos['ce_zone_geo']) {
                        $lieu = $infos['zone_geo'];
                        $id_zone_geo = $infos['ce_zone_geo'];
                        if (strpos($infos['ce_zone_geo'], 'INSEE-C:') === 0) {
                                $id_zone_geo = str_replace('INSEE-C:', '', $infos['ce_zone_geo']);
                                $id_zone_geo = strlen($id_zone_geo) >= 5 ? substr($id_zone_geo, 0, 2) : $id_zone_geo;
                        }
                        $lieuFormate =  "$lieu ($id_zone_geo)";
                }
                return $lieuFormate;
        }

        /**
         * Formater les mots clés du cel en n'affichant que ceux faisant partie d'une liste définie dans le
         * fichier de configuration.
         *
         * @param $infos le tableau contenant les infos sur une image.
         * @return string la chaine filtrée
         */
        private function formaterMotsClesCel($infos) {
                $motsClesAffiches = $this->conteneur->getParametreTableau('determinations.mots_cles_cel_affiches');
                $motsClesCel = explode(',', $infos['mots_cles_texte_image']);
                $motsCles = array_intersect($motsClesAffiches, $motsClesCel);
                return implode(',', $motsCles);
        }

        private function completerResutlats() {
                $this->chargerVotes();
                $this->chargerPropositions();

                $this->completerMotsCles();

                foreach ($this->resultats as $index => $infos) {
                        if ($this->doitRemplacerObservationParProposition($index)) {
                                $id_obs = $infos['id_observation'];
                                $this->resultats[$index]['determination.famille'] = $this->propositions[$id_obs]['famille'];
                                $this->resultats[$index]['determination.ns'] = $this->propositions[$id_obs]['nom_sel'];
                                $this->resultats[$index]['determination.nn'] = $this->propositions[$id_obs]['nom_sel_nn'];
                                $this->resultats[$index]['determination.nt'] = $this->propositions[$id_obs]['nt'];
                        }
                        $this->completerUrlFicheEflore($index);
                }
        }

        private function chargerVotes() {
                $idsObs = implode(',', $this->obsIds);
                $requete = 'SELECT ce_proposition, valeur, ce_utilisateur '.
                        'FROM del_commentaire_vote '.
                        'WHERE ce_proposition IN '.
                        '( SELECT id_commentaire '.
                        '       FROM del_commentaire '.
                        "       WHERE ce_observation IN ($idsObs) AND nom_sel IS NOT NULL ) ".
                        'ORDER BY ce_proposition '.
                        ' -- '.__FILE__.' : '.__LINE__;
                $resultats = $this->bdd->recupererTous($requete);
                if ($resultats !== false) {
                        foreach ($resultats as $vote) {
                                if (!isset($this->votes[$vote['ce_proposition']])) {
                                        $this->votes[$vote['ce_proposition']] = 0;
                                }
                                $valeur = ($vote['valeur'] == 1) ? 1 : -1;
                                $this->votes[$vote['ce_proposition']] += is_numeric($vote['ce_utilisateur']) ? 3 * $valeur : $valeur;
                        }
                }
        }

        private function chargerPropositions() {
                $idsObs = implode(',', $this->obsIds);
                $requete = 'SELECT * '.
                        'FROM del_commentaire '.
                        "WHERE ce_observation IN ($idsObs) ".
                        'AND nom_sel IS NOT NULL '.
                        ' -- '.__FILE__.' : '.__LINE__;
                $resultats = $this->bdd->recupererTous($requete);

                foreach($resultats as $proposition) {
                        $id_proposition = $proposition['id_commentaire'];
                        $id_obs = $proposition['ce_observation'];
                        $proposition['valeur'] = (isset($this->votes[$id_proposition])) ? $this->votes[$id_proposition] : -1;

                        if (!isset($this->propositions[$id_obs])) {
                                $this->propositions[$id_obs] = $proposition;
                        } else {
                                $score_actuel = $proposition['valeur'];
                                $score_precedent = $this->propositions[$id_obs]['valeur'];
                                if ($score_actuel >= $score_precedent) {
                                        $this->propositions[$id_obs] = $proposition;
                                }
                        }
                }
        }

        private function completerMotsCles() {
                $idsImages = implode(',', array_keys($this->indexImagesIds));
                $requete = 'SELECT tag, ce_image '.
                        'FROM del_image_tag '.
                        "WHERE ce_image IN ($idsImages) ".
                        'AND actif = 1 '.
                        ' -- '.__FILE__.' : '.__LINE__;
                $resultats = $this->bdd->recupererTous($requete);

                foreach ($resultats as $info) {
                        $index = $this->indexImagesIds[$info['ce_image']];
                        $tag = ($this->resultats[$index]['mots_cles_image_del'] != '') ? ','.$info['tag'] : $info['tag'];
                        $this->resultats[$index]['mots_cles_image_del'] .= $tag ;
                }
        }

        private function doitRemplacerObservationParProposition($index) {
                $idObs = $this->resultats[$index]['id_observation'];
                return ((isset($this->propositions[$idObs])
                        && $this->propositions[$idObs] != null
                        && $this->propositions[$idObs]['nom_sel_nn'] != 0)
                        && ($this->propositions[$idObs]['valeur'] > 0 ||        $this->resultats[$index]['determination.nn'] == 0)
                );
        }

        private function completerUrlFicheEflore($index) {
                if (isset($this->resultats[$index]['determination.nn'])) {
                        $urlTpl = $this->conteneur->getParametre('determinations.url_fiche_eflore_tpl');
                        $nn = $this->resultats[$index]['determination.nn'];

                        $this->resultats[$index]['url_fiche_eflore'] = sprintf($urlTpl, $nn);
                }
        }
}