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.
 
 
 
 

273 lines
7.6 KiB

<?php
/**
* Déclaration de la classe `Pile` et de la balise `#SAISIE`
*
* @package SPIP\Saisies\Balises
**/
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
// pour ne pas interferer avec d'eventuelles futures fonctions du core
// on met le tout dans une classe ; les fonctions sont autonomes.
/**
* Conteneur pour modifier les arguments d'une balise SPIP (de classe Champ) à compiler
*
* @note
* Ces fonctions visent à modifier l'AST (Arbre de Syntaxe Abstraite) issues
* de l'analyse du squelette. Très utile pour créer des balises qui
* transmettent des arguments supplémentaires automatiquement, à des balises
* déjà existantes.
* Voir un exemple d'utilisation dans `balise_SAISIE_dist()`.
*
* @note
* Les arguments sont stockés sont dans l'entree 0 de la propriété `param`
* dans l'objet Champ (représenté par `$p`), donc dans `$p->param[0]`.
*
* `param[0][0]` vaut toujours '' (ou presque ?)
*
* @see balise_SAISIE_dist() Pour un exemple d'utilisation
**/
class Pile {
/**
* Récupère un argument de balise
*
* @param int $pos
* @param Champ $p
* @return mixed|null Élément de l'AST représentant l'argument s'il existe
**/
static function recuperer_argument_balise($pos, $p) {
if (!isset($p->param[0])) {
return null;
}
if (!isset($p->param[0][$pos])) {
return null;
}
return $p->param[0][$pos];
}
/**
* Supprime un argument de balise
*
* @param int $pos
* @param Champ $p
* @return Champ
**/
static function supprimer_argument_balise($pos, $p) {
if (!isset($p->param[0])) {
return null;
}
if (!isset($p->param[0][$pos])) {
return null;
}
if ($pos == 0) {
array_shift($p->param[0]);
} else {
$debut = array_slice($p->param[0], 0, $pos);
$fin = array_slice($p->param[0], $pos+1);
$p->param[0] = array_merge($debut, $fin);
}
return $p;
}
/**
* Retourne un argument de balise, et le supprime de la liste des arguments
*
* @uses Pile::recuperer_argument_balise()
* @uses Pile::supprimer_argument_balise()
*
* @param int $pos
* @param Champ $p
* @return mixed|null Élément de l'AST représentant l'argument s'il existe
**/
static function recuperer_et_supprimer_argument_balise($pos, &$p) {
$arg = Pile::recuperer_argument_balise($pos, $p);
$p = Pile::supprimer_argument_balise($pos, $p);
return $arg;
}
/**
* Ajoute un argument de balise
*
* Empile l'argument à la suite des arguments déjà existants pour la balise
*
* @param mixed $element Élément de l'AST représentant l'argument à ajouter
* @param Champ $p
* @return Champ
**/
static function ajouter_argument_balise($element, $p) {
// Toujours un parametre 0 vide s'il n'existe pas.
if (!isset($p->param[0][0])) {
if (!isset($p->param[0])) {
$p->param[0] = array();
}
$p->param[0][0] = '';
}
$zero = array_shift($p->param[0]);
array_unshift($p->param[0], $element);
array_unshift($p->param[0], $zero);
return $p;
}
/**
* Crée l'élément de l'AST représentant un argument de balise.
*
* @example
* ```
* $nom = Pile::creer_argument_balise(nom); // {nom}
* $nom = Pile::creer_argument_balise(nom, 'coucou'); // {nom=coucou}
*
* $balise = Pile::creer_balise('BALISE');
* $nom = Pile::creer_argument_balise(nom, $balise); // {nom=#BALISE}
* ```
*
* @param string $nom
* Nom de l'argument
* @param string|object $valeur
* Valeur de l'argument. Peut être une chaîne de caractère ou un autre élément d'AST
* @return array
**/
static function creer_argument_balise($nom, $valeur = null) {
include_spip('public/interfaces');
$s = new Texte;
$s->texte = $nom;
$s->ligne=0;
// si #BALISE cree avec Pile::creer_balise(), le mettre en array, comme les autres
if (is_object($valeur)) {
$valeur = array($valeur);
}
$res = null;
// {nom}
if (is_null($valeur)) {
$res = array($s);
} elseif (is_string($valeur)) {
// {nom=coucou}
$s->texte .= "=$valeur";
$res = array($s);
} elseif (is_array($valeur)) {
// {nom=#BALISE}
$s->texte .= '='; // /!\ sans cette toute petite chose, ça ne fait pas d'egalite :)
$res = array_merge(array($s), $valeur);
}
return $res;
}
/**
* Crée et ajoute un argument à une balise
*
* @uses Pile::creer_argument_balise()
* @uses Pile::ajouter_argument_balise()
*
* @param Champ $p
* @param string $nom
* Nom de l'argument
* @param string|object $valeur
* Valeur de l'argument. Peut être une chaîne de caractère ou un autre élément d'AST
* @return Champ
**/
static function creer_et_ajouter_argument_balise($p, $nom, $valeur = null) {
$new = Pile::creer_argument_balise($nom, $valeur);
return Pile::ajouter_argument_balise($new, $p);
}
/**
* Crée l'AST d'une balise
*
* @example
* ```
* // Crée : #ENV*{titre}
* $titre = Pile::recuperer_argument_balise(1, $p); // $titre, 1er argument de la balise actuelle
* $env = Pile::creer_balise('ENV', array('param' => array($titre), 'etoile' => '*'));
* ```
*
* @param string $nom
* Nom de la balise
* @param array $opt
* Options (remplira les propriétés correspondantes de l'objet Champ)
* @return Champ
**/
static function creer_balise($nom, $opt = array()) {
include_spip('public/interfaces');
$b = new Champ;
$b->nom_champ = strtoupper($nom);
foreach ($opt as $o => $val) {
if (property_exists($b, $o)) {
if ($o == 'param') {
array_unshift($val, '');
$b->$o = array($val);
} else {
$b->$o = $val;
}
}
}
return $b;
}
}
/**
* Compile la balise `#SAISIE` qui retourne le code HTML de la saisie de formulaire indiquée.
*
* Cette balise incluera le squelette `saisies/_base.html` et lui-même `saisies/{type}.html`
*
* La balise `#SAISIE` est un raccourci pour une écriture plus compliquée de la balise `#INCLURE`.
* La balise calcule une série de paramètre récupérer et à transmettre à `#INCLURE`,
* en fonction des valeurs des 2 premiers paramètres transmis.
*
* Les autres arguments sont transmis tels quels à la balise `#INCLURE`.
*
* Ainsi `#SAISIE{input,nom,label=Nom,...}` exécutera l'équivalent de
* `#INCLURE{nom=nom,valeur=#ENV{nom},type_saisie=input,erreurs,fond=saisies/_base,label=Nom,...}`
*
* @syntaxe `#SAISIE{type,nom[,option=xx,...]}`
*
* @uses Pile::recuperer_et_supprimer_argument_balise()
* @uses Pile::creer_balise()
* @uses Pile::creer_et_ajouter_argument_balise()
* @see balise_INCLURE_dist()
*
* @param Champ $p
* @return Champ
*/
function balise_SAISIE_dist($p) {
// on recupere les parametres sans les traduire en code d'execution php
$type_saisie = Pile::recuperer_et_supprimer_argument_balise(1, $p); // $type
$titre = Pile::recuperer_et_supprimer_argument_balise(1, $p); // $titre
// creer #ENV*{$titre} (* pour les cas de tableau serialises par exemple, que l'on veut reutiliser)
$env_titre = Pile::creer_balise('ENV', array('param' => array($titre), 'etoile' => '*')); // #ENV*{titre}
// on modifie $p pour ajouter des arguments
// {nom=$titre, valeur=#ENV{$titre}, erreurs, type_saisie=$type, fond=saisies/_base}
$p = Pile::creer_et_ajouter_argument_balise($p, 'nom', $titre);
$p = Pile::creer_et_ajouter_argument_balise($p, 'valeur', $env_titre);
$p = Pile::creer_et_ajouter_argument_balise($p, 'type_saisie', $type_saisie);
$p = Pile::creer_et_ajouter_argument_balise($p, 'erreurs');
$p = Pile::creer_et_ajouter_argument_balise($p, 'fond', 'saisies/_base');
// on appelle la balise #INCLURE
// avec les arguments ajoutes
if (function_exists('balise_INCLURE')) {
return balise_INCLURE($p);
} else {
return balise_INCLURE_dist($p);
}
}