Subversion Repositories eFlore/Projets.eflore-projets

Compare Revisions

Ignore whitespace Rev 860 → Rev 861

/trunk/services/modules/0.1/coste/Textes.php
25,7 → 25,9
 
// simplifie et accélère la sanitization de l'input:
// SELECT MAX(num_nom) FROM coste_v2_00;
define('_COSTE_TEXTE_MAX_NUM_NOM', 7015 + 1000);
define('_COSTE_TEXTE_MAX_COSTE_NN', 7015 + 1000);
// SELECT MAX(num_nom) FROM bdtfx_v1_02;
define('_COSTE_TEXTE_MAX_BDTFX_NN', 103386 + 10000);
 
/*restore_error_handler();
error_reporting(E_ALL);*/
45,6 → 47,9
// les champs de base de coste_v2_00
// mysql -N tb_eflore<<<"SHOW FIELDS FROM coste_v2_00"|egrep -v 'page_'|awk '{print $1}'|xargs -i -n1 printf "'%s' => 'c.%s',\n" {} {}
static $allow_champs = array(
'coste:nn' => 'c.num_nom',
'bdtfx:nn' => 'IF(c.flore_bdtfx_nn = "",NULL,c.flore_bdtfx_nn)',
'bdtfx:nt' => 'c.flore_bdtfx_nt',
'num_nom' => 'c.num_nom',
'num_nom_retenu' => 'c.num_nom_retenu',
'num_tax_sup' => 'c.num_tax_sup',
93,7 → 98,13
);
 
// les champs suivants disparaissent de la liste utilisée pour former la requête SQL
static $special_champs = array('nom_sci_html', 'nom_sci', '*');
// (ils sont exclue lorsque '*' est utilisée, ce sont généralement des synonymes)
static $special_champs = array('nom_sci_html', 'nom_sci', '*', 'flore_bdtfx_nn', 'flore_bdtfx_nt', 'num_nom');
 
// ces champs sont toujours dans les résultats (cf sqlSelectFields()
static $champs_obligatoires = array('coste:nn', 'bdtfx:nn');
 
 
// le pattern utilisé pour la recherche dite "floue"
static $soundex_scheme = '(%1$s LIKE %2$s OR SOUNDEX(%1$s) = SOUNDEX(%2$s) OR SOUNDEX(REVERSE(%1$s)) = SOUNDEX(REVERSE(%2$s)))';
 
145,10 → 156,10
$matches = intval($matches['total']);
}
 
// reformate les résultats pour les indexer par num_nom
// reformate les résultats pour les indexer par coste:nn
$res2 = array();
foreach($res as $v) {
$res2[$v['num_nom']] = $v;
$res2[$v['coste:nn']] = $v;
}
 
// l'appelant s'occupera du json_encode()
163,8 → 174,8
}
 
 
// la fonction central: récupère les infos à partir de paramètres
// et une optionnel contrainte de num_nom
// la fonction centrale: récupère les infos à partir de paramètres
// et une optionnelle contrainte sur coste:nn ou bdtfx:nn
static function getCosteInfo(array $params, $db) {
// contraintes (WHERE):
$constraints = self::sqlAddConstraint($params, $db);
176,9 → 187,8
 
// joins:
$other_join = self::sqlAddJoins($params, $champs_valides_non_formattes);
 
$req = sprintf(<<<EOF
SELECT SQL_CALC_FOUND_ROWS c.num_nom, %s
SELECT SQL_CALC_FOUND_ROWS %s
FROM tb_eflore.coste_v2_00 c
LEFT JOIN tela_prod_wikini.florecoste_pages dsc ON c.page_wiki_dsc = dsc.tag AND dsc.latest = 'Y'
LEFT JOIN tela_prod_wikini.florecoste_pages cle ON c.page_wiki_cle = cle.tag AND cle.latest = 'Y'
255,11 → 265,18
$stack[] = 'c.tome = ' . intval($params['masque.tome']);
}
 
// ajout de la contrainte sur num_nom si un composant d'URL supplémentaire
// ajout de la contrainte sur coste:nn ou bdtfx:nn si un composant d'URL supplémentaire
// comportant un #id existe, cf self::requestFilterIds()
$o_stack = array();
if(array_key_exists('_ids', $params) && $params['_ids']) {
$stack[] = sprintf("c.num_nom IN (%s)", implode(',', $params['_ids']));
if($params['_ids']['coste']) {
$o_stack[] = sprintf("c.num_nom IN (%s)", implode(',', $params['_ids']['coste']));
}
if($params['_ids']['bdtfx']) {
$o_stack[] = sprintf("c.flore_bdtfx_nn IN (%s)", implode(',', $params['_ids']['bdtfx']));
}
}
if($o_stack) $stack[] = '(' . implode(' OR ', $o_stack) . ')';
 
return $stack;
}
271,7 → 288,7
static function sqlSelectFields($params, &$unmerged) {
$champs = $params['retour.champs'];
// champs coste_v2_00
$c = array_intersect_key(self::$allow_champs, array_flip(explode(',', $champs)));
$c = self::addSQLToFieldSynonym(explode(',', $champs));
if(isset($c['*'])) {
$t = array_diff_key(self::$allow_champs, array_flip(self::$special_champs));
}
291,12 → 308,18
if(array_key_exists('titre', $t))
$t['titre'] = $params['txt.format'] == 'txt' ? 'c.nom_sci' : 'c.nom_sci_html';
 
// champs obligatoires:
$t = array_merge($t, self::addSQLToFieldSynonym(self::$champs_obligatoires));
$unmerged = $t;
 
// XXX: PHP-5.3
$ret = array();
foreach($t as $k => $v) {
$ret[] = "$v AS $k";
if(strpos($k, ':') !== FALSE) {
$ret[] = "$v AS \"$k\"";
} else {
$ret[] = "$v AS $k";
}
}
return implode(',',$ret);
}
307,12 → 330,20
// ou contraintes générées par sqlAddConstraint()
if(array_key_exists('masque.famille', $params) ||
array_key_exists('famille', $champs)) {
$j .= 'LEFT JOIN tb_eflore.bdtfx_v1_02 b ON c.num_nom = b.num_nom';
$j .= 'LEFT JOIN tb_eflore.bdtfx_v1_02 b ON c.flore_bdtfx_nn = b.num_nom';
}
 
