Subversion Repositories eFlore/Applications.del

Rev

Rev 1438 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1438 Rev 1451
Line 45... Line 45...
45
 * - subqueries dans le FROM pour les critère WHERE portant directement sur v_del_image
45
 * - subqueries dans le FROM pour les critère WHERE portant directement sur v_del_image
46
 * plutôt que dans WHERE (qui nécessite dès lors un FULL-JOIN)
46
 * plutôt que dans WHERE (qui nécessite dès lors un FULL-JOIN)
47
 * (http://www.mysqlperformanceblog.com/2007/04/06/using-delayed-join-to-optimize-count-and-limit-queries/)
47
 * (http://www.mysqlperformanceblog.com/2007/04/06/using-delayed-join-to-optimize-count-and-limit-queries/)
48
 * - éviter de dépendre d'une jointure systématique sur `cel_obs`, uniquement pour `(date_)transmission
48
 * - éviter de dépendre d'une jointure systématique sur `cel_obs`, uniquement pour `(date_)transmission
49
 * (cf VIEW del_image)
49
 * (cf VIEW del_image)
50
 * - réorganiser les méthodes statiques parmis Observation, ListeObservations2 et ListImages2
50
 * - réorganiser les méthodes statiques parmis Observation, ListeObservations et ListImages2
51
 * - *peut-être*: passer requestFilterParams() en méthode de classe
51
 * - *peut-être*: passer requestFilterParams() en méthode de classe
52
 *
52
 *
53
 *
53
 *
54
 * MySQL sux:
54
 * MySQL sux:
55
 * EXPLAIN SELECT  id_image FROM v_del_image vdi WHERE vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1 LIMIT 1);
55
 * EXPLAIN SELECT  id_image FROM v_del_image vdi WHERE vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1 LIMIT 1);
Line 63... Line 63...
63
 *  5.1: DEPENDENT SUBQUERY	del_image_tag	index_subquery	ce_image ce_image 8 func 1 Using where
63
 *  5.1: DEPENDENT SUBQUERY	del_image_tag	index_subquery	ce_image ce_image 8 func 1 Using where
64
 * FORCE INDEX/IGNORE INDEX semble incapable de résoudre le problème de l'optimiseur MySQL
64
 * FORCE INDEX/IGNORE INDEX semble incapable de résoudre le problème de l'optimiseur MySQL
65
 *
65
 *
66
 */
66
 */
Line 67... Line 67...
67
 
67
 
68
require_once(dirname(__FILE__) . '/../observations/ListeObservations2.php');
68
require_once(dirname(__FILE__) . '/../observations/ListeObservations.php');
69
require_once(dirname(__FILE__) . '/../observations/Observation.php');
69
require_once(dirname(__FILE__) . '/../observations/Observation.php');
70
restore_error_handler();
70
restore_error_handler();
71
restore_exception_handler();
71
restore_exception_handler();
Line 81... Line 81...
81
	// TODO: PHP-x.y, ces variables devrait être des "const"
81
	// TODO: PHP-x.y, ces variables devrait être des "const"
82
	static $format_image_possible = array('O','CRX2S','CRS','CXS','CS','XS','S','M','L','XL','X2L','X3L');
82
	static $format_image_possible = array('O','CRX2S','CRS','CXS','CS','XS','S','M','L','XL','X2L','X3L');
Line 83... Line 83...
83
 
83
 
Line 84... Line 84...
84
	static $tri_possible = array('date_transmission', 'date_observation', 'votes', 'tags');
84
	static $tri_possible = array('date_transmission', 'date_observation', 'votes', 'tags');
85
 
85
 
Line 86... Line 86...
86
	// en plus de ceux dans ListeObservations2
86
	// en plus de ceux dans ListeObservations
87
	static $parametres_autorises = array('protocole', 'masque.tag_cel', 'masque.tag_pictoflora', 'masque.milieu');
87
	static $parametres_autorises = array('protocole', 'masque.tag_cel', 'masque.tag_pictoflora', 'masque.milieu');
88
 
88
 
Line 149... Line 149...
149
 
149
 
150
		// filtrage de l'INPUT général, on réutilise 90% de identiplante en terme de paramètres autorisés
150
		// filtrage de l'INPUT général, on réutilise 90% de identiplante en terme de paramètres autorisés
151
		// ($parametres_autorises) sauf... masque.type qui fait des modif' de WHERE sur les mots-clefs.
151
		// ($parametres_autorises) sauf... masque.type qui fait des modif' de WHERE sur les mots-clefs.
152
		// Évitons ce genre de chose pour PictoFlora et les risques de conflits avec masque.tag
152
		// Évitons ce genre de chose pour PictoFlora et les risques de conflits avec masque.tag
