<?php
/*******************************************************************************\
 * BIODIV, plugin et squelette pour SPIP - https://www.spip.net/               *
 *         dédié à la gestion d'observations naturalistes                      *
 *                                                                             *
 *         Copyright (C) 2008-2024 Renaud LAURETTE                             *
 *                                                                             *
 * BIODIV a été développé initialement pour le projet Biodiv.Balma de l'APCVEB *
 * (Association de Protection du Cadre de Vie et de l'Environnement balmanais) * 
 *     voir Biodiv.Balma : https://balma.biodiv.fr/                            *
 *     voir APCVEB : https://apcveb.fr/                                        *
 *                                                                             *
 *  Ce programme est un logiciel libre distribué sous licence GNU/GPL.         *
 *  Pour plus de détails voir les fichier COPYING.txt et LICENCE-BIODIV.md     *
\*******************************************************************************/


include_spip('inc/autoriser');
include_spip('inc/actions');
include_spip('inc/editer');
include_spip('biodiv_fonctions');


// Clause where
function clause_where($params,$criteres, &$desc)
{
	$where = array();
	$tables = array();
	foreach($criteres as $ct) {
		$obj = $ct['objet'];
		$prefix = $ct['prefix'];
		$pattern = $ct['desc'];
		foreach($ct['champs'] as $key => $value) {
			$pkey = $prefix . "_" . $key;
			
			if(array_key_exists($pkey,$params)) {
				$crit = trim($params[$pkey]);
					switch($value) {
					case 'EQUAL':
						if(strlen($crit) >0) {
							$where[]= "$prefix.$key=" . sql_quote($crit);
							$desc[$obj][] = _T(sprintf($pattern,$key)). " = '$crit'";
							$tables[$prefix]=1;
						}
						break;
					case 'EQUAL-INT':
						if(strlen($crit) >0) {
							$where[]= "$prefix.$key=" . intval($crit);
							$desc[$obj][] = _T(sprintf($pattern,$key)). " = ".intval($crit);
							$tables[$prefix]=1;
						}
						break;
					case 'LIKE':
						if(strlen($crit) >0) {
							$where[]= "$prefix.$key LIKE " . sql_quote($crit);
							$desc[$obj][] = _T(sprintf($pattern,$key)). " contient '$crit'";
							$tables[$prefix]=1;
						}
						break;
					case 'COMPARE':
						$kop = $pkey.'_op';
						if(array_key_exists($kop,$params) && (strlen($crit)>0)) {
							$where[] = "$prefix.$key $params[$kop] " . sql_quote($params[$pkey]);
							$desc[$obj][] = _T(sprintf($pattern,$key)). " $params[$kop] '$params[$pkey]'";
							$tables[$prefix]=1;
						}
						break;
					case 'COMPARE-INT':
						$kop = $pkey.'_op';
						if(array_key_exists($kop,$params) && (strlen($crit)>0)) {
							$where[] = "$prefix.$key $params[$kop] " . intval($params[$pkey]);
							$desc[$obj][] = _T(sprintf($pattern,$key)). " $params[$kop] ". intval($params[$pkey]);
							$tables[$prefix]=1;
						}
						break;
					case 'INTERVAL':
						$kfrom = $pkey.'_from';
						$kto = $pkey.'_to';
						if(array_key_exists($kfrom,$params) && (strlen($params[$kfrom])>0)) {
							$where[] = "$prefix.$key >= " .sql_quote($params[$kfrom]);
							$desc[$obj][] = _T(sprintf($pattern,$key)). " >= '$params[$kfrom]'";
							$tables[$prefix]=1;
						}
						if(array_key_exists($kto,$params) && (strlen($params[$kto])>0)) {
							$where[] = "$prefix.$key <= " . sql_quote($params[$kto]);
							$desc[$obj][] = _T(sprintf($pattern,$key)). " <= '$params[$kto]'";
							$tables[$prefix]=1;
						}
						break;
					default:
						break;
					}
				}
			}
	}
	return array($tables,$where);
}

function verbose($clause) {
	$text = "";
	foreach($clause as $value) {
		if(strlen($text) !=0) $text .= " AND ";
		$text .= $value;
	}
	return $text;
}


