|
|
|
@ -626,3 +626,178 @@ function territoire_extra_est_peuple($type, $pays, $type_extra) {
|
|
|
|
|
|
|
|
|
|
return $est_peuple;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Lit un objet donné connu par son id ou par un identifiant textuel unique et renvoie tout ou partie de sa
|
|
|
|
|
* description.
|
|
|
|
|
* Il est possible pour un objet donné de fournir la fonction `<objet>_lire_champs` qui renvoie simplement tous les
|
|
|
|
|
* champs de l'objet concerné sans aucun autre traitement. Sinon, l'appel SQL est réalisé par l'API.
|
|
|
|
|
*
|
|
|
|
|
* @param string $objet Type d'objet (comme article ou rubrique)
|
|
|
|
|
* @param int|string $valeur_id Valeur du champ identifiant
|
|
|
|
|
* @param array $options Tableau d'options dont les index possibles sont:
|
|
|
|
|
* - champs : liste des champs à renvoyer. Si absent ou vide la fonction
|
|
|
|
|
* renvoie tous les champs.
|
|
|
|
|
* - champ_id : nom du champ utilisé comme identifiant de l'objet. Si absent ou vide on
|
|
|
|
|
* utilise l'id défini dans la déclaration de l'objet.
|
|
|
|
|
* - force : true pour reforcer une lecture en base meme si un cache existe
|
|
|
|
|
*
|
|
|
|
|
* @return array|string|int|bool
|
|
|
|
|
* si champs est non fourni ou au format array
|
|
|
|
|
* false : l'objet demande n'existe pas
|
|
|
|
|
* array vide : l'objet existe, mais aucun champ demande n'existe
|
|
|
|
|
* array non vide : objet avec le ou les champs demandes existants (les champs demandes non existant sont absent)
|
|
|
|
|
* si champs est fourni au format string
|
|
|
|
|
* false : l'objet demande n'existe pas OU le champs demande n'existe pas
|
|
|
|
|
* string|int : valeur du champ demande pour l'objet demande
|
|
|
|
|
*/
|
|
|
|
|
function objet_lire($objet, $valeur_id, $options = []) {
|
|
|
|
|
if (($t = objet_type($objet)) !== $objet) {
|
|
|
|
|
spip_log("objet_lire: appel avec type $objet invalide au lieu de $t", 'editer' . _LOG_INFO_IMPORTANTE);
|
|
|
|
|
$objet = $t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// tableau du cache des descriptions et des id d'objet (au sens id_xxx).
|
|
|
|
|
// Les tableaux sont toujours indexés par le trio [objet][cle][valeur_cle]
|
|
|
|
|
static $descriptions = [];
|
|
|
|
|
|
|
|
|
|
// On détermine le nom du champ id de la table.
|
|
|
|
|
include_spip('base/objets');
|
|
|
|
|
$primary = id_table_objet($objet);
|
|
|
|
|
|
|
|
|
|
// On détermine l'id à utiliser.
|
|
|
|
|
$champ_id = (!empty($options['champ_id']) ? $options['champ_id'] : $primary);
|
|
|
|
|
|
|
|
|
|
// Si l'objet n'a pas encore été stocké, il faut récupérer sa description complète.
|
|
|
|
|
if (
|
|
|
|
|
!isset($descriptions[$objet][$champ_id][$valeur_id])
|
|
|
|
|
or (isset($options['force']) and $options['force'])
|
|
|
|
|
) {
|
|
|
|
|
// Il est possible pour un type d'objet de fournir une fonction de lecture de tous les champs d'un objet.
|
|
|
|
|
if (
|
|
|
|
|
include_spip('action/editer_' . $objet)
|
|
|
|
|
and function_exists($lire = "${objet}_lire_champs")
|
|
|
|
|
) {
|
|
|
|
|
$valeurs = $lire($objet, $valeur_id, $champ_id);
|
|
|
|
|
} else {
|
|
|
|
|
// On récupère la table SQL à partir du type d'objet.
|
|
|
|
|
$table = table_objet_sql($objet);
|
|
|
|
|
|
|
|
|
|
// La condition est appliquée sur le champ désigné par l'utilisateur.
|
|
|
|
|
$where = [
|
|
|
|
|
"${champ_id}=" . sql_quote($valeur_id)
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// Acquisition de tous les champs de l'objet : si l'accès SQL retourne une erreur on renvoie un tableau vide.
|
|
|
|
|
$valeurs = sql_fetsel('*', $table, $where);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!$valeurs) {
|
|
|
|
|
$valeurs = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$descriptions[$objet][$champ_id][$valeur_id] = $valeurs;
|
|
|
|
|
|
|
|
|
|
if ($champ_id !== $primary and isset($valeurs[$primary])) {
|
|
|
|
|
$descriptions[$objet][$primary][$valeurs[$primary]] = $valeurs;
|
|
|
|
|
$descriptions[$objet][$champ_id][$valeur_id] = &$descriptions[$objet][$primary][$valeurs[$primary]];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$retour = $descriptions[$objet][$champ_id][$valeur_id];
|
|
|
|
|
|
|
|
|
|
// On ne retourne maintenant que les champs demandés.
|
|
|
|
|
// - on détermine les informations à renvoyer.
|
|
|
|
|
if ($retour and !empty($options['champs'])) {
|
|
|
|
|
$champs = $options['champs'];
|
|
|
|
|
// Extraction des seules informations demandées.
|
|
|
|
|
// -- si on demande une information unique on renvoie la valeur simple, sinon on renvoie un tableau.
|
|
|
|
|
// -- si une information n'est pas un champ valide elle n'est pas renvoyée sans renvoyer d'erreur.
|
|
|
|
|
if (is_array($champs)) {
|
|
|
|
|
// Tableau des informations valides
|
|
|
|
|
$retour = array_intersect_key($retour, array_flip($champs));
|
|
|
|
|
} else {
|
|
|
|
|
// Valeur unique demandée.
|
|
|
|
|
$retour = ($retour[$champs] ?? false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $retour;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Lancer le cron via un hit http sans attendre le resultat
|
|
|
|
|
* @param string $url_cron
|
|
|
|
|
* @return bool : true si l'url a pu être appelée en asynchrone, false sinon
|
|
|
|
|
*/
|
|
|
|
|
function queue_lancer_url_http_async($url_cron) {
|
|
|
|
|
// methode la plus rapide :
|
|
|
|
|
// Si fsockopen est possible, on lance le cron via un socket en asynchrone
|
|
|
|
|
// si fsockopen echoue (disponibilite serveur, firewall) on essaye pas cURL
|
|
|
|
|
// car on a toutes les chances d'echouer pareil mais sans moyen de le savoir
|
|
|
|
|
// mais on renvoie false direct
|
|
|
|
|
if (function_exists('fsockopen')) {
|
|
|
|
|
$parts = parse_url($url_cron);
|
|
|
|
|
|
|
|
|
|
switch ($parts['scheme']) {
|
|
|
|
|
case 'https':
|
|
|
|
|
$scheme = 'ssl://';
|
|
|
|
|
$port = 443;
|
|
|
|
|
break;
|
|
|
|
|
case 'http':
|
|
|
|
|
default:
|
|
|
|
|
$scheme = '';
|
|
|
|
|
$port = 80;
|
|
|
|
|
}
|
|
|
|
|
$fp = @fsockopen(
|
|
|
|
|
$scheme . $parts['host'],
|
|
|
|
|
$parts['port'] ?? $port,
|
|
|
|
|
$errno,
|
|
|
|
|
$errstr,
|
|
|
|
|
1
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ($fp) {
|
|
|
|
|
$host_sent = $parts['host'];
|
|
|
|
|
if (isset($parts['port']) and $parts['port'] !== $port) {
|
|
|
|
|
$host_sent .= ':' . $parts['port'];
|
|
|
|
|
}
|
|
|
|
|
$timeout = 200; // ms
|
|
|
|
|
stream_set_timeout($fp, 0, $timeout * 1000);
|
|
|
|
|
$query = $parts['path'] . ($parts['query'] ? '?' . $parts['query'] : '');
|
|
|
|
|
$out = 'GET ' . $query . " HTTP/1.1\r\n";
|
|
|
|
|
$out .= 'Host: ' . $host_sent . "\r\n";
|
|
|
|
|
$out .= "Connection: Close\r\n\r\n";
|
|
|
|
|
fwrite($fp, $out);
|
|
|
|
|
spip_timer('read');
|
|
|
|
|
$t = 0;
|
|
|
|
|
// on lit la reponse si possible pour fermer proprement la connexion
|
|
|
|
|
// avec un timeout total de 200ms pour ne pas se bloquer
|
|
|
|
|
while (!feof($fp) and $t < $timeout) {
|
|
|
|
|
@fgets($fp, 1024);
|
|
|
|
|
$t += spip_timer('read', true);
|
|
|
|
|
spip_timer('read');
|
|
|
|
|
}
|
|
|
|
|
fclose($fp);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// si fsockopen n'est pas dispo on essaye cURL :
|
|
|
|
|
// lancer le cron par un cURL asynchrone si cURL est present
|
|
|
|
|
elseif (function_exists('curl_init')) {
|
|
|
|
|
//setting the curl parameters.
|
|
|
|
|
$ch = curl_init($url_cron);
|
|
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
|
// cf bug : http://www.php.net/manual/en/function.curl-setopt.php#104597
|
|
|
|
|
curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
|
|
|
|
|
// valeur mini pour que la requete soit lancee
|
|
|
|
|
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200);
|
|
|
|
|
// lancer
|
|
|
|
|
curl_exec($ch);
|
|
|
|
|
// fermer
|
|
|
|
|
curl_close($ch);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|