153
		// même si ceux-ci sont improbables (pas d'<input> pour cela).
153
		// même si ceux-ci sont improbables (pas d'<input> pour cela).
154
		$params_ip = ListeObservations2::requestFilterParams($parametres,
154
		$params_ip = ListeObservations::requestFilterParams($parametres,
155
														  array_diff(ListeObservations2::$parametres_autorises,
155
														  array_diff(ListeObservations::$parametres_autorises,
156
																	 array('masque.type')),
156
																	 array('masque.type')),
Line 157... Line 157...
157
														  $this->conteneur);
157
														  $this->conteneur);
158
 
158
 
159
		// notre propre filtrage sur l'INPUT
159
		// notre propre filtrage sur l'INPUT
160
		$params_pf = self::requestFilterParams($parametres,
160
		$params_pf = self::requestFilterParams($parametres,
Line 161... Line 161...
161
											   array_merge(ListeObservations2::$parametres_autorises,
161
											   array_merge(ListeObservations::$parametres_autorises,
162
														   self::$parametres_autorises));
162
														   self::$parametres_autorises));
163
 
163
 
164
		/* filtrage des tags + sémantique des valeurs multiples:
164
		/* filtrage des tags + sémantique des valeurs multiples:
165
		   Lorsqu'on utilise masque.tag* pour chercher des tags, ils sont
165
		   Lorsqu'on utilise masque.tag* pour chercher des tags, ils sont
Line 166... Line 166...
166
		   postulés comme séparés par des virgule, et l'un au moins des tags doit matcher. */
166
		   postulés comme séparés par des virgule, et l'un au moins des tags doit matcher. */
167
		$params_pf['masque.tag_cel'] = self::buildTagsAST(@$parametres['masque.tag_cel'], 'OR', ',');
167
		$params_pf['masque.tag_cel'] = self::buildTagsAST(@$parametres['masque.tag_cel'], 'OR', ',');
168
		$params_pf['masque.tag_pictoflora'] = self::buildTagsAST(@$parametres['masque.tag_pictoflora'], 'OR', ',');
168
		$params_pf['masque.tag_pictoflora'] = self::buildTagsAST(@$parametres['masque.tag_pictoflora'], 'OR', ',');
169
 
169
 
Line 170... Line 170...
170
		$params = array_merge(ListeObservations2::$default_params, // paramètre par défaut Identiplante
170
		$params = array_merge(ListeObservations::$default_params, // paramètre par défaut Identiplante
171
							  self::$default_params, // paramètres par défaut PictoFlora
171
							  self::$default_params, // paramètres par défaut PictoFlora
172
							  $params_ip, // les paramètres passés, traités par Identiplante
172
							  $params_ip, // les paramètres passés, traités par Identiplante
Line 173... Line 173...
173
							  $params_pf); // les paramètres passés, traités par PictoFlora
173
							  $params_pf); // les paramètres passés, traités par PictoFlora
174
 
174
 
175
		// XXX: temp tweak
175
		// XXX: temp tweak
176
		/* $this->conteneur->setParametre('url_images', sprintf($this->conteneur->getParametre('url_images'),
176
		/* $this->conteneur->setParametre('url_images', sprintf($this->conteneur->getParametre('url_images'),
177
		   "%09d", $params['format']));*/
177
		   "%09d", $params['format']));*/
178
 
178
 
179
		// création des contraintes (génériques, de ListeObservations2)
179
		// création des contraintes (génériques, de ListeObservations)
180
		ListeObservations2::sqlAddConstraint($params, $db, $req, $this->conteneur);
180
		ListeObservations::sqlAddConstraint($params, $db, $req, $this->conteneur);
Line 181... Line 181...
181
		// création des contraintes spécifiques (sur les tags essentiellement)
181
		// création des contraintes spécifiques (sur les tags essentiellement)
182
		self::sqlAddConstraint($params, $db, $req, $this->conteneur);
182
		self::sqlAddConstraint($params, $db, $req, $this->conteneur);
183
		// création des contraintes spécifiques impliquées par le masque général
183
		// création des contraintes spécifiques impliquées par le masque général
Line 184... Line 184...
184
		self::sqlAddMasqueConstraint($params, $db, $req, $this->conteneur);
184
		self::sqlAddMasqueConstraint($params, $db, $req, $this->conteneur);
185
		// l'ORDER BY s'avére complexe
185
		// l'ORDER BY s'avére complexe
186
		self::sqlOrderBy($params, $db, $req);
186
		self::sqlOrderBy($params, $db, $req);
187
 
187
 
188
		// 1) grunt-work: *la* requête de récupération des id valides (+ SQL_CALC_FOUND_ROWS)
188
		// 1) grunt-work: *la* requête de récupération des id valides (+ SQL_CALC_FOUND_ROWS)
