113,21 → 113,18 |
"commentaire" => 1, |
"ce_utilisateur" => "auteur.id", |
"nom_utilisateur" => "auteur.nom", |
"prenom_utilisateur" => "auteur.prenom", |
), |
"prenom_utilisateur" => "auteur.prenom",), |
'images' => array( // v_del_image |
'id_image' => 1, |
// l'alias suivant est particulier: in-fine il doit s'appeler mots_cles_texte |
// mais nous afin d'éviter un conflit d'alias nous le renommons plus tard (reformateImagesDoubleIndex) |
'i_mots_cles_texte' => 1 |
)); |
'i_mots_cles_texte' => 1) |
); |
|
|
public function __construct(Conteneur $conteneur = null) { |
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur; |
$this->conteneur->chargerConfiguration('config_images.ini'); |
$this->gestionBdd = $conteneur->getGestionBdd(); |
$this->bdd = $this->gestionBdd->getBdd(); |
$this->bdd = $conteneur->getGestionBdd()->getBdd(); |
} |
|
public function consulter($ressources, $parametres) { |
145,7 → 142,6 |
// Contrairement à IdentiPlantes, nous n'avons de HAVING pour PictoFlora, mais par contre un ORDER BY |
$req = array('select' => array(), 'join' => array(), 'where' => array(), 'groupby' => array(), 'orderby' => array()); |
|
|
$db = $this->bdd; |
|
// filtrage de l'INPUT général, on réutilise 90% de identiplante en terme de paramètres autorisés |
153,14 → 149,12 |
// Évitons ce genre de chose pour PictoFlora et les risques de conflits avec masque.tag |
// même si ceux-ci sont improbables (pas d'<input> pour cela). |
$params_ip = DelTk::requestFilterParams($parametres, |
array_diff(DelTk::$parametres_autorises, |
array('masque.type')), |
array_diff(DelTk::$parametres_autorises, array('masque.type')), |
$this->conteneur); |
|
// notre propre filtrage sur l'INPUT |
$params_pf = self::requestFilterParams($parametres, |
array_merge(DelTk::$parametres_autorises, |
self::$parametres_autorises)); |
array_merge(DelTk::$parametres_autorises, self::$parametres_autorises)); |
|
/* filtrage des tags + sémantique des valeurs multiples: |
Lorsqu'on utilise masque.tag* pour chercher des tags, ils sont |
167,7 → 161,6 |
postulés comme séparés par des virgule, et l'un au moins des tags doit matcher. */ |
$params_pf['masque.tag_cel'] = DelTk::buildTagsAST(@$parametres['masque.tag_cel'], 'OR', ','); |
|
|
if(!isset($parametres['masque.tag_pictoflora']) && isset($parametres['masque.tag'])) { |
$parametres['masque.tag_pictoflora'] = $parametres['masque.tag']; |
} |
202,13 → 195,8 |
$resultat->corps = array('entete' => DelTk::makeJSONHeader(0, $params, Config::get('url_service')), |
'resultats' => array()); |
return $resultat; |
/* |
header('HTTP/1.0 404 Not Found'); |
// don't die (phpunit) |
throw(new Exception()); */ |
} |
|
|
// idobs est une liste (toujours ordonnée) des id d'observations recherchées |
$idobs = array_values(array_map(create_function('$a', 'return $a["id_image"];'), $idobs_tab)); |
$total = $db->recuperer('SELECT FOUND_ROWS() AS c'); $total = intval($total['c']); |
215,23 → 203,6 |
|
$liaisons = self::chargerImages($db, $idobs); |
|
// debug: infos de score |
/*$infosScore = array(); |
foreach ($idobs_tab as $iot) { |
$infosScore[$iot['id_image']] = array( |
'nb_votes' => $iot['nb_votes'], |
'nb_points' => $iot['nb_points'], |
'moyenne' => $iot['moyenne'] |
); |
}*/ |
/* |
// Q&D |
$images = array(); |
$o = new Observation($this->conteneur); |
foreach($idobs as $i) { |
$images[$i] = $o->consulter(array($i), array('justthrow' => 1)); |
} |
*/ |
list($images, $images_keyed_by_id_image) = self::reformateImagesDoubleIndex( |
$liaisons, |
$this->conteneur->getParametre('images.url_images'), |
245,7 → 216,9 |
// Mais magiquement (par référence), cela va remplir notre tableau indexé par couple d'id (id_image, id_observation) |
// cf reformateImagesDoubleIndex() à qui revient la tâche de créer ces deux versions simultanément lorsque |
// c'est encore possible. |
if($votes) Observation::mapVotesToImages($votes, $images_keyed_by_id_image); |
if ($votes) { |
Observation::mapVotesToImages($votes, $images_keyed_by_id_image); |
} |
|
// les deux masques de tags sont transformés en AST dans le processus de construction de la requête. |
// Reprenous les paramètres originaux non-nettoyés (ils sont valables car le nettoyage est déterministe) |
252,11 → 225,35 |
$params_header = array_merge($params, array_filter(array('masque.tag_cel' => @$parametres['masque.tag_cel'], |
'masque.tag_pictoflora' => @$parametres['masque.tag_pictoflora']))); |
$resultat = new ResultatService(); |
$resultat->corps = array('entete' => DelTk::makeJSONHeader($total, $params_header, Config::get('url_service')), |
$resultat->corps = array( |
'entete' => DelTk::makeJSONHeader($total, $params_header, Config::get('url_service')), |
'resultats' => $images); |
return $resultat; |
} |
|
public function supprimer($ressources) { |
$idImage = $ressources[0]; |
$controlAcces = $this->conteneur->getControleAcces(); |
|
$retour = false; |
if ($controlAcces->controlerIpAutorisees()) { |
if ($controlAcces->etreUtilisateurAvecDroitAdmin()) { |
$urlServiceBase = $this->conteneur->getParametre('url_service_suppression_image'); |
$url = $urlServiceBase.$idImage; |
|
$clientHttp = $this->conteneur->getRestClient(); |
echo $url; |
$retour = $clientHttp->supprimer($url); |
echo $retour; |
} else { |
$message = "Vous ne pouvez pas accéder à ce service car vous n'avez pas les droits d'administrateur !\n"; |
$code = RestServeur::HTTP_CODE_ACCES_NON_AUTORISE; |
throw new Exception($message, $code); |
} |
} |
return $retour; |
} |
|
/** |
* TODO: partie spécifique liées à la complexité de PictoFlora: |
* génération de la clause ORDER BY (génère la valeur de la clef orderby' de $req) |
317,7 → 314,6 |
$req['where'][] = 'vdi.milieu LIKE '.$db->proteger('%' . $p['masque.milieu'].'%'); |
} |
|
|
/* Pour le tri par AVG() des votes nous avons toujours un protocole donné, |
celui-ci indique sur quels votes porte l'AVG. |
(c'est un *vote* qui porte sur un protocole et non l'image elle-même) */ |
372,8 → 368,7 |
$db->proteger("%".$val."%"));'), |
$db); |
$req['where'][] = '(' . implode(' AND ', $tags) . ')'; |
} |
else { |
} else { |
$req['where'][] = sprintf("CONCAT(vdi.mots_cles_texte,vdi.i_mots_cles_texte) REGEXP %s", |
$db->proteger(implode('|', $p['masque.tag_cel']['OR']))); |
} |
403,10 → 398,11 |
if(isset($p['masque.tag_pictoflora']['AND'])) { |
// TODO/XXX : comment matcher les observations ayant tous les mots-clef passés ? |
// ... le LEFT-JOIN n'y semble pas adapté |
} else { |
$protected_tags = array(); |
foreach ($p['masque.tag_pictoflora']['OR'] as $tag) { |
$protected_tags[] = $db->proteger(strtolower($tag)); |
} |
else { |
$protected_tags = array(); |
foreach($p['masque.tag_pictoflora']['OR'] as $tag) $protected_tags[] = $db->proteger(strtolower($tag)); |
$req['where'][] = sprintf('tag_normalise IN (%s)', implode(',', $protected_tags)); |
} |
} |
428,8 → 424,7 |
" GROUP BY ce_image". |
" HAVING GROUP_CONCAT(tag_normalise ORDER BY tag_normalise) REGEXP %s)", |
$db->proteger(implode('.*', $p['masque.tag_pictoflora']['AND']))); |
} |
else { |
} else { |
$req['where'][] = sprintf("vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1". |
" GROUP BY ce_image". |
" HAVING GROUP_CONCAT(tag_normalise) REGEXP %s)", |
455,9 → 450,7 |
$ids = @array_map(create_function('$e', 'return $e["ce_image"];'), $ids); |
$ids = !empty($ids) ? implode(',', $ids) : 'SELECT ce_image FROM del_image_tag WHERE false'; |
$req['where'][] = sprintf("vdi.id_image IN (%s)", $ids); |
|
} |
else { |
} else { |
$ids = @$db->recupererTous(sprintf( |
"SELECT ce_image FROM del_image_tag WHERE actif = 1". |
" GROUP BY ce_image". |
563,12 → 556,13 |
|
/* Lorsqu'on utilise le masque général pour chercher des tags, ils sont |
postulés comme séparés par des espaces, et doivent être tous matchés. */ |
if(isset($or_params['masque.tag_cel'])) |
if (isset($or_params['masque.tag_cel'])) { |
$or_masque['masque.tag_cel'] = DelTk::buildTagsAST($p['masque'], 'AND', ' '); |
if(isset($or_params['masque.tag_pictoflora'])) |
} |
if (isset($or_params['masque.tag_pictoflora'])) { |
$or_masque['masque.tag_pictoflora'] = DelTk::buildTagsAST($p['masque'], 'AND', ' '); |
} |
|
|
// pas de select, groupby & co ici: uniquement 'join' et 'where' |
$or_req = array('join' => array(), 'where' => array()); |
DelTk::sqlAddConstraint($or_masque, $db, $or_req); |
604,7 → 598,9 |
); |
|
unset($o['id_image'], $o['i_mots_cles_texte'], $o['jsonindex']); |
if(!isset($obs_merged[$id])) $obs_merged[$id] = $image; |
if (!isset($obs_merged[$id])) { |
$obs_merged[$id] = $image; |
} |
$obs_merged[$id]['observation'] = $o; |
$obs_merged[$id]['protocoles_votes'] = array(); |
|
614,8 → 610,6 |
return array($obs_merged,$obs_keyed_by_id_image); |
} |
|
|
|
// complete & override DelTk::requestFilterParams() (même usage) |
static function requestFilterParams(Array $params, $parametres_autorises = NULL) { |
if($parametres_autorises) { // filtrage de toute clef inconnue |
627,7 → 621,9 |
$p['format'] = DelTk::unsetIfInvalid($params, 'format', self::$format_image_possible); |
|
// "milieu" inutile pour IdentiPlantes ? |
if(isset($params['masque.milieu'])) $p['masque.milieu'] = trim($params['masque.milieu']); |
if (isset($params['masque.milieu'])) { |
$p['masque.milieu'] = trim($params['masque.milieu']); |
} |
|
// compatibilité |
if(isset($params['masque.tag'])) { |
646,29 → 642,5 |
return array_filter($p, create_function('$a','return !in_array($a, array("",false,null),true);')); |
} |
|
|
|
// met à jour *toutes* les stats de nombre de tags et de moyenne des votes |
static function _update_statistics($db) { |
$db->requeter("TRUNCATE TABLE del_image_stat"); |
$db->requeter(<<<EOF |
INSERT INTO `del_image_stat` ( |
SELECT id_image, divo.ce_protocole, divo.moyenne, divo.nb_votes, dit.ctags |
FROM `tb_cel`.`cel_images` ci |
LEFT JOIN |
( SELECT ce_image, ce_protocole, AVG(valeur) AS moyenne, COUNT(valeur) AS nb_votes FROM del_image_vote |
GROUP BY ce_image, ce_protocole ) AS divo |
ON ci.id_image = divo.ce_image |
LEFT JOIN |
( SELECT ce_image, COUNT(id_tag) as ctags FROM del_image_tag |
GROUP BY ce_image ) AS dit |
ON ci.id_image = dit.ce_image ) |
EOF |
); |
} |
|
static function revOrderBy($orderby) { |
// @TODO plutôt 'desc' ? '' : 'desc', non ? |
return $orderby == 'asc' ? 'desc' : 'asc'; |
} |
} |
?> |