// Clause FROM de la requête
// définit les tables et leurs synonymes
function clause_from($criteres,$tables) {
	$from = $where = array();
	$p = "";
	// Récupération des jointures indirectes
	foreach($criteres as $ct) {
		$pfx = $ct['prefix'];
		if(isset($tables[$pfx])) {
			foreach($ct['join'] as $join) $tables[$join]=1;
		}
	}
	// Récupération des tables et des jointures
	foreach($criteres as $ct) {
		$pfx = $ct['prefix'];		
		if($ct['table'] == 'spip_biodiv_observations') {
			$from[] = $ct['table'] . " AS `$pfx`";
			$p= $pfx;
		} else {
			if(isset($tables[$pfx])) {
				$from[] = $ct['table'] . " AS `$pfx`";
				$where = array_merge($where,$ct['where']);
			}
		}
	}
	return array($p,$from,$where);
}


//
// Fonction CVT
//

function formulaires_rechercher_observation_charger()
{

	// On crée le repertoire de gestion des requêtes s'il n'existe pas déjà
	$repertoire = _DIR_TMP . 'requetes';
	if(!is_dir($repertoire)) {
		if(!file_exists($repertoire)) {
			spip_log("RequeteObservations: création du répertoire '$repertoire'","biodiv."._LOG_INFO_IMPORTANTE);
			mkdir($repertoire);
		} else {
			spip_log("RequeteObservations: Un fichier '$repertoire' existe: création ipossible du répertoire.","biodiv."._LOG_INFO_IMPORTANTE);
			return false;
		}
	} else {
		spip_log("RequeteObservations: Le répertoire '$repertoire' existe bien.","biodiv."._LOG_INFO_IMPORTANTE);
	}
	
	// On nettoie le dossier des requetes
	// ayant plus de $delai heures
	$delai = 24;
	$contenu = array_diff(scandir($repertoire),array(".",".."));
	foreach($contenu as $entry) {
		$file = $repertoire . '/' . $entry;
		$stat = stat($file);
		if($stat['mtime'] < time() - ($delai*60*60)) {
			unlink($file);
		}
	}	
	// Pas d'initialisation spécifique
	$valeurs = array();
	return $valeurs;
}

function formulaires_rechercher_observation_verifier()
{
	$erreurs = array();
	spip_log("RequeteObservations:Début vérification.","biodiv."._LOG_INFO_IMPORTANTE);
	
	// champs de recherche pour une observation
	$obs_criteria = array(
		'titre'		=> 'LIKE',
		'type_obs'	=> 'EQUAL',
		'espece'	=> 'LIKE',
		'quantite'	=> 'COMPARE-INT',
		'denombrement' => 'EQUAL',		
		'date_obs'	=> 'INTERVAL',
		'pjour'		=> 'EQUAL',
		'descriptif' => 'LIKE',
		'adresse'	=> 'LIKE',
		'commune'	=> 'LIKE',
		'insee'		=> 'EQUAL',
		'discret'	=> 'EQUAL'
		);
	
	// table auteurs_liens
	$aut_criteria = array (
		'id_auteur'	=> 'EQUAL'
		);
	
	// table article pour les fiches espece
	$esp_criteria = array (
		'titre' => 'LIKE',
		'soustitre' => 'LIKE'
		);
	
	// table rubrique pour les groupes d'espèces
	$rub_criteria = array(
		'titre' => 'LIKE'
		);		
	
	// table taxons pour la classification INPN
	$tax_criteria = array(
		'regne' => 'LIKE',
		'group1' => 'LIKE',
		'group2' => 'LIKE'
		);	
	
	// tous les champs de recherche
	$criteres = array(
		array(
			'objet' => 'Observation',
			'table' => 'spip_biodiv_observations',
			'champs' => $obs_criteria,
			'prefix' => 'o',
			'desc' => 'observation:champ_%s_label',
			'join' => array(),
			),
		array(
			'objet' => 'Observateur',
			'table' => 'spip_auteurs_liens',
			'champs' => $aut_criteria,
			'prefix' => 'a',
			'desc' => 'observation:champ_%s_label',
			'join' => array('o'),
			'where' => array(
						'a.id_objet = o.id_observation',
						"a.objet='observation'"
						)
			),	
		array(
			'objet' => 'Fiche esp&egrave;ce',
			'table' => 'spip_articles',
			'champs' => $esp_criteria,
			'prefix' => 'e',
			'desc' => 'espece:champ_%s_label',
			'join' => array('o'),
			'where' => array(
					"e.composition='espece'",
					'e.id_article = o.id_espece'
					)
			),
		array(
			'objet' => 'Groupe',
			'table' => 'spip_rubriques',
			'champs' => $rub_criteria,
			'prefix' => 'r',
			'desc' => 'espece:champ_%s_groupe',
			'join' => array('e'),
			'where' => array(
				"r.composition='espece'",
				'(r.id_rubrique=e.id_rubrique OR r.id_rubrique=e.id_secteur)',
				)
			),
		array(
			'objet' => 'Taxon',
			'table' => 'spip_taxrefs',
			'champs' => $tax_criteria,
			'prefix' => 't',
			'desc' => 'espece:champ_%s_taxon',
			'join' => array('e'),
			'where' => array(
				't.id_espece=e.id_article',
				)
			)
		);
	
	$desc = $tables = array();
	list($tables,$where1) = clause_where($_REQUEST,$criteres, $desc);
	list($opx,$from,$where2) = clause_from($criteres,$tables);
	$_REQUEST['w_observation'] = array_merge($where1,$where2);
	$_REQUEST['f_observation'] = $from;
	$_REQUEST['p_observation'] = $opx;
	$_REQUEST['v_observation'] = $desc;
	
	spip_log("RequeteObservations: Vérification faite.","biodiv."._LOG_INFO_IMPORTANTE);
	return $erreurs;
}