189
		// $idobs_tab = ListeObservations2::getIdObs($params, $req, $db);
189
		// $idobs_tab = ListeObservations::getIdObs($params, $req, $db);
190
		$idobs_tab = self::getIdImages($params, $req, $db);
190
		$idobs_tab = self::getIdImages($params, $req, $db);
191
 
191
 
192
		// Ce n'est pas la peine de continuer s'il n'y a pas eu de résultats dans la table del_obs_images
192
		// Ce n'est pas la peine de continuer s'il n'y a pas eu de résultats dans la table del_obs_images
Line 214... Line 214...
214
		   $o = new Observation($this->conteneur);
214
		   $o = new Observation($this->conteneur);
215
		   foreach($idobs as $i) {
215
		   foreach($idobs as $i) {
216
		   $images[$i] = $o->consulter(array($i), array('justthrow' => 1));
216
		   $images[$i] = $o->consulter(array($i), array('justthrow' => 1));
217
		   }
217
		   }
218
		*/
218
		*/
219
		list($images, $images_keyed_by_id_image) = ListeObservations2::reformateImagesDoubleIndex(
219
		list($images, $images_keyed_by_id_image) = ListeObservations::reformateImagesDoubleIndex(
220
			$liaisons,
220
			$liaisons,
221
			$this->conteneur->getParametre('url_images'),
221
			$this->conteneur->getParametre('url_images'),
222
			$params['format']);
222
			$params['format']);
Line 235... Line 235...
235
		// les deux masques de tags sont transformés en AST dans le processus de construction de la requête.
235
		// les deux masques de tags sont transformés en AST dans le processus de construction de la requête.
236
		// Reprenous les paramètres originaux non-nettoyés (ils sont valables car le nettoyage est déterministe)
236
		// Reprenous les paramètres originaux non-nettoyés (ils sont valables car le nettoyage est déterministe)
237
		$params_header = array_merge($params, array_filter(array('masque.tag_cel' => @$parametres['masque.tag_cel'],
237
		$params_header = array_merge($params, array_filter(array('masque.tag_cel' => @$parametres['masque.tag_cel'],
238
																 'masque.tag_pictoflora' => @$parametres['masque.tag_pictoflora'])));
238
																 'masque.tag_pictoflora' => @$parametres['masque.tag_pictoflora'])));
239
		$resultat = new ResultatService();
239
		$resultat = new ResultatService();
240
		$resultat->corps = array('entete' => ListeObservations2::makeJSONHeader($total, $params_header, Config::get('url_service')),
240
		$resultat->corps = array('entete' => ListeObservations::makeJSONHeader($total, $params_header, Config::get('url_service')),
241
								 'resultats' => $images);
241
								 'resultats' => $images);
242
		return $resultat;
242
		return $resultat;
243
	}
243
	}
Line 244... Line 244...
244
 
244
 
Line 290... Line 290...
290
	 * équivalent à:
290
	 * équivalent à:
291
	 * (split sur " ", "OR" entre chaque condition, "AND" pour chaque valeur de tag)
291
	 * (split sur " ", "OR" entre chaque condition, "AND" pour chaque valeur de tag)
292
	 *
292
	 *
293
	 */
293
	 */
294
	static function sqlAddConstraint($p, $db, &$req, Conteneur $c = NULL) {
294
	static function sqlAddConstraint($p, $db, &$req, Conteneur $c = NULL) {
295
		// TODO implement dans ListeObservations2 ?
295
		// TODO implement dans ListeObservations ?
296
		if(!empty($p['masque.milieu'])) {
296
		if(!empty($p['masque.milieu'])) {
297
			$req['where'][] = 'vdi.milieu LIKE '.$db->proteger('%' . $p['masque.milieu'].'%');
297
			$req['where'][] = 'vdi.milieu LIKE '.$db->proteger('%' . $p['masque.milieu'].'%');
298
		}
298
		}
Line 425... Line 425...
425
	   de manière identique à la seule différence que:
425
	   de manière identique à la seule différence que:
426
	   1) ils sont combinés par des "OU" logiques plutôt que des "ET".
426
	   1) ils sont combinés par des "OU" logiques plutôt que des "ET".
427
	   2) les tags sont traités différemment pour conserver la compatibilité avec l'utilisation historique:
427
	   2) les tags sont traités différemment pour conserver la compatibilité avec l'utilisation historique:
428
	   	  Tous les mots-clefs doivent matcher et sont séparés par des espaces
428
	   	  Tous les mots-clefs doivent matcher et sont séparés par des espaces
429
		  (dit autrement, str_replace(" ", ".*", $mots-clefs-requête) =~ $mots-clefs-mysql)
