File "preparer_sql_plugin.php"
Full path: /home/argothem/www/v4_old/plugins-dist/bigup/javascript/plugins/auto/preparer_sql_plugin.php
File size: 10.67 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* Fichier permettant de calculer les données SQL à insérer
* à partir d'une arbre de description originaire d'un plugin.xml
*
* @plugin SVP pour SPIP
* @license GPL
* @package SPIP\SVP\Plugins
**/
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* Pour une description de plugin donnée (issue de la dtd de plugin.xml),
* prépare les données à installer en bdd
*
* Les données sont parfois sérialisées, parfois transcodées, parfois compilées
* pour tenir compte des spécificités de cette DTD et du stockage en bdd.
*
* @uses compiler_branches_spip()
* @param array $plugin
* Description de plugin
* @return array
* Couples clés => valeurs de description du paquet
**/
function plugins_preparer_sql_plugin($plugin) {
$dependances = [];
include_spip('inc/svp_outiller');
$champs = [];
if (!$plugin) {
return $champs;
}
// On initialise les champs ne necessitant aucune transformation
$champs['etat'] = (isset($plugin['etat']) and $plugin['etat']) ? $plugin['etat'] : '';
$champs['version'] = $plugin['version'] ? normaliser_version($plugin['version']) : '';
$champs['version_base'] = (isset($plugin['schema']) and $plugin['schema']) ? $plugin['schema'] : '';
// Renommage de certains champs
$champs['logo'] = (isset($plugin['logo']) and $plugin['logo']) ? $plugin['logo'] : '';
$champs['lien_doc'] = (isset($plugin['documentation']) and $plugin['documentation']) ? normaliser_lien($plugin['documentation']) : '';
// On passe le prefixe en lettres majuscules comme ce qui est fait dans SPIP
// Ainsi les valeurs dans la table spip_plugins coincideront avec celles de la meta plugin
$champs['prefixe'] = strtoupper($plugin['prefix']);
// Indicateurs d'etat numerique (pour simplifier la recherche des maj de STP)
static $num = ['stable' => 4, 'test' => 3, 'dev' => 2, 'experimental' => 1];
$champs['etatnum'] = (isset($plugin['etat']) and isset($num[$plugin['etat']])) ? $num[$plugin['etat']] : 0;
// On passe en utf-8 avec le bon charset les champs pouvant contenir des entites html
$champs['description'] = entite2charset($plugin['description'], 'utf-8');
// Traitement des auteurs, credits, licences et copyright
// -- on extrait les auteurs, licences et copyrights sous forme de tableaux
// -- depuis le commit 18294 du core la balise auteur est renvoyee sous forme de tableau mais
// contient toujours qu'un seul index
$balise_auteur = entite2charset($plugin['auteur'][0], 'utf-8');
$auteurs = normaliser_auteur_licence($balise_auteur, 'auteur');
$balise_licence = isset($plugin['licence'][0]) ? entite2charset($plugin['licence'][0], 'utf-8') : '';
$licences = normaliser_auteur_licence($balise_licence, 'licence');
// -- on merge les tableaux recuperes dans auteur et licence
$champs['auteur'] = $champs['licence'] = $champs['copyright'] = '';
if ($t = array_merge($auteurs['auteur'], $licences['auteur'])) {
$champs['auteur'] = serialize($t);
}
if ($t = array_merge($auteurs['licence'], $licences['licence'])) {
$champs['licence'] = serialize($t);
}
if ($t = array_merge($auteurs['copyright'], $licences['copyright'])) {
$champs['copyright'] = serialize($t);
}
// Extrait d'un nom et un slogan normalises
// Slogan : si vide on ne fait plus rien de special, on traitera ça a l'affichage
$champs['slogan'] = $plugin['slogan'] ? entite2charset($plugin['slogan'], 'utf-8') : '';
// Nom : on repere dans le nom du plugin un chiffre en fin de nom
// et on l'ampute de ce numero pour le normaliser
// et on passe tout en unicode avec le charset du site
$champs['nom'] = trim(entite2charset($plugin['nom'], 'utf-8'));
// Extraction de la compatibilite SPIP et construction de la liste des branches spip supportees
$champs['compatibilite_spip'] = $plugin['compatibilite'] ?: '';
$champs['branches_spip'] = ($plugin['compatibilite']) ? compiler_branches_spip($plugin['compatibilite']) : '';
// Construction du tableau des dependances necessite, lib et utilise
$dependances['necessite'] = $plugin['necessite'];
$dependances['librairie'] = $plugin['lib'];
$dependances['utilise'] = $plugin['utilise'];
$champs['dependances'] = serialize($dependances);
// Calculer le champ 'procure' (tableau sérialisé prefixe => version)
$champs['procure'] = '';
if (!empty($plugin['procure'][0])) {
$champs['procure'] = [];
foreach ($plugin['procure'][0] as $procure) {
$p = strtoupper($procure['nom']);
if (
!isset($champs['procure'][$p])
or spip_version_compare($procure['version'], $champs['procure'][$p], '>')
) {
$champs['procure'][$p] = $procure['version'];
}
}
$champs['procure'] = serialize($champs['procure']);
}
// Champs non supportes par la DTD plugin et ne pouvant etre deduits d'autres balises
$champs['lien_demo'] = '';
$champs['lien_dev'] = '';
$champs['credit'] = '';
return $champs;
}
/**
* Normalise un nom issu d'un plugin.xml
*
* @todo Supprimer cette fonction qui ne sert nulle part ?
*
* @uses extraire_trads()
*
* @param string $nom
* Le nom
* @param string $langue
* La langue à extraire
* @param bool $supprimer_numero
* Supprimer les numéros ?
* @return string
* Le nom
**/
function normaliser_nom($nom, $langue = '', $supprimer_numero = true) {
include_spip('inc/texte');
// On extrait les traductions de l'eventuel multi
// Si le nom n'est pas un multi alors le tableau renvoye est de la forme '' => 'nom'
$noms = extraire_trads(str_replace(['<multi>', '</multi>'], [], $nom, $nbr_replace));
$multi = ($nbr_replace > 0 and !$langue) ? true : false;
$nouveau_nom = '';
foreach ($noms as $_lang => $_nom) {
$_nom = trim($_nom);
if (!$_lang) {
$_lang = _LANGUE_PAR_DEFAUT;
}
if ($supprimer_numero) {
$nbr_matches = preg_match(',(.+)(\s+[\d._]*)$,Um', $_nom, $matches);
} else {
$nbr_matches = 0;
}
if (!$langue or $langue == $_lang or (is_countable($noms) ? count($noms) : 0) == 1) {
$nouveau_nom .= (($multi) ? '[' . $_lang . ']' : '') .
(($nbr_matches > 0) ? trim($matches[1]) : $_nom);
}
}
if ($nouveau_nom) { // On renvoie un nouveau nom multi ou pas sans la valeur de la branche
$nouveau_nom = (($multi) ? '<multi>' : '') . $nouveau_nom . (($multi) ? '</multi>' : '');
}
return $nouveau_nom;
}
/**
* Normalise un lien issu d'un plugin.xml
*
* Éliminer les textes superflus dans les liens (raccourcis [XXX->http...])
* et normaliser l'esperluete pour éviter l'erreur d'entité indéfinie
*
* @param string $url
* URL à normaliser
* @return string
* URL normalisée
*/
function normaliser_lien($url) {
if (!preg_match(',https?://[^]\s]+,', $url, $r)) {
return '';
}
$url = str_replace('&', '&', str_replace('&', '&', $r[0]));
return $url;
}
/**
* Normalise un auteur ou une licence issue d'un plugin.xml
*
* - Élimination des multi (exclus dans la nouvelle version)
* - Transformation en attribut des balises A
* - Interprétation des balises BR et LI et de la virgule et du
* espace+tiret comme séparateurs
*
* @uses _RACCOURCI_LIEN
*
* @param string $texte
* Texte de la balise
* @param string $balise
* Nom de la balise (auteur | licence)
* @return array
* Tableau listant les auteurs, licences et copyright trouvés
*/
function normaliser_auteur_licence($texte, $balise) {
include_spip('inc/filtres');
include_spip('inc/lien');
include_spip('inc/svp_outiller');
// On extrait le multi si besoin et on selectionne la traduction francaise
$t = normaliser_multi($texte);
$res = ['auteur' => [], 'licence' => [], 'copyright' => []];
foreach (preg_split('@(<br */?>)|<li>|,|\s-|\n_*\s*|&| & | et @', $t[_LANGUE_PAR_DEFAUT]) as $v) {
// On detecte d'abord si le bloc texte en cours contient un eventuel copyright
// -- cela generera une balise copyright et non auteur
$copy = '';
if (preg_match('/(?:\©|¬©|copyright|\(c\)|©)[\s:]*([\d-]+)/i', $v, $r)) {
$copy = trim($r[1]);
$v = str_replace($r[0], '', $v);
$res['copyright'][] = $copy;
}
// On detecte ensuite un lien eventuel d'un auteur
// -- soit sous la forme d'une href d'une ancre
// -- soit sous la forme d'un raccourci SPIP
// Dans les deux cas on garde preferentiellement le contenu de l'ancre ou du raccourci
// si il existe
$href = $mail = '';
if (preg_match('@<a[^>]*href=(\W)(.*?)\1[^>]*>(.*?)</a>@', $v, $r)) {
$href = $r[2];
$v = str_replace($r[0], $r[3], $v);
} elseif (preg_match(_RACCOURCI_LIEN, $v, $r)) {
if (preg_match('/([^\w\d._-]*)(([\w\d._-]+)@([\w\d.-]+))/', $r[4], $m)) {
$mail = $r[4];
} else {
$href = $r[4];
}
$v = $r[1] ?: str_replace($r[0], '', $v);
} else {
$href = '';
}
// On detecte ensuite un mail eventuel
if (!$mail and preg_match('/([^\w\d._-]*)(([\w\d._-]+)@([\w\d.-]+))/', $v, $r)) {
$mail = $r[2];
$v = str_replace($r[2], '', $v);
if (!$v) {
// On considere alors que la premiere partie du mail peut faire office de nom d'auteur
if (preg_match('/(([\w\d_-]+)[.]([\w\d_-]+))@/', $r[2], $s)) {
$v = ucfirst($s[2]) . ' ' . ucfirst($s[3]);
} else {
$v = ucfirst($r[3]);
}
}
}
// On detecte aussi si le bloc texte en cours contient une eventuelle licence
// -- cela generera une balise licence et non auteur
// cette heuristique n'est pas deterministe car la phrase de licence n'est pas connue
$licence = [];
if (
preg_match(
'/\b((gnu|free|creative\s+common|cc)*[\/|\s|-]*(apache|lgpl|agpl|gpl|fdl|mit|bsd|art\s+|attribution|by)(\s+licence|\-sharealike|-nc-nd|-nc-sa|-sa|-nc|-nd)*\s*v*(\d*[\.\d+]*))\b/i',
$v,
$r
)
) {
if ($licence = definir_licence($r[2], $r[3], $r[4], $r[5])) {
$res['licence'][] = $licence;
}
}
// On finalise la balise auteur ou licence si on a pas trouve de licence prioritaire
if ($href) {
$href = !preg_match(',https?://,', $href, $matches) ? 'http://' . $href : $href;
}
$v = trim(textebrut($v));
if ((strlen($v) > 2) and !$licence) {
if ($balise == 'auteur') {
$res['auteur'][] = ['nom' => $v, 'url' => $href, 'mail' => $mail];
} else {
$res['licence'][] = ['nom' => $v, 'url' => $href];
}
}
}
return $res;
}
/**
* Expanse les multi en un tableau de textes complets, un par langue
*
* @uses _EXTRAIRE_MULTI
* @param string $texte
* Le texte
* @return array
* Texte expansé par code de langue : couples (code de langue => texte)
*/
function normaliser_multi($texte) {
include_spip('inc/filtres');
if (!preg_match_all(_EXTRAIRE_MULTI, $texte, $regs, PREG_SET_ORDER)) {
return [_LANGUE_PAR_DEFAUT => $texte];
}
$trads = [];
foreach ($regs as $reg) {
foreach (extraire_trads($reg[1]) as $k => $v) {
// Si le code de langue n'est pas précisé dans le multi c'est donc la langue par défaut
$lang = $k ?: _LANGUE_PAR_DEFAUT;
$trads[$lang] = str_replace($reg[0], $v, $trads[$k] ?? $texte);
}
}
return $trads;
}