return $j;
}
 
// d'un tableau de type array("coste:nn", "type_epithete")
// retourne
// un tableau de type array("coste:nn" => "c.num_nom", "type_epithete" => "c.type_epithete")
// basé sur self::$allow_champs
static function addSQLToFieldSynonym(Array $syno) {
return array_intersect_key(self::$allow_champs, array_flip($syno));
}
 
// request handler
static function requestParse(&$ressource, &$params) {
$uri = explode('/', $_SERVER['REDIRECT_URL']);
355,7 → 386,7
FILTER_VALIDATE_INT,
array('options' => array('default' => NULL,
'min_range' => 0,
'max_range' => _COSTE_TEXTE_MAX_NUM_NOM)));
'max_range' => _COSTE_TEXTE_MAX_COSTE_NN)));
 
// on filtre les NULL, FALSE et '', mais pas les 0, d'où le callback()
// TODO: PHP-5.3
368,17 → 399,23
static function requestFilterIds($uri) {
if(count($uri) != 1) return NULL;
 
// getNN renvoie le num_nom passé comme segment d'URI
// getNN* renvoient le num_nom passé comme segment d'URI:
// - soit un id selon coste (num_nom dans coste_v2_00)
// - soit un id selon bdtfx (num_nom dans bdtfx_v1_02)
// ou bien l'extrait du pattern bdtfx.nn:(#id)
$ids = array_filter(array_map(array(__CLASS__, 'getNN'), explode(',', $uri[0])));
$ids_coste = array_filter(array_map(array(__CLASS__, 'getNNCoste'), explode(',', $uri[0])));
$ids_bdtfx = array_filter(array_map(array(__CLASS__, 'getNNBdtfx'), explode(',', $uri[0])));
 
// en cas d'échec (tous les id sont invalides), bail-out
if(!$ids) {
if(!$ids_bdtfx && !$ids_coste) {
// http_response_code(500);
throw new Exception('not supported', 500);
}
 
return array_slice($ids, 0, _COSTE_TEXTE_MAX_RESULT_LIMIT);
return array(
'coste' => array_slice($ids_coste, 0, intval(_COSTE_TEXTE_MAX_RESULT_LIMIT/2) ),
'bdtfx' => array_slice($ids_bdtfx, 0, intval(_COSTE_TEXTE_MAX_RESULT_LIMIT/2) )
);
}
 
static function aide() {
387,11 → 424,12
Service coste/textes:
Retourne des informations (choisies) à propos d'un taxon donné (à partir de son numéro nomenclatural
Retourne des informations (choisies) à propos de taxons recherchés (à partir de divers critères)
 
Les résultats sont indexés. La clef par défaut est le num_nom d'après coste (attribut \"coste:nn\")
Usage:
coste/textes/<liste-num_nom>?<params>
* <liste-num_nom> étant une liste de numéros nomenclaturaux de taxons bdtfx séparés par des virgules
au format <#id> ou <bdtfx.nn:#id>
* <liste-num_nom> étant une liste de numéros nomenclaturaux de taxons séparés par des virgules au format:
- <#id>: un numéro nomenclatural dans la base coste
- <bdtfx.nn:#id>: un numéro nomenclatural dans la base bdtfx
* retour.champs une liste de champs séparés par des virgules parmi *,%s
* les paramètres acceptés sont les suivants: %s
* les champs retournés par défaut sont les suivants: %s
404,13 → 442,18
);
}
 
static function getNN($refnn) {
static function getNNCoste($refnn) {
if(is_numeric($refnn)) {
$t = intval($refnn);
if($t >= 1 && $t < _COSTE_TEXTE_MAX_NUM_NOM) return $t;
return FALSE;
if($t >= 1 && $t < _COSTE_TEXTE_MAX_COSTE_NN) return $t;
}
return FALSE;
}
 
static function getNNBdtfx($refnn) {
if(strpos($refnn, 'bdtfx.nn:') !== 0) return FALSE;
return intval(str_replace('bdtfx.nn:', '', $refnn));
$t = intval(str_replace('bdtfx.nn:', '', $refnn));
if($t >= 1 && $t < _COSTE_TEXTE_MAX_BDTFX_NN) return $t;
return FALSE;
}
}