You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

287 lines
8.3 KiB

<?php
/**
* Fonctions utiles au plugin Squelette SPIP
*
* @plugin Squelette SPIP
* @copyright 2017
* @author Jordan, nicod_
* @licence GNU/GPL
* @package SPIP\Skelspip\Fonctions
*/
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* On définit le critères enfants si on n'a pas polyhiérarchie
*/
if(!function_exists('critere_enfants_dist')){
function critere_enfants_dist($idb, &$boucles, $crit){
global $exceptions_des_tables;
$boucle = &$boucles[$idb];
if (isset($crit->param[0])){
$arg = calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent);
}
else
$arg = kwote(calculer_argument_precedent($idb, 'id_rubrique', $boucles));
if ($boucle->type_requete == 'rubriques' OR isset($exceptions_des_tables[$boucle->id_table]['id_parent'])) {
$id_parent = isset($exceptions_des_tables[$boucle->id_table]['id_parent']) ?
$exceptions_des_tables[$boucle->id_table]['id_parent'] :
'id_parent';
$mparent = $boucle->id_table . '.' . $id_parent;
}
else {
$mparent = $boucle->id_table . '.id_rubrique';
}
$where = array();
$where[] = "is_array(\$r=$arg)?sql_in('$mparent',\$r):array('=', '$mparent', \$r)";
$where = reset($where);
$boucle->where[]= $where;
}
}
/**
* Pluriels, singulier ou zéro...
*
* Les items sont à indiquer comme pour la fonction _T() sous la forme :
* "module:chaine"
*
* Cherchera chaine_zero, chaine_un, chaine_nb en fonction de $nb.
*
* @example
* ```
* [(#NB|galactic_pluraliser{forum:sujets})]
* [(#NB|galactic_pluraliser{#LISTE{forum:sujets_zero,forum:sujets_un,forum:sujets_nb}})]
* ```
*
* @param int $nb : le nombre
* @param string|array $chaine
* - string : radical de l'item de langue, sera complété par _zero, _un, _nb
* - array : couples {0 => module:chaine_zero, 1 => module:chaine_un, 2 => module:chaine_nb}
*
* @param array $vars : Les autres variables nécessaires aux chaines de langues (facultatif)
* @return string : la chaine de langue finale en utilisant la fonction _T()
*/
function galactic_pluraliser($nb, $chaine, $vars = array()) {
$nb = intval($nb);
if (!is_array($vars)) {
$vars = array();
}
if (!is_array($chaine)) {
$chaine = array(
$chaine . '_zero',
$chaine . '_un',
$chaine . '_nb',
);
}
$vars['nb'] = $nb;
if ($nb > 1) {
return _T($chaine[2], $vars);
} elseif ($nb == 1) {
return _T($chaine[1], $vars);
} else {
return _T($chaine[0], $vars);
}
}
/**
* Critère de recherche "fulltext" direct.
*
* On retourne le select et where fulltext et on l’ajoute à la boucle.
* On ne passe donc pas par la table spip_resultats.
*
* Évite qu’aucun résultat sur `(FORUMS){id_article}{recherche plugin}` ne soit retourné
* car la recherche ne stocke que les 500 premières réponses pertinentes dans
* toute la table forums (sans tenir compte de id_article)
*
* @note
* {recherche_fulltext} = {recherche_fulltext #ENV{recherche}}
*
* @param int $idb
* @param array $boucles
* @param array $crit
* @param array $ignore_keys exemple : `['forum' => ['titre']]`
*/
function critere_recherche_fulltext_dist($idb, &$boucles, $crit, $ignore_keys = []) {
$boucle = &$boucles[$idb];
if (isset($crit->param[0])) {
$quoi = calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent);
} else {
$quoi = '(isset($Pile[0]["recherche"]) ? $Pile[0]["recherche"] : (isset($GLOBALS["recherche"]) ? $GLOBALS["recherche"] : ""))';
}
$_modificateur = var_export($boucle->modificateur, true);
$_ignore_keys = var_export($ignore_keys, true);
$boucle->hash .= '
// RECHERCHE FULLTEXT' . ($crit->cond ? '
if (!strlen(' . $quoi . ')){
list($rech_select, $rech_where) = array("0 as points","");
} else' : '') . ' {
list($rech_select, $rech_where) = prepare_recherche_fulltext(' . $quoi . ', "' . $boucle->id_table . '", "' . $crit->cond . '", "' . $boucle->sql_serveur . '", ' . $_modificateur . ', "' . $boucle->primary . ', ' . $_ignore_keys . '");
}
';
$boucle->select[] = '$rech_select';
$boucle->where[] = '$rech_where?:\'\'';
}
/**
* Calculer les select et where Fulltext pour une recherche donnée.
*
* @see inc_prepare_recherche_dist() de Fulltext.
*
* @param string $recherche
* chaine recherchee
* @param string $table
* table dans laquelle porte la recherche
* @param bool $cond
* critere conditionnel sur {recherche?}
* @param string $serveur
* serveur de base de donnees
* @param array $modificateurs
* modificateurs de boucle, ie liste des criteres presents
* @param string $primary
* cle primaire de la table de recherche
* @param string $ignore_keys
* Clés à ignorer
* @return array
*/
function prepare_recherche_fulltext(
$recherche,
$table = 'articles',
$cond = false,
$serveur = '',
$modificateurs = array(),
$primary = '',
$ignore_keys = []
) {
include_spip('inc/rechercher');
$keys = fulltext_keys($table, $table, $serveur);
// Permettre d’ignorer des clés fulltext.
if (!empty($ignore_keys[$table])) {
$keys = array_diff_key($keys, array_flip($ignore_keys[$table]));
}
if (!$keys) {
return;
}
// s'il n'y a qu'un mot mais <= 3 lettres, il faut le chercher avec une *
// ex: RFC => RFC* ; car mysql fulltext n'indexe pas ces mots
if (preg_match('/^\w{1,3}$/', $recherche)) {
$recherche .= '*';
}
$r = trim(preg_replace(',\s+,', ' ', $recherche));
$p = sql_quote(trim("$r"), $serveur);
// si espace, ajouter la meme chaine avec des guillemets pour ameliorer la pertinence
$pe = (strpos($r, ' ') and strpos($r, '"') === false) ? sql_quote(trim("\"$r\""), $serveur) : '';
// On va additionner toutes les cles FULLTEXT
// de la table
$score = array();
$full_text_where = array();
foreach ($keys as $name => $key) {
$val = "MATCH($key) AGAINST ($p)";
$val_where = $val;
// Une chaine exacte rapporte plein de points
if ($pe) {
$val .= "+ 2 * MATCH($key) AGAINST ($pe)";
}
// Appliquer les ponderations donnees
// quels sont les champs presents ?
// par defaut le poids d'une cle est fonction decroissante
// de son nombre d'elements
// ainsi un FULLTEXT sur `titre` vaudra plus que `titre`,`chapo`
$compteur = preg_match_all(',`.*`,U', $key, $ignore);
$mult = intval(sqrt(1000/$compteur))/10;
// Appliquer le coefficient multiplicatif
if ($mult != 1) {
$val = "($val) * $mult";
}
// si symboles booleens les prendre en compte
if ($boolean = preg_match(', [+-><~]|\* |".*?",', " $r ")) {
$val = "MATCH($key) AGAINST ($p IN BOOLEAN MODE) * $mult";
$val_where = "MATCH($key) AGAINST ($p IN BOOLEAN MODE)";
}
$full_text_where[] = $val_where;
$score[] = $val;
}
$full_text_where = array('(('.implode(') OR (', $full_text_where).'))');
$score = 'SUM(' . join(' + ', $score) . ') AS points';
return array($score, $full_text_where);
}
function generer_svg($source, $width = null, $height = null, $alt = null) {
$style = '';
if ($source && file_exists($source)) {
$svg = svg_accessible(svg_compacte(file_get_contents($source)), $alt);
if ($width) {
$style .= 'max-width: '.$width.'px; width: 100%;';
}
if ($height) {
$style .= 'max-height: '.$height.'px; height: 100%;';
}
if ($style) {
$svg = str_replace('<svg ', '<svg style="'.$style.'" ', $svg);
}
return $svg;
}
return null;
}
function svg_compacte($svg) {
$svg = preg_replace('#(<\?xml[^>]*\?' . '>)#', '', $svg);
$svg = preg_replace('#(<!--[^>]*>)#', '', $svg);
$svg = preg_replace('#(xmlns="[^"]*")#', '', $svg);
$svg = preg_replace('#(xmlns:xlink="[^"]*")#', '', $svg);
$svg = preg_replace("#(\r|\n)*#", '', $svg);
$svg = preg_replace("#(\s)+#", ' ', $svg);
return $svg;
}
function svg_accessible($svg, $titre = null, $desc = null, $role = 'img') {
if ($titre || $desc) {
// insérer l'attribut sur la balise <svg>
$aria_labelledby = 'aria-labelledby="' . ($titre ? 'title' : '') . ($titre && $desc ? ' ' : '') . ($desc ? 'desc' : '') . '"';
$svg = preg_replace('#(<svg[^>]*)>#', '$1 ' . $aria_labelledby . '>', $svg);
// insérer les balises
if ($desc) {
$svg = preg_replace('#(<svg[^>]*>)#', '$1' . "\n" . '<desc id="desc">' . $desc . '</desc>', $svg);
}
if ($titre) {
$svg = preg_replace('#(<svg[^>]*>)#', '$1' . "\n" . '<title id="title">' . $titre . '</title>', $svg);
}
}
if ($role) {
// insérer l'attribut sur la balise <svg>
$aria_role = 'role="' . $role . '"';
$svg = preg_replace('#(<svg[^>]*)>#', '$1 ' . $aria_role . '>', $svg);
}
return $svg;
}