Line 63... |
Line 63... |
63 |
// del/services/0.1/images?navigation.depart=0&navigation.limite=12&tri=votes&ordre=desc&protocole=3
|
63 |
// del/services/0.1/images?navigation.depart=0&navigation.limite=12&tri=votes&ordre=desc&protocole=3
|
64 |
// del/services/0.1/images?navigation.depart=0&navigation.limite=12&tri=votes&ordre=desc&protocole=3&masque=plop
|
64 |
// del/services/0.1/images?navigation.depart=0&navigation.limite=12&tri=votes&ordre=desc&protocole=3&masque=plop
|
Line 65... |
Line 65... |
65 |
|
65 |
|
Line -... |
Line 66... |
- |
|
66 |
class ListeImages2 {
|
66 |
class ListeImages2 {
|
67 |
|
Line 67... |
Line 68... |
67 |
|
68 |
// TODO: PHP-x.y, ces variables devrait être des "const"
|
Line 68... |
Line 69... |
68 |
static $format_image_possible = array('O','CRX2S','CRS','CXS','CS','XS','S','M','L','XL','X2L','X3L');
|
69 |
static $format_image_possible = array('O','CRX2S','CRS','CXS','CS','XS','S','M','L','XL','X2L','X3L');
|
69 |
|
70 |
|
Line 70... |
Line 71... |
70 |
static $tri_possible = array('date_observation', 'votes', 'tags');
|
71 |
static $tri_possible = array('date_transmission', 'date_observation', 'votes', 'tags');
|
Line 140... |
Line 141... |
140 |
$params_ip = ListeObservations2::requestFilterParams($parametres,
|
141 |
$params_ip = ListeObservations2::requestFilterParams($parametres,
|
141 |
array_diff(ListeObservations2::$parametres_autorises,
|
142 |
array_diff(ListeObservations2::$parametres_autorises,
|
142 |
array('masque.type')),
|
143 |
array('masque.type')),
|
143 |
$this->conteneur);
|
144 |
$this->conteneur);
|
Line 144... |
Line -... |
144 |
|
- |
|
145 |
// Cette variable est utile au filtrage des tags
|
- |
|
146 |
// Elle peut-être redéfinie en interne par sqlAddMasqueConstraint() ci-dessous
|
- |
|
147 |
// lorsque celui-ci transforme le masque général en masque par champ
|
- |
|
148 |
// et ré-appelle self::requestFilterParams()
|
- |
|
149 |
$parametres['tag_explode_char'] = ','; // " " (whitespace) ou "," ou NULL
|
- |
|
150 |
// tag_explode_semantic est lui utilisé lors de l'ajout des contraintes sur tags self::sqlAddConstraint()
|
- |
|
151 |
$parametres['tag_explode_semantic'] = 'OR'; // "AND" ou "OR" (si 'tag_explode_char' NOT NULL)
|
145 |
|
152 |
// notre propre filtrage sur l'INPUT
|
146 |
// notre propre filtrage sur l'INPUT
|
153 |
$params_pf = self::requestFilterParams($parametres,
|
147 |
$params_pf = self::requestFilterParams($parametres,
|
154 |
array_merge(ListeObservations2::$parametres_autorises,
|
148 |
array_merge(ListeObservations2::$parametres_autorises,
|
Line -... |
Line 149... |
- |
|
149 |
self::$parametres_autorises));
|
- |
|
150 |
|
- |
|
151 |
/* filtrage des tags + sémantique des valeurs multiples:
|
- |
|
152 |
Lorsqu'on utilise masque.tag* pour chercher des tags, ils sont
|
- |
|
153 |
postulés comme séparés par des virgule, et l'un au moins des tags doit matcher. */
|
Line 155... |
Line 154... |
155 |
self::$parametres_autorises));
|
154 |
$params_pf['masque.tag_cel'] = self::buildTagsAST(@$parametres['masque.tag_cel'], 'OR', ',');
|
156 |
|
155 |
$params_pf['masque.tag_pictoflora'] = self::buildTagsAST(@$parametres['masque.tag_pictoflora'], 'OR', ',');
|
157 |
|
156 |
|
158 |
$params = array_merge(ListeObservations2::$default_params, // paramètre par défaut Identiplante
|
157 |
$params = array_merge(ListeObservations2::$default_params, // paramètre par défaut Identiplante
|
Line 230... |
Line 229... |
230 |
* les "mieux notées", ou bien les images ayant le "plus de tags" (COUNT())
|
229 |
* les "mieux notées", ou bien les images ayant le "plus de tags" (COUNT())
|
231 |
*/
|
230 |
*/
|
232 |
static function sqlOrderBy($p, $db, &$req) {
|
231 |
static function sqlOrderBy($p, $db, &$req) {
|
233 |
// parmi self::$tri_possible
|
232 |
// parmi self::$tri_possible
|
234 |
if($p['tri'] == 'votes') { // LEFT JOIN sur "dis" ci-dessous
|
233 |
if($p['tri'] == 'votes') { // LEFT JOIN sur "dis" ci-dessous
|
235 |
$req['orderby'] = 'dis.moyenne ' . $p['ordre'];
|
234 |
$req['orderby'] = 'dis.moyenne ' . $p['ordre'] . ', dis.nb_votes ' . $p['ordre'];
|
236 |
return;
|
235 |
return;
|
237 |
}
|
236 |
}
|
Line 238... |
Line 237... |
238 |
|
237 |
|
239 |
if($p['tri'] == 'tags') { // LEFT JOIN sur "dis" ci-dessous
|
238 |
if($p['tri'] == 'tags') { // LEFT JOIN sur "dis" ci-dessous
|
240 |
$req['orderby'] = 'dis.nb_tags ' . $p['ordre'];
|
239 |
$req['orderby'] = 'dis.nb_tags ' . $p['ordre'];
|
241 |
return;
|
240 |
return;
|
Line -... |
Line 241... |
- |
|
241 |
}
|
- |
|
242 |
|
- |
|
243 |
if($p['tri'] == 'date_observation') {
|
- |
|
244 |
$req['orderby'] = 'date_observation ' . $p['ordre'] . ', id_observation ' . $p['ordre'];
|
- |
|
245 |
return;
|
242 |
}
|
246 |
}
|
243 |
|
- |
|
244 |
// tri == 'date_transmission'
|
247 |
|
245 |
$req['orderby'] = 'date_transmission ' . $p['ordre'];
|
248 |
// tri == 'date_transmission'
|
246 |
// avant cel:r1860, date_transmission pouvait être NULL
|
249 |
// avant cel:r1860, date_transmission pouvait être NULL
|
247 |
// or nous voulons de la consistence (notamment pour phpunit)
|
250 |
// or nous voulons de la consistence (notamment pour phpunit)
|
Line 248... |
Line 251... |
248 |
$req['orderby'] .= ', id_observation ' . $p['ordre'];
|
251 |
$req['orderby'] = 'date_transmission ' . $p['ordre'] . ', id_observation ' . $p['ordre'];
|
249 |
}
|
252 |
}
|
250 |
|
253 |
|
Line 313... |
Line 316... |
313 |
($p['ordre'] == 'desc') ? 'INNER' : 'LEFT');
|
316 |
($p['ordre'] == 'desc') ? 'INNER' : 'LEFT');
|
314 |
// nécessaire (dup ce_image dans del_image_stat)
|
317 |
// nécessaire (dup ce_image dans del_image_stat)
|
315 |
$req['groupby'][] = 'vdi.id_observation';
|
318 |
$req['groupby'][] = 'vdi.id_observation';
|
316 |
}
|
319 |
}
|
Line 317... |
Line -... |
317 |
|
- |
|
318 |
|
- |
|
319 |
// TODO: support du "ET", "OU", "(", ")"
|
320 |
|
320 |
// http://codehackit.blogspot.fr/2011/08/expression-parser-in-php.html
|
321 |
// car il ne sont pas traités par la générique requestFilterParams() les clefs "masque.tag_*"
|
321 |
// http://blog.angeloff.name/post/2012/08/05/php-recursive-patterns/
|
322 |
// sont toujours présentes; bien que parfois NULL.
|
322 |
if(!empty($p['masque.tag_cel'])) {
|
323 |
if($p['masque.tag_cel']) {
|
323 |
if($p['tag_explode_semantic'] == 'AND') {
|
324 |
if(isset($p['masque.tag_cel']['AND'])) {
|
324 |
// TODO: utiliser les tables de mots clefs normaliées dans tb_cel ?
|
325 |
// TODO: utiliser les tables de mots clefs normaliées dans tb_cel ?
|
325 |
// et auquel cas laisser au client le choix du couteux "%" ?
|
326 |
// et auquel cas laisser au client le choix du couteux "%" ?
|
326 |
$tags = $p['masque.tag_cel'];
|
327 |
$tags = $p['masque.tag_cel']['AND'];
|
327 |
array_walk($tags, create_function('&$val, $k, $db',
|
328 |
array_walk($tags, create_function('&$val, $k, $db',
|
328 |
'$val = sprintf("CONCAT(vdi.mots_cles_texte,vdi.i_mots_cles_texte) LIKE %s",
|
329 |
'$val = sprintf("CONCAT(vdi.mots_cles_texte,vdi.i_mots_cles_texte) LIKE %s",
|
329 |
$db->proteger("%".$val."%"));'),
|
330 |
$db->proteger("%".$val."%"));'),
|
330 |
$db);
|
331 |
$db);
|
331 |
$req['where'][] = implode(' AND ', $tags);
|
332 |
$req['where'][] = '(' . implode(' AND ', $tags) . ')';
|
332 |
}
|
333 |
}
|
333 |
else { // OR assumed
|
334 |
else {
|
334 |
$req['where'][] = sprintf("CONCAT(vdi.mots_cles_texte,vdi.mots_cles_texte) REGEXP %s",
|
335 |
$req['where'][] = sprintf("CONCAT(vdi.mots_cles_texte,vdi.i_mots_cles_texte) REGEXP %s",
|
335 |
$db->proteger(implode('|', $p['masque.tag_cel'])));
|
336 |
$db->proteger(implode('|', $p['masque.tag_cel']['OR'])));
|
336 |
}
|
337 |
}
|
Line 337... |
Line 338... |
337 |
}
|
338 |
}
|
338 |
|
339 |
|
339 |
|
340 |
|
340 |
// XXX: utiliser tag plutôt que tag_normalise ?
|
341 |
// XXX: utiliser tag plutôt que tag_normalise ?
|
341 |
if(!empty($p['masque.tag_pictoflora'])) {
|
342 |
if($p['masque.tag_pictoflora']) {
|
Line 342... |
Line 343... |
342 |
// pas de LEFT JOIN ? ou bien peut-être en cas de tri, mais nous parlons bien ici d'un masque
|
343 |
// pas de LEFT JOIN ? ou bien peut-être en cas de tri, mais nous parlons bien ici d'un masque
|
343 |
/* $req['join'][] = 'LEFT JOIN del_image_tag dit ON dit.ce_image = vdi.id_image';
|
344 |
/* $req['join'][] = 'LEFT JOIN del_image_tag dit ON dit.ce_image = vdi.id_image';
|
344 |
$req['where'][] = 'dit.actif = 1'; */
|
345 |
$req['where'][] = 'dit.actif = 1'; */
|
345 |
|
346 |
|
346 |
if($p['tag_explode_semantic'] == 'AND') {
|
347 |
if(isset($p['masque.tag_pictoflora']['AND'])) {
|
347 |
// optimsation: en cas de "AND" on sort() l'input et le GROUP_CONCAT()
|
348 |
// optimsation: en cas de "AND" on sort() l'input et le GROUP_CONCAT()
|
348 |
// donc nous utilisons des ".*" plutôt que de multiples conditions et "|"
|
349 |
// donc nous utilisons des ".*" plutôt que de multiples conditions et "|"
|
349 |
sort($p['masque.tag_pictoflora']);
|
350 |
sort($p['masque.tag_pictoflora']['AND']);
|
350 |
$req['where'][] = sprintf("vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1".
|
351 |
$req['where'][] = sprintf("vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1".
|
351 |
" GROUP BY ce_image".
|
352 |
" GROUP BY ce_image".
|
352 |
" HAVING GROUP_CONCAT(tag_normalise ORDER BY tag_normalise) REGEXP %s)",
|
353 |
" HAVING GROUP_CONCAT(tag_normalise ORDER BY tag_normalise) REGEXP %s)",
|
353 |
$db->proteger(implode('.*', $p['masque.tag_pictoflora'])));
|
354 |
$db->proteger(implode('.*', $p['masque.tag_pictoflora']['AND'])));
|
354 |
}
|
355 |
}
|
355 |
else { // OR assumed
|
356 |
else {
|
356 |
$req['where'][] = sprintf("vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1".
|
357 |
$req['where'][] = sprintf("vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1".
|
357 |
" GROUP BY ce_image".
|
358 |
" GROUP BY ce_image".
|
358 |
" HAVING GROUP_CONCAT(tag_normalise) REGEXP %s)",
|
- |
|
359 |
$db->proteger(implode('|', $p['masque.tag_pictoflora'])));
|
359 |
" HAVING GROUP_CONCAT(tag_normalise) REGEXP %s)",
|
Line -... |
Line 360... |
- |
|
360 |
$db->proteger(implode('|', $p['masque.tag_pictoflora']['OR'])));
|
360 |
}
|
361 |
}
|
361 |
}
|
362 |
}
|
362 |
|
363 |
}
|
363 |
}
|
364 |
|
364 |
|
365 |
|
Line 410... |
Line 411... |
410 |
$or_params = array('masque.auteur' => $p['masque'],
|
411 |
$or_params = array('masque.auteur' => $p['masque'],
|
411 |
'masque.departement' => $p['masque'],
|
412 |
'masque.departement' => $p['masque'],
|
412 |
'masque.commune' => $p['masque'], // TODO/XXX ?
|
413 |
'masque.commune' => $p['masque'], // TODO/XXX ?
|
413 |
'masque.id_zone_geo' => $p['masque'],
|
414 |
'masque.id_zone_geo' => $p['masque'],
|
Line 414... |
Line 415... |
414 |
|
415 |
|
- |
|
416 |
/* tous-deux remplacent masque.tag
|
415 |
// tous-deux remplacent masque.tag
|
417 |
mais sont traité séparément des requestFilterParams() */
|
416 |
'masque.tag_cel' => $p['masque'],
|
418 |
// 'masque.tag_cel' => $p['masque'],
|
Line 417... |
Line 419... |
417 |
'masque.tag_pictoflora' => $p['masque'],
|
419 |
// 'masque.tag_pictoflora' => $p['masque'],
|
418 |
|
420 |
|
419 |
'masque.ns' => $p['masque'],
|
421 |
'masque.ns' => $p['masque'],
|
420 |
'masque.famille' => $p['masque'],
|
422 |
'masque.famille' => $p['masque'],
|
Line 426... |
Line 428... |
426 |
'tri' => $p['tri'],
|
428 |
'tri' => $p['tri'],
|
427 |
'ordre' => $p['ordre']);
|
429 |
'ordre' => $p['ordre']);
|
Line 428... |
Line 430... |
428 |
|
430 |
|
429 |
$or_masque = array_merge(
|
431 |
$or_masque = array_merge(
|
430 |
ListeObservations2::requestFilterParams($or_params, NULL, $c /* pour masque.departement */),
|
432 |
ListeObservations2::requestFilterParams($or_params, NULL, $c /* pour masque.departement */),
|
- |
|
433 |
self::requestFilterParams($or_params));
|
- |
|
434 |
|
- |
|
435 |
/* Lorsqu'on utilise le masque général pour chercher des tags, ils sont
|
431 |
self::requestFilterParams($or_params),
|
436 |
postulés comme séparés par des espaces, et doivent être tous matchés. */
|
- |
|
437 |
$or_masque['masque.tag_cel'] = self::buildTagsAST($p['masque'], 'AND', ' ');
|
Line -... |
Line 438... |
- |
|
438 |
$or_masque['masque.tag_pictoflora'] = self::buildTagsAST($p['masque'], 'AND', ' ');
|
432 |
array('tag_explode_char' => ' ', 'tag_explode_semantic' => 'AND')); // spéciaux
|
439 |
|
433 |
|
440 |
|
434 |
// pas de select, groupby & co ici
|
441 |
// pas de select, groupby & co ici: uniquement 'join' et 'where'
|
435 |
$or_req = array('join' => array(), 'where' => array());
|
442 |
$or_req = array('join' => array(), 'where' => array());
|
Line 436... |
Line 443... |
436 |
ListeObservations2::sqlAddConstraint($or_masque, $db, $or_req);
|
443 |
ListeObservations2::sqlAddConstraint($or_masque, $db, $or_req);
|
Line 442... |
Line 449... |
442 |
$req['join'] = array_unique(array_merge($req['join'], $or_req['join']));
|
449 |
$req['join'] = array_unique(array_merge($req['join'], $or_req['join']));
|
443 |
}
|
450 |
}
|
444 |
}
|
451 |
}
|
445 |
}
|
452 |
}
|
Line 446... |
Line 453... |
446 |
|
453 |
|
447 |
// complete & override ListeObservations2::requestFilterParams()
|
454 |
// complete & override ListeObservations2::requestFilterParams() (même usage)
|
448 |
static function requestFilterParams(Array $params, $parametres_autorises = NULL) {
|
455 |
static function requestFilterParams(Array $params, $parametres_autorises = NULL) {
|
449 |
if($parametres_autorises) { // filtrage de toute clef inconnue
|
456 |
if($parametres_autorises) { // filtrage de toute clef inconnue
|
450 |
$params = array_intersect_key($params, array_flip($parametres_autorises));
|
457 |
$params = array_intersect_key($params, array_flip($parametres_autorises));
|
Line 451... |
Line 458... |
451 |
}
|
458 |
}
|
452 |
|
459 |
|
453 |
$p = array();
|
460 |
$p = array();
|
Line 454... |
Line 461... |
454 |
$p['tri'] = ListeObservations2::unsetIfInvalid($params, 'tri', self::$tri_possible);
|
461 |
$p['tri'] = ListeObservations2::unsetIfInvalid($params, 'tri', self::$tri_possible);
|
455 |
$p['format'] = ListeObservations2::unsetIfInvalid($params, 'format', self::$format_image_possible);
|
462 |
$p['format'] = ListeObservations2::unsetIfInvalid($params, 'format', self::$format_image_possible);
|
Line 456... |
Line 463... |
456 |
|
463 |
|
457 |
// et pour identiplantes ?
|
464 |
// "milieu" inutile pour IdentiPlantes ?
|
458 |
if(isset($params['masque.milieu'])) $p['masque.milieu'] = trim($params['masque.milieu']);
|
465 |
if(isset($params['masque.milieu'])) $p['masque.milieu'] = trim($params['masque.milieu']);
|
459 |
|
466 |
|
Line 460... |
Line -... |
460 |
// compatibilité
|
- |
|
461 |
if(isset($params['masque.tag'])) {
|
- |
|
462 |
$params['masque.tag_cel'] = $params['masque.tag_pictoflora'] = $params['masque.tag'];
|
- |
|
463 |
}
|
- |
|
464 |
|
- |
|
465 |
/* Nous n'implod()ons pas ici, car la sémantique des éléments multiples est
|
- |
|
466 |
variable (tag_explode_semantic) et considérée plus tard, notamment lors de la
|
- |
|
467 |
construction du SQL (sqlAddConstraint()).
|
- |
|
468 |
Cette sémantique peut varier selon que ces tags proviennent du formulaire de
|
- |
|
469 |
recherche avancée ou via le masque général (et l'appel récursif à requestFilterParams()
|
- |
|
470 |
qu'il implique) */
|
- |
|
471 |
if(isset($params['masque.tag_cel'])) {
|
- |
|
472 |
if(isset($params['tag_explode_char'])) {
|
- |
|
473 |
$x = explode($params['tag_explode_char'], $params['masque.tag_cel']);
|
- |
|
474 |
$x = array_map('trim', $x);
|
- |
|
475 |
$p['masque.tag_cel'] = array_filter($x);
|
- |
|
476 |
} else {
|
- |
|
477 |
// toujours un tableau
|
- |
|
478 |
$p['masque.tag_cel'] = array(trim($params['masque.tag_cel']));
|
- |
|
479 |
}
|
- |
|
480 |
|
- |
|
481 |
}
|
- |
|
482 |
|
- |
|
483 |
if(isset($params['masque.tag_pictoflora'])) {
|
- |
|
484 |
if(isset($params['tag_explode_char'])) {
|
- |
|
485 |
$x = explode($params['tag_explode_char'], $params['masque.tag_pictoflora']);
|
- |
|
486 |
$x = array_map('trim', $x);
|
- |
|
487 |
$p['masque.tag_pictoflora'] = array_filter($x);
|
- |
|
488 |
} else {
|
- |
|
489 |
// toujours un tableau
|
467 |
// compatibilité
|
490 |
$p['masque.tag_pictoflora'] = array(trim($params['masque.tag_pictoflora']));
|
468 |
if(isset($params['masque.tag'])) {
|
491 |
}
|
469 |
$params['masque.tag_cel'] = $params['masque.tag_pictoflora'] = $params['masque.tag'];
|
492 |
}
|
470 |
}
|
493 |
|
471 |
|
Line 501... |
Line 479... |
501 |
|
479 |
|
502 |
return array_filter($p, create_function('$a','return !in_array($a, array("",false,null),true);'));
|
480 |
return array_filter($p, create_function('$a','return !in_array($a, array("",false,null),true);'));
|
Line -... |
Line 481... |
- |
|
481 |
}
|
- |
|
482 |
|
- |
|
483 |
|
- |
|
484 |
/* Construit un (vulgaire) abstract syntax tree:
|
- |
|
485 |
"AND" => [ "tag1", "tag2" ]
|
- |
|
486 |
Idéalement (avec un parser simple comme proposé par http://hoa-project.net/Literature/Hack/Compiler.html#Langage_PP)
|
- |
|
487 |
nous aurions:
|
- |
|
488 |
"AND" => [ "tag1", "tag2", "OR" => [ "tag3", "tag4" ] ]
|
- |
|
489 |
|
- |
|
490 |
Ici nous devons traiter les cas suivants:
|
- |
|
491 |
tags séparés par des "ET/AND OU/OR", séparés par des espaces ou des virgules.
|
- |
|
492 |
Mais la chaîne peut aussi avoir été issue du "masque général" (la barre de recherche générique).
|
- |
|
493 |
ce qui implique des comportement par défaut différents afin de préserver la compatibilité.
|
- |
|
494 |
|
- |
|
495 |
Théorie:
|
- |
|
496 |
1) tags passés par "champ tag":
|
- |
|
497 |
- support du ET/OU, et explode par virgule.
|
- |
|
498 |
- si pas d'opérande détectée: "OU"
|
- |
|
499 |
|
- |
|
500 |
2) tags passés par "recherche générale":
|
- |
|
501 |
- support du ET/OU, et explode par whitespace.
|
- |
|
502 |
- si pas d'opérande détectée: "ET"
|
- |
|
503 |
|
- |
|
504 |
La présence de $additional_sep s'explique car ET/OU sous-entendent une séparation par des espaces.
|
- |
|
505 |
Mais ce n'est pas toujours pertinent car: 1) la compatibilité suggère de considérer parfois
|
- |
|
506 |
la virgule comme séparateur et 2) les tags *peuvent* contenir des espaces. Par conséquent:
|
- |
|
507 |
* a,b,c => "a" $default_op "b" $default_op "c"
|
- |
|
508 |
* a,b AND c => "a" AND "b" AND "c"
|
- |
|
509 |
* a OR b AND c,d => "a" AND "b" AND "c" AND "d"
|
- |
|
510 |
C'est à dire par ordre décroissant de priorité:
|
- |
|
511 |
1) opérande contenu dans la chaîne
|
- |
|
512 |
2) opérande par défaut
|
- |
|
513 |
3) les séparateurs présents sont substitués par l'opérande déterminée par 1) ou 2)
|
- |
|
514 |
|
- |
|
515 |
// TODO: support des parenthèses, imbrications & co: "(", ")"
|
- |
|
516 |
// http://codehackit.blogspot.fr/2011/08/expression-parser-in-php.html
|
- |
|
517 |
// http://blog.angeloff.name/post/2012/08/05/php-recursive-patterns/
|
- |
|
518 |
|
- |
|
519 |
@param $str: la chaîne à "parser"
|
- |
|
520 |
@param $default_op: "AND" ou "OR"
|
- |
|
521 |
@param $additional_sep: séparateur de mots:
|
- |
|
522 |
*/
|
- |
|
523 |
static function buildTagsAST($str = NULL, $default_op, $additional_sep = ',') {
|
- |
|
524 |
if(!$str) return;
|
- |
|
525 |
$words = preg_split('/ (OR|AND|ET|OU) /', $str, -1, PREG_SPLIT_NO_EMPTY);
|
- |
|
526 |
|
- |
|
527 |
if(preg_match('/\b(ET|AND)\b/', $str)) $op = 'AND';
|
- |
|
528 |
elseif(preg_match('/\b(OU|OR)\b/', $str)) $op = 'OR';
|
- |
|
529 |
else $op = $default_op;
|
- |
|
530 |
|
- |
|
531 |
if($additional_sep) {
|
- |
|
532 |
array_walk($words,
|
- |
|
533 |
create_function('&$v, $k, $sep', '$v = preg_split("/".$sep."/", $v, -1, PREG_SPLIT_NO_EMPTY);'),
|
- |
|
534 |
$additional_sep);
|
- |
|
535 |
}
|
- |
|
536 |
$words = self::array_flatten($words);
|
- |
|
537 |
$words = array_map('trim', $words);
|
Line 503... |
Line 538... |
503 |
}
|
538 |
return array($op => array_filter($words));
|
504 |
|
539 |
}
|
505 |
|
540 |
|
506 |
|
541 |
|
507 |
// met à jour *toutes* les stats de nombre de tags et de moyenne des votes
|
542 |
// met à jour *toutes* les stats de nombre de tags et de moyenne des votes
|
508 |
static function _update_statistics($db) {
|
543 |
static function _update_statistics($db) {
|
509 |
$db->requeter("TRUNCATE TABLE del_image_stat");
|
544 |
$db->requeter("TRUNCATE TABLE del_image_stat");
|
510 |
$db->requeter(<<<EOF
|
545 |
$db->requeter(<<<EOF
|
511 |
INSERT INTO `del_image_stat` (
|
546 |
INSERT INTO `del_image_stat` (
|
512 |
SELECT id_image, divo.ce_protocole, divo.moyenne, dit.ctags
|
547 |
SELECT id_image, divo.ce_protocole, divo.moyenne, divo.nb_votes, dit.ctags
|
513 |
FROM `BASECEL`.`cel_images` ci
|
548 |
FROM `tb_cel`.`cel_images` ci
|
514 |
LEFT JOIN
|
549 |
LEFT JOIN
|
515 |
( SELECT ce_image, ce_protocole, AVG(valeur) AS moyenne FROM del_image_vote
|
550 |
( SELECT ce_image, ce_protocole, AVG(valeur) AS moyenne, COUNT(valeur) AS nb_votes FROM del_image_vote
|
516 |
GROUP BY ce_image, ce_protocole ) AS divo
|
551 |
GROUP BY ce_image, ce_protocole ) AS divo
|
517 |
ON ci.id_image = divo.ce_image
|
552 |
ON ci.id_image = divo.ce_image
|
518 |
LEFT JOIN
|
553 |
LEFT JOIN
|
519 |
( SELECT ce_image, COUNT(id_tag) as ctags FROM del_image_tag
|
554 |
( SELECT ce_image, COUNT(id_tag) as ctags FROM del_image_tag
|
520 |
GROUP BY ce_image ) AS dit
|
555 |
GROUP BY ce_image ) AS dit
|
- |
|
556 |
ON ci.id_image = dit.ce_image )
|
- |
|
557 |
EOF
|
- |
|
558 |
);
|
- |
|
559 |
}
|
- |
|
560 |
|
- |
|
561 |
static function revOrderBy($orderby) {
|
- |
|
562 |
return $orderby == 'asc' ? 'desc' : 'asc';
|
- |
|
563 |
}
|
- |
|
564 |
|
- |
|
565 |
static function array_flatten($arr) {
|
- |
|
566 |
$arr = array_values($arr);
|
- |
|
567 |
while (list($k,$v)=each($arr)) {
|
- |
|
568 |
if (is_array($v)) {
|
- |
|
569 |
array_splice($arr,$k,1,$v);
|
- |
|
570 |
next($arr);
|
521 |
ON ci.id_image = dit.ce_image )
|
571 |
}
|
522 |
EOF
|
572 |
}
|