function formulaires_rechercher_observation_traiter()
{	
	$resultat = array();
	
	$requete['requete'] = $_REQUEST['v_observation'];
	
	// Construction du FROM
	$opx = $_REQUEST['p_observation'];
	$from = $_REQUEST['f_observation'];
	
	// construction du SELECT
	$what = array("$opx.id_observation","$opx.lat","$opx.lng");	
	
	// Construction de la clause WHERE : critères saisis ...
	$where = $_REQUEST['w_observation'];
	// ... autorisations différées : 
	// seront à appliquer au moment de l'appel de la requête
	$where[] = "$opx.discret IN (:discretion:)";	
	
	// On construit la bounding box si l'utilisateur a défini un périmètre
	$requete['perimetre'] = json_decode(_request('dumpy'));
	if(is_object($requete['perimetre'])) {
			$polygon = $requete['perimetre']->geometry->coordinates[0];
			$minlng = 180; $maxlng=-180;
			$minlat=90; $maxlat =-90;
			foreach($polygon as $vertex) {
				$minlng = ($minlng > $vertex[0]) ? $vertex[0] : $minlng;
				$minlat = ($minlat > $vertex[1]) ? $vertex[1] : $minlat;
				$maxlng = ($maxlng < $vertex[0]) ? $vertex[0] : $maxlng;
				$maxlat = ($maxlat < $vertex[1]) ? $vertex[1] : $maxlat;
			}
			$requete['perimetre']->bbox = array($minlng, $minlat, $maxlng, $maxlat);
			// ... bounding box du polygone ...
			$where[] = "$opx.lat <= $maxlat";
			$where[] = "$opx.lat >= $minlat";
			$where[] = "$opx.lng <= $maxlng";
			$where[] = "$opx.lng >= $minlng";
	}
	
	// Aggrégation de la requête
	$requete['sql'] = array(
		'select' => $what,
		'from'=> $from,
		'where' => $where,
		'eval' => array(
			'discretion' => 'discretion_auteur'
			)
		);
	
	// on génère le fichier
	$repertoire = _DIR_TMP . "requetes/";
	$fichier = md5(time());
	$file = $repertoire . $fichier . ".json";
	spip_log("RequeteObservations: Génération du fichier de requête '$file'.","biodiv."._LOG_INFO_IMPORTANTE);
	
	$fp = fopen($file,"w");
	if($fp) {
		// ecrire le fichier
		fwrite($fp,json_encode($requete));
		fclose($fp);
		spip_log("RequeteObservations: Requête '$file' sauvegardée.","biodiv."._LOG_INFO_IMPORTANTE);
		$resultat['message_ok'] = $requete->titre;
		$resultat['redirect'] = generer_url_public('observation_resultat',array('rq'=>$fichier),false, false);		
	} else {
		$resultat['message_erreur'] = "Echec cr&eacute;ation du fichier requ&ecirc;te :" . $requete->titre;
		spip_log("RequeteObservations: Echec de création du fichier requête '$file'.","biodiv."._LOG_INFO_IMPORTANTE);
	}

	// On retourne le résultat
	return $resultat;
}

?>
