Rev 3198 | Rev 3662 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php
// declare(encoding='UTF-8');
/**
* Service affichant les dernières photo publiques du CEL ouvrable sous forme de diaporama.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* Cas d'utilisation et documentation :
* @link http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=AideCELWidgetPhoto
*
* Paramètres :
* ===> extra = booléen (1 ou 0) [par défaut : 1]
* Affiche / Cache la vignette en taille plus importante au bas du widget.
* ===> vignette = [0-9]+,[0-9]+ [par défaut : 4,3]
* Indique le nombre de vignette par ligne et le nombre de ligne.
*
* @author Jean-Pascal MILCENT <jpm@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>
* @version $Id$
* @copyright Copyright (c) 2010, Tela Botanica (accueil@tela-botanica.org)
*/
class Saisie extends WidgetCommun {
const DS = DIRECTORY_SEPARATOR;
const SERVICE_DEFAUT = 'saisie';
const WS_SAISIE = 'CelWidgetSaisie';
const WS_UPLOAD = 'CelWidgetUploadImageTemp';
const WS_OBS = 'CelObs';
const WS_COORD = 'CoordSearch';
const LANGUE_DEFAUT = 'fr';
const PROJET_DEFAUT = 'base';
const WS_NOM = 'noms';
const EFLORE_API_VERSION = '0.1';
const WIDGETS_SPECIAUX = ['tb_aupresdemonarbre','tb_streets','tb_lichensgo'];
const SQUELETTES_SPECIAUX = ['arbres','plantes','lichens'];
const WS_OBS_LIST = 'InventoryObservationList';
const WS_IMG_LIST = 'celImage';
private $cel_url_tpl = null;
/** Si spécifié, on ajoute une barre de navigation inter-applications */
private $bar;
//private $parametres_autorises = array('projet', 'type', 'langue', 'order');
private $parametres_autorises = array(
'projet' => 'projet',
'type' => 'type',
'langue' => 'langue',
'order' => 'order'
);
/**
* Méthode appelée par défaut pour charger ce widget.
*/
public function executer() {
$retour = null;
// Pour la création de l'id du cache nous ne tenons pas compte du paramètre de l'url callback
unset($this->parametres['callback']);
extract($this->parametres);
$this->bar = (isset($bar)) ? $bar : false;
/* Le fichier Framework.php du Framework de Tela Botanica doit être appelé avant tout autre chose dans l'application.
Sinon, rien ne sera chargé.
L'emplacement du Framework peut varier en fonction de l'environnement (test, prod...). Afin de faciliter la configuration
de l'emplacement du Framework, un fichier framework.defaut.php doit être renommé en framework.php et configuré pour chaque installation de
l'application.
Chemin du fichier chargeant le framework requis */
$framework = dirname(__FILE__).'/framework.php';
if (!file_exists($framework)) {
$e = "Veuillez paramêtrer l'emplacement et la version du Framework dans le fichier $framework";
trigger_error($e, E_USER_ERROR);
} else {
// Inclusion du Framework
require_once $framework;
// Ajout d'information concernant cette application
Framework::setCheminAppli(__FILE__);// Obligatoire
Framework::setInfoAppli(Config::get('info'));// Optionnel
}
$langue = (isset($langue)) ? $langue : self::LANGUE_DEFAUT;
$this->langue = I18n::setLangue($langue);
$this->parametres['langue'] = $langue;
if (!isset($mode)) {
$mode = self::SERVICE_DEFAUT;
}
if (!isset($projet)) {
$this->parametres['projet'] = self::PROJET_DEFAUT;
}
$methode = $this->traiterNomMethodeExecuter($mode);
if (method_exists($this, $methode)) {
$retour = $this->$methode();
} else {
$this->messages[] = "Ce type de service '$methode' n'est pas disponible.";
}
$contenu = ''; //print_r($retour);exit;
if (is_null($retour)) {
$this->messages[] = 'La ressource demandée a retourné une valeur nulle.';
} else {
if (isset($retour['donnees'])) {
// ne pas afficher le projet dans l'url si on est dans saisie de base
$projet_dans_url = ( $this->parametres['projet'] !== 'base') ? '?'. $this->parametres['projet'].'&'.'langue='.$this->parametres['langue'] : '';
$retour['donnees']['conf_mode'] = $this->config['parametres']['modeServeur'];
$retour['donnees']['prod'] = ($this->config['parametres']['modeServeur'] === 'prod');
$retour['donnees']['bar'] = $this->bar;
$retour['donnees']['url_base'] = sprintf($this->config['chemins']['baseURLAbsoluDyn'], $this->config['manager']['cheminDos']);
$retour['donnees']['url_ws_annuaire'] = sprintf($this->config['chemins']['baseURLServicesAnnuaireTpl'], 'utilisateur/identite-par-courriel/');
$retour['donnees']['url_ws_saisie'] = sprintf($this->config['chemins']['baseURLServicesCelTpl'], self::WS_SAISIE);
$retour['donnees']['url_ws_obs'] = sprintf($this->config['chemins']['baseURLServicesCelTpl'], self::WS_OBS);
$retour['donnees']['url_ws_upload'] = sprintf($this->config['chemins']['baseURLServicesCelTpl'], self::WS_UPLOAD);
$retour['donnees']['authTpl'] = $this->config['manager']['authTpl']. $projet_dans_url;
$retour['donnees']['mode'] = $mode;
$retour['donnees']['langue'] = $langue;
$retour['donnees']['widgets_url'] = sprintf($this->config['chemins']['baseURLAbsoluDyn'],'');
$retour['donnees']['url_ws_obs_list'] = sprintf($this->config['chemins']['baseURLServicesCelTpl'], self::WS_OBS_LIST);
$retour['donnees']['url_ws_cel_imgs'] = sprintf($this->config['chemins']['baseURLServicesCelTpl'], self::WS_IMG_LIST) . '/liste-ids?obsId=';
$retour['donnees']['url_ws_cel_img_url'] = str_replace ( '%s.jpg', '{id}XS', $this->config['chemins']['celImgUrlTpl'] );
$squelette = dirname(__FILE__).self::DS.'squelettes'.self::DS.$retour['squelette'].'.tpl.html';
switch ( $retour['squelette'] ) {
case 'apa':
$retour['donnees']['squelette'] = $this->parametres['projet'];
break;
case 'apaforms':
$retour['donnees']['squelette'] = $this->parametres['squelette'];
break;
default:
$retour['donnees']['squelette'] = $retour['squelette'];
break;
}
$contenu = $this->traiterSquelettePhp($squelette, $retour['donnees']);
} else {
$this->messages[] = 'Les données à transmettre au squelette sont nulles.';
}
}
$this->envoyer($contenu);
}
private function executerSaisie() {
$retour = array();
if (in_array($this->parametres['projet'], self::WIDGETS_SPECIAUX) ) {
if (isset($this->parametres['squelette']) && in_array($this->parametres['squelette'], self::SQUELETTES_SPECIAUX) ) {
$retour['squelette'] = 'apaforms';
} else {
$retour['squelette'] = 'apa';
}
} else {
$retour['squelette'] = 'saisie';
$retour['donnees']['general'] = I18n::get('General');
$retour['donnees']['aide'] = I18n::get('Aide');
$retour['donnees']['observateur'] = I18n::get('Observateur');
$retour['donnees']['observation'] = I18n::get('Observation');
$retour['donnees']['image'] = I18n::get('Image');
$retour['donnees']['chpsupp'] = I18n::get('Chpsupp');
$retour['donnees']['resume'] = I18n::get('Resume');
}
$retour['donnees']['widget'] = $this->rechercherProjet();
return $retour;
}
/* Recherche si le projet existe sinon va chercher les infos de base */
private function rechercherProjet() {
// projet avec un squelette défini (et non juste un mot-clé d'observation)
$estProjetDefini = true;
$tab = array();
$url = $this->config['manager']['celUrlTpl'].'?projet='.$this->parametres['projet'].'&langue='.$this->parametres['langue'];
$json = $this->getDao()->consulter($url);
if (!in_array($this->parametres['projet'], self::WIDGETS_SPECIAUX)){
if ( $json !== "[]") {
$tab = $this->rechercherChampsSupp();
} else {
$url = $this->config['manager']['celUrlTpl'].'?projet=base&langue='.$this->parametres['langue'];
$json = $this->getDao()->consulter($url);
$estProjetDefini = false;
}
}
$tableau = json_decode($json, true);
$tableau = $this->traiterParametres($estProjetDefini, $tableau[0]);
if (
isset($this->parametres['squelette']) &&
($this->parametres['squelette'] === 'plantes' || $this->parametres['squelette'] === 'lichens')
) {
$tableau['type_especes'] = 'liste';
if ( $this->parametres['squelette'] === 'lichens' ) {
$tableau['referentiel'] = 'taxref';
}
}
$tableau['especes'] = $this->rechercherInfosEspeces($tableau);
if (isset($tableau['type_especes']) && 'fixe' === $tableau['type_especes']) {
// si on trouve ":" dans referentiel, referentiel = première partie
$tableau['referentiel'] = (strstr($tableau['referentiel'],':',true)) ?: $tableau['referentiel'];
}
$tableau['milieux'] = ($tableau['milieux'] != '') ? explode(';', $tableau['milieux']) : [];
if(!isset($this->parametres['id-obs'])) {
if (isset($this->parametres['dept']) || isset($this->parametres['commune'],$this->parametres['dept']) || isset($this->parametres['code_insee'])) {
$localisation = $this->traiterParamsLocalisation($this->parametres);
// les paramètres dans l'url peuvent surcharger les données de localisation de la bdd
if ($localisation) $tableau['localisation'] = $localisation;
}
if (isset($tableau['localisation'])) $tableau['localisation'] = $this->traiterLocalisation($tableau['localisation']);
}
if (isset($tableau['motscles'])) {
if (isset($tableau['tag-obs'])) {
$tableau['tag-obs'] .= $tableau['motscles'];
} else if (isset($tableau['tag-img'])) {
$tableau['tag-img'] .= $tableau['motscles'];
} else {
$tableau['tag-obs'] = $tableau['tag-img'] = $tableau['motscles'];
}
}
$tableau['chpSupp'] = $tab;
$langue_projet_url = ( isset ( $this->parametres['langue'] ) && $this->parametres['langue'] !== 'fr' ) ? '_' . $this->parametres['langue'] : '';
$tableau['chemin_fichiers'] = sprintf( $this->config['chemins']['baseURLAbsoluDyn'], $this->config['manager']['imgProjet'] . $tableau['projet'] . $langue_projet_url . '/' );
return $tableau;
}
/* Recherche si un projet a des champs de saisie supplémentaire */
private function rechercherChampsSupp() {
$retour = array();
$projet = $this->parametres['projet'];
$url = $this->config['manager']['celChpSupTpl'] .'?projet=' . $projet . '&langue=' . $this->parametres['langue'];
$json = $this->getDao()->consulter($url);
$retour = json_decode($json, true);
foreach ( $retour[$projet]['champs-supp'] as $key => $chsup ) {
$retour[$projet]['champs-supp'][$key]['name'] = $this->clean_string( $chsup['name'] );
$retour[$projet]['champs-supp'][$key]['description'] = $this->clean_string( $chsup['description']);
$retour[$projet]['champs-supp'][$key]['unit'] = $this->clean_string( $chsup['unit'] );
if ( isset( $chsup['fieldValues'] ) ) {
$retour[$projet]['champs-supp'][$key]['fieldValues'] = json_decode( $this->clean_string( $chsup['fieldValues'] ), true );
if ( isset( $retour[$projet]['champs-supp'][$key]['fieldValues']['listValue'] ) ) {
foreach( $retour[$projet]['champs-supp'][$key]['fieldValues']['listValue'] as $list_key => $list_value_array ) {
// Obtenir une liste de valeurs utilisables dans les attributs for id ou name par exemple
$retour[$projet]['champs-supp'][$key]['fieldValues']['cleanListValue'][] = ($list_value_array !== 'other') ? 'val-' . preg_replace( '/[^A-Za-z0-9_\-]/', '', $this->remove_accents( strtolower($list_value_array[0] ) ) ) : '';
}
}
}
$retour[$projet]['champs-supp'][$key]['mandatory'] = intval( $chsup['mandatory'] );
}
return $retour;
}
// remplace certains parametres définis en bd par les parametres définis dans l'url
private function traiterParametres($estProjetDefini, $tableau) {
$criteres = array('tag-obs', 'tag-img', 'projet', 'titre', 'logo');
$criteresProjetNonDefini = array('commune', 'num_nom', 'referentiel');
foreach($this->parametres as $nom_critere => $valeur_critere) {
if (($estProjetDefini == false || $tableau['projet'] == 'base') && in_array($nom_critere, $criteresProjetNonDefini)) {
$tableau[$nom_critere] = $valeur_critere;
} else if (in_array($nom_critere, $criteres)) {
$tableau[$nom_critere] = $valeur_critere;
}
}
return $tableau;
}
private function traiterLocalisation( $infos_localisation ) {
$infos = explode(';', $infos_localisation);
$tableauTmp = array();
$retour = array();
foreach ($infos as $info) {
$tableauTmp = explode(':', $info);
$retour[$tableauTmp[0]] = $tableauTmp[1];
}
return $retour;
}
private function traiterParamsLocalisation( $params ) {
$infos = array();
$tableauTmp = array();
$zoom = '12';
if (isset($params['commune'])) {
$url = sprintf($this->config['chemins']['baseURLServicesCelTpl'], self::WS_COORD). '?zone='.$params['commune'].'&code='.$params['dept'];
} else if (isset($params['dept'])) {
// pas trouvé de manière simple de déterminer le centroïde du département
// du coup on retrouve le code insee du chef lieu
$params['code_insee'] = $this->recupererChefLieuDept($params['dept']);
$zoom = '9';
}
// quoi qu'il arrive, s'il est défini, on donne la priorité au code insee (plus précis)
if (isset($params['code_insee'])) {
$url = sprintf($this->config['chemins']['baseURLServicesCelTpl'], self::WS_COORD). '?code='.$params['code_insee'];
}
if(!empty($url)) $json = $this->getDao()->consulter($url);
if(!empty($json)) $infos = json_decode($json, true);
if(!empty($infos)) {
$infos['lat'] = str_replace(',','.',strval(round($infos['lat'],5)));
$infos['lng'] = str_replace(',','.',strval(round($infos['lng'],5)));
return 'latitude:'.$infos['lat'].';longitude:'.$infos['lng'].';zoom:'.$zoom;
} else {
return false;
}
}
private function rechercherInfosEspeces( $infos_projets ) {
$retour = array();
$referentiel = $infos_projets['referentiel'];
$urlWsNsTpl = $this->config['chemins']['baseURLServicesEfloreTpl'];
$retour['url_ws_autocompletion_ns'] = sprintf( $urlWsNsTpl, self::EFLORE_API_VERSION, $referentiel, self::WS_NOM );;
$retour['url_ws_autocompletion_ns_tpl'] = sprintf( $urlWsNsTpl, self::EFLORE_API_VERSION, '{referentiel}', self::WS_NOM );
$retour['ns_referentiel'] = $referentiel;
if ( isset( $infos_projets['type_especes'] ) ) {
switch ( $infos_projets['type_especes'] ) {
case 'fixe' :
$info_taxon = explode(':', $referentiel);
if (!empty($info_taxon) && count((array) $info_taxon) === 2) {
$retour = $this->chargerInfosTaxon( $info_taxon[0], $info_taxon[1] );
}
break;
case 'referentiel' : break;
case 'liste' :
$retour['taxons'] = $this->recupererListeNomsSci();
break;
}
} else if ( isset( $referentiel ) ) {
if ( isset($infos_projets['num_nom'] ) ) {
$retour = $this->chargerInfosTaxon( $referentiel, $infos_projets['num_nom'] );
}
}
return $retour;
}
/**
* Consulte un webservice pour obtenir des informations sur le taxon dont le
* numéro nomenclatural est $num_nom (ce sont donc plutôt des infos sur le nom
* et non le taxon?)
* @param string|int $num_nom
* @return array
*/
protected function chargerInfosTaxon( $referentiel, $num_nom ) {
$url_service_infos = sprintf( $this->config['chemins']['infosTaxonUrl'], $referentiel, $num_nom );
$infos = json_decode( file_get_contents( $url_service_infos ) );
// trop de champs injectés dans les infos espèces peuvent
// faire planter javascript
$champs_a_garder = array( 'id', 'nom_sci','nom_sci_complet', 'nom_complet', 'famille','nom_retenu.id', 'nom_retenu_complet', 'num_taxonomique' );
$resultat = array();
$retour = array();
if ( isset( $infos ) && !empty( $infos ) ) {
$infos = (array) $infos;
if ( isset( $infos['nom_sci'] ) && $infos['nom_sci'] !== '' ) {
$resultat = array_intersect_key( $infos, array_flip($champs_a_garder ) );
$resultat['retenu'] = ( $infos['id'] == $infos['nom_retenu.id'] ) ? 'true' : 'false';
$retour['espece_imposee'] = true;
$retour['nn_espece_defaut'] = $nnEspeceImposee;
$retour['nom_sci_espece_defaut'] = $resultat['nom_complet'];
$retour['infos_espece'] = $this->array2js( $resultat, true );
}
}
return $retour;
}
protected function getReferentielImpose() {
$referentiel_impose = true;
if (!empty($_GET['referentiel']) && $_GET['referentiel'] !== 'autre') {
$this->ns_referentiel = $_GET['referentiel'];
} else if (isset($this->configProjet['referentiel'])) {
$this->ns_referentiel = $this->configProjet['referentiel'];
} else if (isset($this->configMission['referentiel'])) {
$this->ns_referentiel = $this->configMission['referentiel'];
} else {
$referentiel_impose = false;
}
return $referentiel_impose;
}
/**
* Trie par nom français les taxons lus dans le fichier csv/tsv
*/
protected function recupererListeNomsSci() {
$taxons = $this->recupererListeTaxon();
if (is_array($taxons)) {
$taxons = self::trierTableauMd($taxons, array('nom_fr' => SORT_ASC));
}
return $taxons;
}
/**
* @TODO documenter
* @return array
*/
protected function recupererListeNoms() {
$taxons = $this->recupererListeTaxon();
$nomsAAfficher = array();
$nomsSpeciaux = array();
if (is_array($taxons)) {
foreach ($taxons as $taxon) {
$nomSciTitle = $taxon['nom_ret'].
($taxon['nom_fr'] != '' ? ' - '.$taxon['nom_fr'] : '' ).
($taxon['nom_fr_autre'] != '' ? ' - '.$taxon['nom_fr_autre'] : '' );
$nomFrTitle = $taxon['nom_sel'].
($taxon['nom_ret'] != $taxon['nom_sel']? ' - '.$taxon['nom_ret'] : '' ).
($taxon['nom_fr_autre'] != '' ? ' - '.$taxon['nom_fr_autre'] : '' );
if ($taxon['groupe'] == 'special') {
$nomsSpeciaux[] = array(
'num_nom' => $taxon['num_nom_sel'],
'nom_a_afficher' => $taxon['nom_fr'],
'nom_a_sauver' => $taxon['nom_sel'],
'nom_title' => $nomSciTitle,
'nom_type' => 'nom-special');
} else {
$nomsAAfficher[] = array(
'num_nom' => $taxon['num_nom_sel'],
'nom_a_afficher' => $taxon['nom_sel'],
'nom_a_sauver' => $taxon['nom_sel'],
'nom_title' => $nomSciTitle,
'nom_type' => 'nom-sci');
$nomsAAfficher[] = array(
'num_nom' => $taxon['num_nom_sel'],
'nom_a_afficher' => $taxon['nom_fr'],
'nom_a_sauver' => $taxon['nom_fr'],
'nom_title' => $nomFrTitle,
'nom_type' => 'nom-fr');
}
}
$nomsAAfficher = self::trierTableauMd($nomsAAfficher, array('nom_a_afficher' => SORT_ASC));
$nomsSpeciaux = self::trierTableauMd($nomsSpeciaux, array('nom_a_afficher' => SORT_ASC));
}
return array('speciaux' => $nomsSpeciaux, 'sci-et-fr' => $nomsAAfficher);
}
/**
* Lit une liste de taxons depuis un fichier csv ou tsv fourni
*/
protected function recupererListeTaxon() {
$taxons = array();
$langue_projet_url = ( isset ( $this->parametres['langue'] ) && $this->parametres['langue'] !== 'fr' ) ? '_' . $this->parametres['langue'] : '';
$chemin_images = dirname(__FILE__) . self::DS . '..' . self::DS . 'manager' . self::DS . 'squelettes' . self::DS . 'img' . self::DS . 'images_projets' . self::DS;
$nom_fichier = ($this->parametres['squelette'] === 'lichens') ? 'lichens_taxons' : 'especes';
$chemin_taxon = $chemin_images . $this->parametres['projet'] . $langue_projet_url . self::DS . $nom_fichier. '.';
if ( file_exists( $chemin_taxon . 'csv' ) && is_readable( $chemin_taxon . 'csv' ) ) {
$taxons = $this->decomposerFichierCsv( $chemin_taxon . 'csv' );
} else if ( file_exists( $chemin_taxon . 'tsv' ) && is_readable( $chemin_taxon . 'tsv' ) ) {
$taxons = $this->decomposerFichierCsv( $chemin_taxon . 'tsv' );
} else {
$this->debug[] = "Impossible d'ouvrir le fichier '$nom_fichier'.";
}
return $taxons;
}
/**
* Lit une liste de taxons depuis un fichier csv ou tsv fourni
*/
protected function recupererChefLieuDept($dept) {
$infosDepts = array();
$code_insee = '';
$chemin_fichier = dirname(__FILE__).self::DS.'squelettes'.self::DS.'dept.csv';
if (file_exists($chemin_fichier ) && is_readable($chemin_fichier)) {
$infosDepts = $this->decomposerFichierCsv( $chemin_fichier,"," );
if(!empty($infosDepts) && is_array($infosDepts)) {
foreach ($infosDepts as $key => $infosDept) {
if($dept == $infosDept['dep']) {
return $code_insee = $infosDept['cheflieu'];
}
}
}
} else {
$this->debug[] = "Impossible d'ouvrir le fichier '$nom_fichier'.";
}
}
/**
* Découpe un fihcier csv/tsv
*/
protected function decomposerFichierCsv($fichier, $delimiter = "\t"){
$header = null;
$data = array();
if (($handle = fopen($fichier, "r")) !== FALSE) {
while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
if (!$header) {
$header = $row;
} else {
$data[] = array_combine($header, $row);
}
}
fclose($handle);
}
return $data;
}
/**
* Convertit un tableau PHP en Javascript - @WTF pourquoi ne pas faire un json_encode ?
* @param array $array
* @param boolean $show_keys
* @return une portion de JSON représentant le tableau
*/
protected function array2js($array,$show_keys) {
$tableauJs = '{}';
if (!empty($array)) {
$total = count($array) - 1;
$i = 0;
$dimensions = array();
foreach ($array as $key => $value) {
if (is_array($value)) {
$dimensions[$i] = array2js($value,$show_keys);
if ($show_keys) {
$dimensions[$i] = '\"'.$key.'\":'.$dimensions[$i];
}
} else {
$dimensions[$i] = '\"'.addslashes($value).'\"';
if ($show_keys) {
$dimensions[$i] = '\"'.$key.'\":'.$dimensions[$i];
}
}
if ($i == 0) {
$dimensions[$i] = '{'.$dimensions[$i];
}
if ($i == $total) {
$dimensions[$i].= '}';
}
$i++;
}
$tableauJs = implode(',', $dimensions);
}
return $tableauJs;
}
}
?>