429
		  (dit autrement, str_replace(" ", ".*", $mots-clefs-requête) =~ $mots-clefs-mysql)
430
	   Pour plus d'information: ListeObservations2::sqlAddMasqueConstraint() */
430
	   Pour plus d'information: ListeObservations::sqlAddMasqueConstraint() */
431
	static function sqlAddMasqueConstraint($p, $db, &$req, Conteneur $c = NULL) {
431
	static function sqlAddMasqueConstraint($p, $db, &$req, Conteneur $c = NULL) {
432
		if(!empty($p['masque'])) {
432
		if(!empty($p['masque'])) {
433
			$or_params = array('masque.auteur' => $p['masque'],
433
			$or_params = array('masque.auteur' => $p['masque'],
434
							   'masque.departement' => $p['masque'],
434
							   'masque.departement' => $p['masque'],
435
							   'masque.commune' => $p['masque'], // TODO/XXX ?
435
							   'masque.commune' => $p['masque'], // TODO/XXX ?
Line 449... Line 449...
449
							   // tri est aussi nécessaire car affecte les contraintes de JOIN
449
							   // tri est aussi nécessaire car affecte les contraintes de JOIN
450
							   'tri' => $p['tri'],
450
							   'tri' => $p['tri'],
451
							   'ordre' => $p['ordre']);
451
							   'ordre' => $p['ordre']);
Line 452... Line 452...
452
 
452
 
453
			$or_masque = array_merge(
453
			$or_masque = array_merge(
454
				ListeObservations2::requestFilterParams($or_params, NULL, $c /* pour masque.departement */),
454
				ListeObservations::requestFilterParams($or_params, NULL, $c /* pour masque.departement */),
Line 455... Line 455...
455
				self::requestFilterParams($or_params));
455
				self::requestFilterParams($or_params));
456
 
456
 
457
			/* Lorsqu'on utilise le masque général pour chercher des tags, ils sont
457
			/* Lorsqu'on utilise le masque général pour chercher des tags, ils sont
458
			   postulés comme séparés par des espaces, et doivent être tous matchés. */
458
			   postulés comme séparés par des espaces, et doivent être tous matchés. */
Line 459... Line 459...
459
			$or_masque['masque.tag_cel'] = self::buildTagsAST($p['masque'], 'AND', ' ');
459
			$or_masque['masque.tag_cel'] = self::buildTagsAST($p['masque'], 'AND', ' ');
460
			$or_masque['masque.tag_pictoflora'] = self::buildTagsAST($p['masque'], 'AND', ' ');
460
			$or_masque['masque.tag_pictoflora'] = self::buildTagsAST($p['masque'], 'AND', ' ');
461
 
461
 
462
 
462
 
Line 463... Line 463...
463
			// pas de select, groupby & co ici: uniquement 'join' et 'where'
463
			// pas de select, groupby & co ici: uniquement 'join' et 'where'
464
			$or_req = array('join' => array(), 'where' => array());
464
			$or_req = array('join' => array(), 'where' => array());
465
			ListeObservations2::sqlAddConstraint($or_masque, $db, $or_req);
465
			ListeObservations::sqlAddConstraint($or_masque, $db, $or_req);
466
			self::sqlAddConstraint($or_masque, $db, $or_req);
466
			self::sqlAddConstraint($or_masque, $db, $or_req);
467
 
467
 
468
			if($or_req['where']) {
468
			if($or_req['where']) {
469
				$req['where'][] = '(' . implode(' OR ', $or_req['where']) . ')';
469
				$req['where'][] = '(' . implode(' OR ', $or_req['where']) . ')';
Line 470... Line 470...
470
				// utile au cas ou des jointures seraient rajoutées
470
				// utile au cas ou des jointures seraient rajoutées
471
				$req['join'] = array_unique(array_merge($req['join'], $or_req['join']));
471
				$req['join'] = array_unique(array_merge($req['join'], $or_req['join']));
472
			}
472
			}
473
		}
473
		}
474
	}
474
	}
Line 475... Line 475...
475
 
475
 
476
	// complete & override ListeObservations2::requestFilterParams() (même usage)
476
	// complete & override ListeObservations::requestFilterParams() (même usage)
477
	static function requestFilterParams(Array $params, $parametres_autorises = NULL) {
477
	static function requestFilterParams(Array $params, $parametres_autorises = NULL) {
Line 478... Line 478...
478
		if($parametres_autorises) { // filtrage de toute clef inconnue
478
		if($parametres_autorises) { // filtrage de toute clef inconnue
479
			$params = array_intersect_key($params, array_flip($parametres_autorises));
479
			$params = array_intersect_key($params, array_flip($parametres_autorises));
Line 480... Line 480...
480
		}
480
		}