Skip to content
Extraits de code Groupes Projets
Valider f3120a68 rédigé par ben.spip@gmail.com's avatar ben.spip@gmail.com
Parcourir les fichiers

et réaparaissent

git-svn-id: https://zone.spip.org/spip-zone/_core_/tests@28915 ac52e18a-acf5-0310-9fe8-c4428f23b10a
parent
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
Affichage de
avec 1518 ajouts et 0 suppression
[(#REM|ou{1}|=={' '}|?{'',ou est pete})]
[(#REM|et{1}|=={''}|?{'',et est pete})]
[(#REM|xor{1}|=={' '}|?{'',xor est pete})]
[(#REM|not|=={' '}|?{'',not est pete})]
[(#REM|not|not|=={''}|?{'',not est pete})]
[(#REM|sinon{'a'}|=={'a'}|?{'',sinon est pete})]
[(#REM|not|sinon{'a'}|=={' '}|?{'',sinon est pete})]
OK
<?php
# Ces tests sont invalides, cf.
# http://trac.rezo.net/trac/spip/ticket/778#comment:5
$test = 'parametre_url';
require '../test.inc';
$url = "/ecrire/?exec=exec&id_obj=id_obj&no_val";
$amp = str_replace('&', '&amp;', $url);
$essais["ajout_parametre"] =
array($amp . '&amp;ajout=valajout', $url, 'ajout', 'valajout');
$essais["enleve_parametre"] =
array('/ecrire/?exec=exec&amp;no_val', $url, 'id_obj', '');
$essais["change_parametre"] =
array('/ecrire/?exec=exec&amp;id_obj=changobj&amp;no_val', $url, 'id_obj', 'changobj');
$essais["change_noval"] =
array('/ecrire/?exec=exec&amp;id_obj=id_obj&amp;no_val=yesval', $url, 'no_val', 'yesval');
$essais["enleve_parametre_no_val"] =
array('/ecrire/?exec=exec&amp;id_obj=id_obj', $url, 'no_val', '');
$essais["enleve_parametre_no_amp"] =
array('/ecrire/?exec=exec&no_val',$url,'id_obj','','&');
$essais["enleve_parametre_no_valamp"] =
array('/ecrire/?exec=exec&id_obj=id_obj', $url, 'no_val','','&');
$essais["recupere_parametre_id_obj"] =
array('id_obj', $url, 'id_obj');
$essais["recupere_parametre_no_val"] =
array('', $url, 'no_val');
$essais["recupere_parametre_absent"] =
array(NULL, $url, 'toto');
//
// hop ! on y va
//
$err = tester_fun('parametre_url', $essais);
// si le tableau $err est pas vide ca va pas
if ($err) {
die ('<dl>' . join('', $err) . '</dl>');
}
echo "OK";
?>
<?php
require '../test.inc';
include_spip('base/abstract_sql');
if (function_exists('sql_in'))
$test = 'sql_in';
else
$test = 'calcul_mysql_in';
$essais[] =
array('((i IN (1,2,3)))','i','1,2,3');
$essais[] =
array('((i IN ("a","b","c")))','i','"a","b","c"');
$essais[] =
array("((i IN (1,2,4)))",'i',array(1,2,4));
$essais[] =
array("((i IN ('a','b','c')))",'i',array('a','b','c'));
// ce test ne peut pas marcher avec _q(), il faut eviter le hex
// dans toute cette histoire
# $essais[] =
# array('((referer_md5 IN (0x8488c20259e2c09)))','referer_md5','0x8488c20259e2c09');
//
// hop ! on y va
//
$err = tester_fun($test, $essais);
// si le tableau $err est pas vide ca va pas
if ($err) {
die ('<dl>' . join('', $err) . '</dl>');
}
echo "OK";
?>
<?php
(isset($test) && $test) || ($test = 'suivre_liens');
require '../test.inc';
include_spip('inc/filtres');
# source # lien # resultat
$tests = array(
array(
suivre_lien('http://toto/', 'http://tata/'), 'http://tata/'
),
array(
suivre_lien('http://toto/', 'tata'), 'http://toto/tata'
),
array(
suivre_lien('http://toto/ad?hic', '?hoc'), 'http://toto/?hoc'
),
array(
suivre_lien('http://toto/./', '#hup'), 'http://toto/#hup'
),
array(
suivre_lien('http://toto/fleche/de/tout', '/bois/'), 'http://toto/bois/'
),
array(
suivre_lien('http://toto/du/lac#1', 'yop'), 'http://toto/du/yop'
),
array(
suivre_lien('http://toto/', 'http://tata/'), 'http://tata/'
),
array(
suivre_lien('http://toto/allo', '#3'), 'http://toto/allo#3'
),
array(
suivre_lien('http://toto/', 'http://tata/./'), 'http://tata/'
),
array(
suivre_lien('http://toto/et#lui', ''), 'http://toto/et#lui'
),
array(
suivre_lien('http://toto', './'), 'http://toto/'
),
array(
suivre_lien('http://toto/hop/a', './'), 'http://toto/hop/'
)
);
//
// hop ! on y va
//
foreach ($tests as $c => $u)
if ($u[0] !== $u[1]) {
echo "test $c: ".htmlspecialchars($u[0]).' =! '.htmlspecialchars($u[1])."<br />\n";
$err++;
}
if ($err)
exit;
echo "OK";
?>
<?php
$test = 'typo';
require '../test.inc';
include_spip('inc/texte');
lang_select('fr');
// un ! mais pas deux
$essais[] = array('Chat&nbsp;!!', "Chat!!");
// et pas apres "(" -- http://trac.rezo.net/trac/spip/changeset/10177
$essais[] = array('(!)', "(!)");
$err = tester_fun('typo', $essais);
// si le tableau $err est pas vide ca va pas
if ($err) {
die ('<dl>' . join('', $err) . '</dl>');
}
echo "OK";
?>
<?php
chdir('..');
require 'ecrire/inc_version.php';
// pas admin ? passe ton chemin (ce script est un vilain trou de securite)
if ( ($auteur_session['statut'] != '0minirezo') and ( $_SERVER["REMOTE_ADDR"]!='127.0.0.1'))
die('pas admin !');
// chercher les bases de tests
$bases = array('tests');
foreach (creer_chemin() as $d) {
if ($d && @is_dir("${d}tests"))
$bases[] = "${d}tests";
}
echo
"<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>\n",
"<html><head><title>Tests de SPIP</title>",
"<script src='jquery-1.1.js' type='text/javascript'></script>\n",
"<script src='testrunner.js' type='text/javascript'></script>\n",
"<link rel='stylesheet' href='tests.css' type='text/css' />\n",
"</head><body>\n",
"<h1>",
"Tests SPIP ", version_spip(),
"</h1>\n";
foreach ($bases as $base) {
// regarder tous les tests
$tests = preg_files($base .= '/', '/\w+/.*\.(php|html)$');
foreach ($tests as $test) {
if (strlen($t=_request('rech')) && (strpos($test, $t)===false))
continue;
//ignorer le contenu du jeu de squelettes dédié aux tests
if (stristr($test,'squelettes'))
continue;
//ignorer les fichiers lanceurs pour simpleTests aux tests
if (stristr($test,'lanceur_spip.php'))
continue;
if (stristr($test,'all_tests.php'))
continue;
if (substr(basename($test),0,7) != 'inclus_' &&
substr(basename($test),-14) != '_fonctions.php'){
if (preg_match(',\.php$,', $test))
$url = '../'.$test.'?mode=test_general';
else
$url = "squel.php?test=$test&amp;var_mode=recalcul";
$joli = basename($test);
$dirTests = false;
if ($base == 'tests/') {
$dirTests = true;
$section = basename(dirname($test));
} else {
$section = dirname($test);
$section_dir = $section;
#$section = str_replace('/tests',' ',dirname($test));
if ($svn = version_svn_courante(dirname(dirname($test))))
$section_svn = ' ['.abs($svn).']';
}
if ($section <> $sectionold) {
if ($sectionold) echo "</dl>\n";
$titre = $dirTests ? $section : "<a href='../$section_dir'>$section</a>$section_svn";
echo "<dl><dt>$titre</dt>\n";
$sectionold = $section;
}
echo "<dd>
<a href='$url' class='joli'>".$joli.":</a> &nbsp;
&nbsp;</dd>\n";
}
}
}
echo "</dl>\n";
echo "<div id='count'>";
echo "<span id='succes'>0</span> succ&#232;s, ";
echo "<span id='echec'>0</span> &#233;chec / ";
echo "<span id='total'>0</span> total";
echo "<br />tests exp&#233;di&#233;s en <span id='timer'>0</span>ms";
echo "</div>";
echo "</body></html>";
function version_spip() {
include_spip('inc/minipres');
$version = $GLOBALS['spip_version_affichee'];
if ($svn_revision = version_svn_courante(_DIR_RACINE))
$version .= ' ' . (($svn_revision < 0) ? 'SVN ':'')
. "[<a href='http://trac.rezo.net/trac/spip/changeset/"
. abs($svn_revision) . "' onclick=\"window.open(this.href); return false;\">"
. abs($svn_revision) . "</a>]";
return $version;
}
?>
Ce diff est replié.
<?php
$test = 'chemin';
require '../test.inc';
$chemin = creer_chemin();
_chemin('toto');
$chemin1 = creer_chemin();
if ((count($chemin1)!=(count($chemin)+1))
OR ('toto/'!==$chemin1[1] AND 'toto/'!==$chemin1[0]))
die('Erreur ajout chemin par la fonction _chemin()'.var_dump($chemin).var_dump($chemin1));
$GLOBALS['dossier_squelettes']= "titi:".$GLOBALS['dossier_squelettes'];
$chemin2 = creer_chemin();
if ( (count($chemin2)==count($chemin1)) OR 'titi/'!==reset($chemin2) )
die('Erreur prise en compte dossier squelette'.var_dump($chemin1).var_dump($chemin2));
echo "OK";
?>
<?php
$test = 'Ne pas crasher sur les <code><code></code> imbriqués';
require '../test.inc';
include_spip('inc/texte');
$c = dutexte();
propre($c);
die('OK');
//
// DONNEES
//
function dutexte() {
return '({{{Classificar els resultats}}}
<html><tt><b>{par</b> <i>critère_de_classement</i><b>}</b></tt></html> iIndica l’ordre en què es presenten els resultats. Aquest criteri de classificació correspon a una de les etiquetes extretes de la base de dades per cada tipus de bucle. Per exemple, podrem classificar els articles per la data <code>{per date}</code>, per la data en què han estat redactats <code>{par date_redac}</code> o per títol <code>{par titre}</code>. (Fixeu-vos que, tot i que les etiquetes es presenten en majúscules, els criteris de classificació es presenten en minúscules.)
{Cas particular}: {{<code>{par hasard}</code>}} (per atzar) permet mostrar una llista presentada en ordre aleatori.
{Invertir la classificació}. A més a més, {{<code>{inverse}</code>}} provoca la presentació d’una classificació en ordre invers. Per exemple <code>{par date}</code> comença pels articles més antics; amb <code>{par date}{inverse}</code> la llista es comença amb els articles més recents.
A partir d\'[->3369], el criteri {inverse} pot agafar com a paràmetre qualsevol marcador per tal de variar dinàmicament el sentit de la tria. Per exemple, és possible escriure: <code><BOUCLE_exemple(ARTICLES){par #ENV{tri}}{inverse #ENV{senstri}}></code>, la qual cosa permet escollir la columna de selecció i el sentit del que s\'escull per mitjà del url (&senstri=1 o &senstri=0)
{Classificar per número}. <span style=\'color: red;\'>[SPIP 1.3]</span> Quan el criteri de classificació es un element de text (per exemple el títol –{titre}-), la classificació es fa per ordre {alfabètic}. No obstant, per forçar un ordre de presentació, es pot posar un número al davant del títol. Per exemple: «1. El meu primer article», « 2. Segon article», « 3. Tercer... », etc. Amb una classificació alfabètica, la classificació d’aquests elements donaria la sèrie «1, 10, 11, 2, 3...». Per restablir la classificació numèrica, es pot fer servir el criteri:
<html><tt><b>{par num</b> critère<b>}</b></tt></html>
Per exemple:
<cadre><BOUCLE_articles(ARTICLES){id_rubrique}{par date}{inverse}></cadre>
mostra els articles d’una secció classificats segons un ordre cronològic invers (els més recents al començament, els més antics al final), i:
<cadre><BOUCLE_articles(ARTICLES){id_rubrique}{par titre}>
</cadre>
els mostra segons l’ordre alfabètic del seu títol; finalment:
<cadre><BOUCLE_articles(ARTICLES){id_rubrique}{par num titre}>
</cadre>
els mostra segons l’ordre del número del seu títol. (ALERTA: l\'opció <code>{par num titre<code>}</code> no funciona en les versions de MySQL anteriors a la versió 3.23).
{Classificar segons diversos criteris} A partir de [->3005], es pot classificar segons diversos criteris: <html><tt><b>{par</b> critère1<b>,</b> critère2<b>}</b></tt></html>. S\'indiquen d\'aquesta manera ordres de classificació consecutives. Els resultats es s\'ordenaran primerament segons el {critère1}, després el {critère2} pels resultats que tinguin el mateix {critère1}. Es poden especificar tants criteris com sigui necessari.
Per exemple <code>{par date, titre}</code> ordena els resultats per {date} després els resultats que tenen la mateixa {date} seran ordenats per {titre}.
Amb [->3176] podem especificar diversos criteris <html><tt><b>{par</b> <i>...</i><b>}</b></tt></html> per un boucle per arribar al mateix resultat. Per exemple: <code>{par date} {par titre}</code> és equivalent a l\'exemple anterior.
<blockquote>
{Comentari:} Quan s\'utilitzen diversos criteris de classificació, el criteri <HTML><TT><B>{inverse}</B></TT></HTML> només s\'aplica al criteri de classificació situat just abans.
És per això que [->3176] introdueix la notació <HTML><TT><B>{!par ...}</B></TT></HTML> que inversa un criteri de classificació en particular. Per exemple: <code>{!par date} {par num titre}</code> classifica per {date} decreixents, després per números creixents en el mateix {titre} pels resultats que tenen la mateixa {date}.
</blockquote>
{{{Comparacions, igualtats}}}
<HTML><TT><B>{</B><I>critère</I> <B> < </B><I>valeur</I><B>}</B></TT></HTML> Comparació amb un valor fixat (es pot utilitzar «>», «<», «=», «>=», «<=». Tots els {criteris de classificació} (tal i com són extrets de la base de dades) poden ser utilitzats igualment per limitar el número de resultats.
El valor a la dreta de l\'operador pot ser:
- Un valor constant fixat a l\'esquelet. Per exemple:
<cadre><BOUCLE_art(ARTICLES){id_article=5}></cadre>
mostra només l’article que té el número 5. És útil, per exemple, per ressaltar un article concret a la pàgina d’inici.
<cadre><BOUCLE_art(ARTICLES){id_secteur=2}></cadre>
mostra els articles del sector número 2.
- A partir de <span style=\'color: #fa9a00;\'>[SPIP 1.8]</span>, una etiqueta disponible en el context del bucle. Per exemple:
<cadre>
<BOUCLE_art(ARTICLES){id_article=5}>
<BOUCLE_titre(ARTICLES) {titre=#TITRE}>
...
</BOUCLE_titre>
</BOUCLE_art>
</cadre>
serveix per trobar els articles que tenen el mateix títol que l\'article 5.
<blockquote>
{Atenció:} Només podem fer servir una etiqueta simple. No està permès ni filtrar-la ni posar-hi codi opcional.
En especial, si volem utilitzar l\'etiqueta {{#ENV}} -- o una altra etiqueta que admeti paràmetres --, hem d\'emprar la notació: <code>{titre = #ENV{titre}}</code> i {{no}}: <code>{titre = [(#ENV{titre})]}</code>.
</blockquote>
{{Expressions regulars:}}
Molt potent (però força més complexe de manipular), el terme de comparació « == » introdueix una comparació segons una expressió regular. Per exemple:
<cadre><BOUCLE_art(ARTICLES){titre==^[aA]}></cadre>
selecciona els articles el títol dels quals comença per « a » o « A ».
{{Negació:}}
A partir de <span style=\'color: red;\'>[SPIP 1.2]</span> es pot fer servir la notació <html><tt>{xxx != yyy}</tt> i <tt>{xxx !== yyy}</tt></html>, el <html>!</html> corresponent a la negació (operador lògic NOT).
<cadre><BOUCLE_art(ARTICLES){id_secteur != 2}></cadre>
selecciona els articles que no pertanyen al sector número 2.
<cadre><BOUCLE_art(ARTICLES){titre!==^[aA]}></cadre>
selecciona els articles el títol dels quals {no} comença per « a » o « A ».
{{{Publicació en funció de la data}}}
Per facilitar l\'ús de les comparacions a les dates, s\'han afegit els criteris següents:
- <TT>age</TT> i <TT>age_redac</TT> corresponen respectivament a l’antiguitat de la publicació i de la primera publicació d’un article, en dies: <TT><code>{</code>age<30<code>}</code></TT> selecciona els elements publicats des de fa menys d’un mes;
- els critères <TT>mois</TT>, <TT>mois_redac</TT>, <TT>annee</TT>, <TT>annee_redac</TT> permeten comparar amb valors fixes (per exemple, <code>{annee<=2000}</code> pels elements publicats fins l’any 2000).
Es poden combinar diversos criteris per efectuar seleccions més precises. Per exemple:
<cadre><BOUCLE_art(ARTICLES){id_secteur=2}{id_rubrique!=3}{age<30}></cadre>
mostra els articles del sector 2, excepte els de la secció 3, i publicats des de fa menys de 30 dies.
{Una astúcia}. El criteri <code>edat</code> és molt pràctic per mostrar els articles o les breus la data dels quals és « posterior » a l’actual, amb valors negatius (a condició d’haver seleccionat, a la Configuració precisa del lloc, la opció « Publicar els articles amb data posterior »). Per exemple, aquest criteri permet de donar èmfasi a futurs esdeveniments: <code>{age<0}</code> selecciona els articles o les breus d’una data posterior (« desprès » d’avui)...
<span style=\'color: red;\'>(SPIP 1.3)</span> {Edat respecte a una data donada}. El criteri edat <code>(age)</code> es calcula en relació a la data d’avui (d’aquesta manera, <code>{age<30}</code> correspon als articles publicats des de fa menys d’un mes respecte a la data d’avui). El criteri <tt><b>age_relatif</b></tt> (edat relativa) compara la data d’un article o d’una breu amb una data «actual»; per exemple, a l’interior d’un bucle ARTICLES, coneixem ja una data per a cada resultat del bucle, per tant, podem seleccionar en relació a aquesta data (i no només en relació amb la data d’avui).
Per exemple:
<cadre>
<BOUCLE_article_principal(ARTICLES){id_article}>
<h1>#TITRE</h1>
<BOUCLE_suivant(ARTICLES){id_rubrique}{age_relatif<=0}{exclus}{par date}{0,1}>
Article següent: #TITRE
</BOUCLE_suivant>
</BOUCLE_article_principal>
</cadre>
el BOUCLE_suivant mostra un únic article de la mateixa secció, classificat per data, la data de publicació del qual és inferior o igual a la data de l’« article_principal »; és a dir, l’article de la mateixa secció publicat després de l’article principal.
Trobareu informació més àmplia sobre la utilització de les dates a l\'article que parla sobre «[->2198]».
{{{Presentació d’una part dels resultats}}}
- {{<code>{branche}</code>}} A partir de <span style=\'color: #066;\'>[SPIP 1.8.2]</span>, limita els resultats -- pels bucles que tenen un #ID_RUBRIQUE -- a la branca actual (la secció actual i les subseccions). Per exemple:
_ <code><BOUCLE_articles(ARTICLES) {branche}></code> ens tornarà tots els articles de la secció actual i de les seves subseccions,
_ <code><BOUCLE_articles(ARTICLES) {!branche}></code> ens tornarà tots els articles uq no es troben dins de la secció actual o les seves subseccions,
Es pot utilitzar el criteri
<HTML><TT><B>{branche?}</B></TT></HTML> {optionnel} per aplicar-lo només si una secció es selecciona dins del context (un bucle englobant o l\'url proporcionada per un id_rubrique). Per exemple:
_ <code><BOUCLE_articles(ARTICLES) {branche?}></code> ens retornarà tots els articles de la secció actual i de les seves subseccions si hi ha un id_rubrique en el context, sinó, ens torna tots els articles del lloc Web.
[#doublons<-]
- {{<code>{doublons}</code>}} o {{<code>{unique}</code>}} (aquests dos criteris són absolutament idèntics) permeten prohibit que es mostrin resultats que ja s\'han mostrar dins d\'altres bucles utilitzant aquest criteri.
<quote>{històric:}
A partir de <span style=\'color: red;\'>[SPIP 1.2]</span> i fins a [<span style=\'color: red;\'>S</span><span style=\'color: orange;\'>P</span><span style=\'color: yellow;\'>I</span><span style=\'color: green;\'>P </span><span style=\'color: blue;\'>1</span><span style=\'color: black;\'>.</span><span style=\'color: darkviolet;\'>7</span>.2], només els bucles {{<tt>ARTICLES, RUBRIQUES, DOCUMENTS</tt>}} i {{<tt>SITES</tt>}} acceptaven aquest criteri.</quote>
[#doublons_nomme<-]
- {{<code>{doublons</code>}} {<code>xxxx</code>}{{<code>}</code>}} a partir de <span style=\'color: #fa9a00;\'>[SPIP 1.8]</span>, es poden tenir diversos criteris <code>{doublons}</code> independents. Els bucles que tinguin <code>{doublons rouge}</code> no tindran cap incidència sobre els bucles que tinguin <code>{doublons bleu}</code> com a criteri.
[#exclus<-]
- {{<code>{exclus}</code>}} permet excloure del resultat l\'element (article, breu, secció, etc.) en el qual ja ens trobem. Per exemple, quan publiquem els articles continguts en una mateixa secció, no volem publicar un enllaç cap a l\'article en el que ja ens trobem.
[#critere_in<-]
- <HTML><TT><B>{</B><I>xxxx</I><B> IN </B><I>a,b,c,d,...</I><B>}</B></TT></HTML> a partir de <span style=\'color: #fa9a00;\'>[SPIP 1.8]</span>, limita la presentació als resultats que tinguin el criteri {xxxx} igual a {a, b, c} {{o}} {d.} Els resultats són ordenats segons l\'ordre indicat (excepte per demanda explícita d\'un altre criteri d\'ordre). També és possible seleccionar cadenes de caràcters, per exemple amb <code>{titre IN \'Chine\', \'Japon\'}</code>.
Amb
[->3369], les etiquetes són reconegudes en els arguments d\'IN, i sobretot l\'etiqueta <TT>ENV</TT>, a la que se li apliquen els filtres d\'anàlisi per assegurar que l\'ordre SQL s\'escriurà bé. De forma derogatòria, Spip verificarà si l\'argument d\' <TT>ENV</TT> apunta cap a una taula (venint per exemple d\'entrades de formulari l\'atribut de les quals <tt>name</tt> s\'acaba per <tt>[]</tt>). Si aquest és el cas, i si els filtres d\'anàlisi han estat desactivats sufixant aquesta etiqueta per una doble estrella, llavors cada element de la taula serà considerat com argument d\'IN, aplicant Spip els filtres de seguretat damunt de cadascun d\'ells.
L\'esquelet estàndard <tt>formulaire_forum_previsu</tt> subministra un exemple d\'ús amb un bucle MOTS que té el criteri <HTML><tt>{id_mot IN #ENV**{ajouter_mot}}</tt></HTML>: aquest bucle selecciona només les paraules clau que pertanyen a un conjunt indicat dinàmicament. Aquí, aquest conjunt haurà estat construit pel formulari de l\'esquelet estàndard <tt>choix_mots</tt>, el qual utilitza atributs <tt>name=ajouter_mot[]</tt>.
- <HTML><TT><B>{</B><I>a</I><B>,</B><I>b</I><B>}</B></TT></HTML> on {a} i {b} són xifres. Aquest criteri permet limitar el número de resultats. {a} indica el resultat a partir del qual es comença la visualització (atenció, el primer resultat porta el número 0 - zero) ; {b} indica el número de resultats mostrats.
Per exemple <HTML><TT>{0,10}</TT></HTML> mostra els deu primers resultats; <HTML><TT>{4,2}</TT></HTML> mostra els dos resultats a partir del cinquè (inclòs).
<HTML><TT><B>{debut_</B><I>xxx</I><B>,</B><I>b</I><B>}</B></TT></HTML> és una variant molt elaborada del criteri anterior. Permet fer començar la limitació dels resultats per una variable passada per l’URL (aquesta variable reemplaça així la {a} que se li indicava anteriorment). És un funcionament una mica complex, però afortunadament no es necessari fer-la servir gaire sovint.
La variable passada per l’URL comença forçosament per <TT>debut_xxx</TT> (on {xxx} és una paraula escollida pel webmestre). D’aquesta manera, per una pàgina que té com URL:
<HTML><TT>spip.php?page=petition&id_article=13&debut_signatures=200</TT></HTML>
amb un esquelet <TT>(petition.html)</TT> que conté, per exemple:
<cadre><BOUCLE_signatures(SIGNATURES){id_article}{debut_signatures,100}></cadre>
obtindrem la llista de 100 signatures a partir de la 201[[<recorda> el primer resultat té el número 0, per tant el resultat 200 representa realment la signatura número 201]]. Amb l’URL:
<HTML><TT>spip.php?page=petition&id_article=13&debut_signatures=300</TT></HTML>
obtindríem la llista de 100 signatures a partir de la 301[[<recorda>]].
- <HTML><TT><B>{</B><I>a</I><B>,n-</B><I>b</I><B>}</B></TT></HTML> a partir de <span style=\'color: #fa9a00;\'>[SPIP 1.8]</span>, és una variant de <code>{a,b}</code> la que limita la publicació en funció del número de resultats dins el bucle. {a} és el resultat a partir del qual començar a fer la publicació; {b} indica el número de resultats a {{no mostrar}} al final del bucle.
<code>{0,n-10}</code> mostrarà tots els resultats del bucle excepte els 10 últims.
- <HTML><TT><B>{n-</B><I>a</I><B>,</B><I>b</I><B>}</B></TT></HTML> a partir de <span style=\'color: #fa9a00;\'>[SPIP 1.8]</span>, és el que penja de <code>{a, n-b}</code>. Es limita la publicació a {b} resultats després del {a}<sup>e</sup> resultat del bucle.
Per exemple: <code>{n-20,10}</code> mostrarà 10 resultats partint del 20<sup>è</sup> resultat abans del final del bucle.
- <HTML><TT><B>{</B><I>a</I><B>/</B><I>b</I><B>}</B></TT></HTML> on {a} i {b} són xifres. Aquest criteri permet mostrar una part {a} (proporcionalment) dels resultats en relació al nombre total «porcions» {b}.
Per exemple: <HTML><TT>{1/3}</TT></HTML> mostra el primer terç dels resultats. Aquest criteri és útil, sobretot, per presentar llistes en diverses columnes. Per obtenir una visualització en dues columnes, hem de crear un primer bucle, dins d’una cel·la d’una taula, amb el criteri <code>{1/2}</code> (la primera meitat dels resultats); després mostrarem un segon bucle dins una nova cel·la, amb el criteri <code>{2/2}</code> (la segona meitat dels resultats).
{Atenció}. La utilització del [criteri <code>{doublons}</code>->#doublons] amb aquest criteri és perillós. Per exemple:
<cadre>
<BOUCLE_prem(ARTICLES){id_rubrique}{1/2}{doublons}>
<li> #TITRE
</BOUCLE_prem>
<BOUCLE_deux(ARTICLES){id_rubrique}{2/2}{doublons}>
<li> #TITRE
</BOUCLE_deux>
</cadre>
no mostrarà tots els articles de la secció! Imaginem, per exemple, que hi ha un total de 20 articles a la nostra secció. El BOUCLE_prem mostrarà la primera meitat dels articles, és a dir els 10 primers, i impedirà (com a conseqüència de <tt><code>{doublons}</code></tt>) de tornar-los a utilitzar. El BOUCLE_deux, per la seva part, recuperarà la segona meitat dels articles d’aquesta secció {que encara no s’han mostrat} pel BOUCLE_prem; o sigui, la meitat dels 10 articles següents, és a dir els 5 últims articles de la secció. Haurem « perdut », per tant, 5 articles en aquesta operació...
{{{Visualització {entre} els resultats}}}
<tt>{{<code>{</code>}}"{inter}"{{<code>}</code>}}</tt> permet indicar un codi HTML (aquí, {inter}) inserit {entre} els resultats del bucle. Per exemple, per separar una llista d’autors per una coma, ho farem de la manera següent:
<cadre><BOUCLE_auteurs(AUTEURS){id_article}{","}></cadre>
{{{Divers}}}
{{<code>{logo}</code>}} permet seleccionar només els articles (o seccions, etc) que disposin d\'un logo. Funciona també en el bucle (HIERARCHIE). El criteri invers <code>{!logo}</code> llista els objectes que no tenen logo.';
}
?>
[(#REM)
On cherche un article avec un document en note dans le texte,
et on veut qu'il soit pris par {doublons}
cf. http://trac.rezo.net/trac/spip/ticket/779
]
<BOUCLE_r(ARTICLES){texte==[[][[].*<doc[0-9]+>.*[]][]]}{statut==.}{0,1}>
#SET{ida,#ID_ARTICLE}
#SET{idd,#TEXTE*|replace{^.*\x5b\x5b.*<doc}|replace{>.*$}|intval}
</BOUCLE_r>
<BOUCLE_d(DOCUMENTS){id_document=#GET{idd}}>
<BOUCLE_a(ARTICLES){id_article=#GET{ida}}{statut==.}>
[(#TEXTE|?)]
</BOUCLE_a>
<BOUCLE_test(DOCUMENTS){id_document}{doublons}>
erreur, _test n'a pas doublonne ! (#ID_DOCUMENT)
</BOUCLE_test>
OK #_d:ID_DOCUMENT
<//B_test>
</BOUCLE_d>
[(#REM|creer_article_a_doublons_notes)]
<//B_d>
<?php
/*
Creation article de test pour doublons_notes.html
On cherche un document, on le met dans la note d'un texte,
*/
function creer_article_a_doublons_notes() {
$res = spip_query("SELECT id_document from spip_documents order by rand() limit 1");
list($doc) = array_values(sql_fetch($res));
spip_query("REPLACE spip_articles (id_article, titre, statut, texte) VALUES (-1, 'test pour doublons_notes.html', 'prepa', 'hello [[ xx <doc$doc> ]].')");
}
?>
<?php
$test = 'echappe_html';
require '../test.inc';
include_spip('inc/texte');
$marque = '<span class="base64" title=\'QQ==\' ></span>';
$essais['simple imbriqué'] = array(
'avant 1' . $marque . 'apres 1</code>apres 2',
'avant 1<code class="php"> avant 2<code>le code</code>apres 1</code>apres 2'
);
$essais['complexe imbriqué'] = array(
<<<EOT
{{{code class="php"}}}
avant blah
$marque
apres blah et avant php
$marque
{{{code tout court}}}
$marque
{{{Tu vois ?}}}
Voilà , $marque</code>
On peut croire que c'est embétant , faut mettre une div autour pour encadrer , mais cela permet d'orienter geshi en cours de route comme dans [Compte à rebours (revisited)->article6]
EOT
,
<<<EOT
{{{code class="php"}}}
avant blah
<code class="blah">
blah in
balh 2
</code>
apres blah et avant php
<code class="php telecharge">
<?php
function uncomment(\$source) {
return preg_replace(
'#(?:/\*(?:(?R)|.)*\*/|//.*$)|(([\'"])(?:.*)(?<!\\\\)\2|([^\'"/]+))#msU',
"$1", \$source);
}
?>
</code>
{{{code tout court}}}
<code>
<?php
function uncomment(\$source) {
return preg_replace(
'#(?:/\*(?:(?R)|.)*\*/|//.*$)|(([\'"])(?:.*)(?<!\\\\)\2|([^\'"/]+))#msU',
"$1", \$source);
}
?>
</code>
{{{Tu vois ?}}}
Voilà , <code><code class="xxx">insere tout avec des <br /> , pas de <div class="spip_code"></code></code>
On peut croire que c'est embétant , faut mettre une div autour pour encadrer , mais cela permet d'orienter geshi en cours de route comme dans [Compte à rebours (revisited)->article6]
EOT
);
$essais['unicode sans rien'] = array(
"azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-"
,
"azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-azerty小さくてもグローバルなケベックの村-"
);
$essais['sans rien'] = array(
"astuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolos"
,
"astuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolosastuce & travaux de mode rigolos"
);
$essais['code sans imbrication'] = array(
'avant 1' . $marque . 'apres 2'
,
'avant 1<code class="php"> avant 2 code le code code apres 1</code>apres 2'
);
$essais['pourriture'] = array(
<<<EOT
Le code mis en $marque ou en $marque peut lui même contenir $marque ou $marque ...
$marque
Je voudrais présenter l'usage du plugin coloration_code qui fournit une extension à geshi : la classe "spip".
Je mets donc :
$marque
Ici présenté avec le $marque d'origine de spip
Mais si je mets le même texte dans $marque , voilà le résultat:
$marque
Voilà c'est corrigé, [->http://trac.rezo.net/trac/spip-zone/changeset/3823] , mais on s'est aperçu que le problème est le même pour le &lt;code> d'origine de spip. (voir plus bas)
En fait, l'expression régulière (regexp) utilisée par le plugin pour récupérer les morceaux de code à colorer devrait être récursive !
$marque est insuffisant.
Il faut un truc comme:
<div style="color: red;">
$marque
</div>
Les différences:
- la balise de fermeture est recherchée avec \1 , c'est à dire cadre ou code comme trouvé en début d'espression
- pour l'intérieur (le code en lui-même) on ne cherche pas seulement .* (n'importe quoi) mais (?:((?R))|.)* : le motif complet recherché , soit un &lt;code>...&lt/code> ou cadre imbriqué , ou n'importe quoi (.) . C'est une regexp récursive.
- une amélioration supplémentaire : le paramètre class peut être donné entre simple ou double apostrophes.
- le texte dans le tag après class="xxx" est capté ce qui pourra permettre des extensions futures, comme insérer des attributs supplémentaires au code html fabriqué.
Essai de code dans code (au lieu de cadre comme tout en haut)
$marque
et le tour est joué
</code>
Donc comme l'ancien coloration_code, le &lt;/code> est mangé et "et le tour est joué" apparait hors-code.
EOT
,
<<<EOT
Le code mis en <code><code></code> ou en <code><cadre></code> peut lui même contenir <code><code></code> ou <code><cadre></code> ...
<code class="xxx">
ça 'xiste pô
</code>
Je voudrais présenter l'usage du plugin coloration_code qui fournit une extension à geshi : la classe "spip".
Je mets donc :
<cadre>
Pour insérer du code coloré, il suffit de rajouter {class="xxx"} au tag code de spip:
<code class="php">
// mon morceau de php
\$variable = "blah";
// ...
</code>
et le tour est joué
</cadre>
Ici présenté avec le <code><cadre></code> d'origine de spip
Mais si je mets le même texte dans <code><cadre class="spip"></code> , voilà le résultat:
<cadre class="spip">
Pour insérer du code coloré, il suffit de rajouter {class="xxx"} au tag code de spip:
<code class="php">
// mon morceau de php
\$variable = "blah";
// ...
</code>
et le tour est joué
</cadre>
Voilà c'est corrigé, [->http://trac.rezo.net/trac/spip-zone/changeset/3823] , mais on s'est aperçu que le problème est le même pour le &lt;code> d'origine de spip. (voir plus bas)
En fait, l'expression régulière (regexp) utilisée par le plugin pour récupérer les morceaux de code à colorer devrait être récursive !
<code>
',<(cadre|code)[[:space:]]+class="(.*)"[[:space:]]*>(.*)</(cadre|code)>,Uims'
</code> est insuffisant.
Il faut un truc comme:
<div style="color: red;">
<code>
',<(cadre|code)[[:space:]]+class=("|\')(.*)\2([^>])*>((?:((?R))|.)*)</\1>,Uims'
</code>
</div>
Les différences:
- la balise de fermeture est recherchée avec \1 , c'est à dire cadre ou code comme trouvé en début d'espression
- pour l'intérieur (le code en lui-même) on ne cherche pas seulement .* (n'importe quoi) mais (?:((?R))|.)* : le motif complet recherché , soit un &lt;code>...&lt/code> ou cadre imbriqué , ou n'importe quoi (.) . C'est une regexp récursive.
- une amélioration supplémentaire : le paramètre class peut être donné entre simple ou double apostrophes.
- le texte dans le tag après class="xxx" est capté ce qui pourra permettre des extensions futures, comme insérer des attributs supplémentaires au code html fabriqué.
Essai de code dans code (au lieu de cadre comme tout en haut)
<code>
Pour insérer du code coloré, il suffit de rajouter {class="xxx"} au tag code de spip:
<code class="php">
// mon morceau de php
\$variable = "blah";
// ...
</code>
et le tour est joué
</code>
Donc comme l'ancien coloration_code, le &lt;/code> est mangé et "et le tour est joué" apparait hors-code.
EOT
);
function echappe($regs) {
return 'A';
}
function traiter_echap_html($regs) {
return echappe($regs);
}
function traiter_echap_code($regs) {
return echappe($regs);
}
function traiter_echap_cadre($regs) {
return echappe($regs);
}
function traiter_echap_frame($regs) {
return echappe($regs);
}
function traiter_echap_script($regs) {
return echappe($regs);
}
// hop ! on y va
$err = tester_fun('echappe_html', $essais);
// si le tableau $err est pas vide ca va pas
if ($err) {
echo ('<dl>' . join('', $err) . '</dl>');
} else {
echo "OK";
}
// essai de perf simple
$repeter = _request('repeter');
while ($repeter--) {
foreach ($essais as $ess) {
extraire_attribut($ess[1], $ess[2]);
}
}
?>
<?php
$test = 'liens';
require '../test.inc';
include_spip('inc/texte');
include_spip('inc/lang');
$s = spip_query("SELECT * FROM spip_articles WHERE statut='publie' AND lang>'' LIMIT 0,1");
$t = sql_fetch($s);
if ($t['lang'] == 'eo')
lang_select('fa');
else
lang_select('eo');
$p0 = '[->'.$t['id_article'].']';
$p1 = '[bla {blabla}->url]'; // blabla ne peut pas etre un hreflang
$p2 = '[bla{en}->url]';
$p3 = '[bla|bulle de savon{eo}->url]';
$p4 = '[bla|fa->url]'; // fa est hreflang ET title
$p5 = '[bla|bulle de savon->url]';
$p6 = '[<multi>[fr]X[eo]Y[fa]Z</multi>->url]';
$p7 = '[uneancre<-] a [->www.monsite.tld]';
$p8 = 'un superbe www.monsite.tld, pas mal';
$p9 = 'un superbe http://www.monsite.tld, pas mal';
$p10 = 'un superbe https://www.monsite.tld, pas mal';
$p11 = '<flv|url=http://rezo.net/>';
if (extraire_attribut(propre($p0), 'hreflang') !== $t['lang'])
$err[] = "hreflang automatique errone dans $p0 : ".PtoBR(propre($p0));
if (extraire_attribut(propre($p1), 'href') !== 'url')
$err[] = "url mal extrait de $p1";
if (extraire_attribut(propre($p1), 'hreflang') == 'blabla')
$err[] = "hreflang errone dans $p1";
if (supprimer_tags(propre($p1)) !== 'bla blabla')
$err[] = "texte du lien abime dans $p1";
if (extraire_attribut(propre($p2), 'href') !== 'url')
$err[] = "url mal extrait de $p2";
if (extraire_attribut(propre($p2), 'hreflang') !== 'en')
$err[] = "hreflang errone dans $p2";
if (supprimer_tags(propre($p2)) !== 'bla')
$err[] = "texte du lien abime dans $p2";
if (extraire_attribut(propre($p3), 'href') !== 'url')
$err[] = "url mal extrait de $p3";
if (extraire_attribut(propre($p3), 'hreflang') !== 'eo')
$err[] = "hreflang errone dans $p3";
if (extraire_attribut(propre($p3), 'title') !== 'bulle de savon')
$err[] = "title errone dans $p3";
if (supprimer_tags(propre($p3)) !== 'bla')
$err[] = "texte du lien abime dans $p3";
if (extraire_attribut(propre($p4), 'href') !== 'url')
$err[] = "url mal extrait de $p4";
if (extraire_attribut(propre($p4), 'hreflang') !== 'fa')
$err[] = "hreflang errone dans $p4";
if (extraire_attribut(propre($p4), 'title') !== 'fa')
$err[] = "title errone dans $p4";
if (supprimer_tags(propre($p4)) !== 'bla')
$err[] = "texte du lien abime dans $p4";
if (extraire_attribut(propre($p5), 'href') !== 'url')
$err[] = "url mal extrait de $p5";
if (extraire_attribut(propre($p5), 'hreflang') !== NULL)
$err[] = "hreflang errone dans $p5";
if (extraire_attribut(propre($p5), 'title') !== 'bulle de savon')
$err[] = "title errone dans $p5";
if (supprimer_tags(propre($p5)) !== 'bla')
$err[] = "texte du lien abime dans $p5";
if (supprimer_tags(propre($p6)) !== 'Y')
$err[] = "multi abime dans $p6";
# (('<multi>[fr]X[en]Y</multi>')); => pre_typo
if ('http://www.monsite.tld'
!== $a = extraire_attribut(array_pop(extraire_balises(propre($p7), 'a')), 'href'))
$err[] = $a.': erreur sur le lien '.$p7;
if ('http://www.monsite.tld'
!== $a =extraire_attribut(extraire_balise(propre($p8), 'a'), 'href'))
$err[] = $a.': erreur sur le lien '.$p8;
if ('http://www.monsite.tld'
!== $a =extraire_attribut(extraire_balise(propre($p9), 'a'), 'href'))
$err[] = $a.': erreur sur le lien '.$p9;
if ('https://www.monsite.tld'
!== $a =extraire_attribut(extraire_balise(propre($p10), 'a'), 'href'))
$err[] = $a.': erreur sur le lien '.$p10;
if ('https://www.monsite.tld'
!== $a =extraire_attribut(extraire_balise(propre($p10), 'a'), 'href'))
$err[] = $a.': erreur sur le lien '.$p10;
if ("<p><flv|url=http://rezo.net/></p>"
!== $a = propre($p11))
$err[] = $a.': erreur sur le modele '.$p11;
if ($err)
var_dump($err);
else
echo "OK";
?>
[(#REM)
tester # NOTES et ses particularismes
]
[(#REM) une note appelee explicitement ]
[(#EVAL{'"a".chr(91).chr(91)."<b>c".chr(93).chr(93)'}|propre|?)]
[(#NOTES|supprimer_tags|match{^.b. c$}|?{'',#SET{err,'erreur note &lt;b>'}})]
[(#REM) une note appelee explicitement <a>]
[(#EVAL{'"eh".chr(91).chr(91)."<a>oh".chr(93).chr(93)'}|propre|?)]
[(#NOTES|PtoBR|match{^.<a.*>a</a>.\s+oh$}|?{'',#SET{err,'erreur note &lt;a>'}})]
[(#REM) une note appelee explicitement <a> avec un lien dedans]
[(#EVAL{'"ki".chr(91).chr(91)."<a><a href=\"#test\">uh</a>".chr(93).chr(93)'}|propre|?)]
[(#NOTES|PtoBR|match{^.<a.*>a</a>.\s}|?{'',#SET{err,'erreur note &lt;a&gt; avec lien'}})]
[(#REM) une note appelee explicitement vide ]
[(#EVAL{'"a".chr(91).chr(91)."<>d".chr(93).chr(93)'}|propre|?)]
[(#NOTES|supprimer_tags|match{^d$}|?{'',#SET{err,'erreur note &lt;d>'}})]
[(#REM) une note appelee explicitement avec une espace au debut ]
[(#EVAL{'"a".chr(91).chr(91)." <e>f".chr(93).chr(93)'}|propre|?)]
[(#NOTES|supprimer_tags|match{^.e. f$}|?{'',#SET{err,'erreur note &lt;e>'}})]
[(#REM) une note appelee avec une construction html equilibree ]
[(#EVAL{'"g".chr(91).chr(91)." <b>h</b>".chr(93).chr(93)'}|propre|?)]
[(#NOTES|supprimer_tags|match{^.1. +h$}|?{'',#SET{err,'erreur note &lt;g>'}})]
[(#REM) une note appelee avec un caractere sensible ]
[(#EVAL{'"j".chr(91).chr(91)." <*>k".chr(93).chr(93)'}|propre|?)]
[(#NOTES|PtoBR|match{^.<a.*>\*</a>.\s+k$}|?{'',#SET{err,'erreur note &lt;j>'}})]
[(#GET{err}|sinon{OK})]
<?php
$test = 'traiter_raccourcis';
require '../test.inc';
// ces tests sont prevus pour la variable de personnalisation :
$GLOBALS['toujours_paragrapher'] = false;
include_spip('inc/texte');
// trois tests un peu identiques sur <br />...
$essais['div'] = array(
'<div>titi<br />toto</div><br />tata',
'<div>titi<br />toto</div><br />tata'
);
$essais['span'] = array(
'<span>titi<br />toto</span><br />tata',
'<span>titi<br />toto</span><br />tata'
);
$essais['table'] = array(
'<table><tr><td>titi<br />toto</td></tr></table><br />tata',
'<table><tr><td>titi<br />toto</td></tr></table><br />tata'
);
// melanges de \n et de <br />
$essais['\n_x1_mixte1'] = array(
"titi\n<br />toto<br />",
"titi\n<br />toto<br />"
);
$essais['\n_x1_mixte2'] = array(
"titi\n<br />\ntoto<br />",
"titi\n<br />\ntoto<br />"
);
// des tirets en debut de texte
$essais['tirets1'] = array(
"&mdash;&nbsp;chose\n<br />&mdash;&nbsp;truc",
"-- chose\n-- truc"
);
$GLOBALS['puce'] = '-';
$essais['tirets2'] = array(
"-&nbsp;chose\n<br />-&nbsp;truc",
"- chose\n- truc"
);
// ligne horizontale
$essais['lignehorizontale'] = array(
"\n<hr class=\"spip\" />\n",
"\n----\n"
);
// hop ! on y va
$err = tester_fun('traiter_raccourcis', $essais);
if (!preg_match($c = ",<p\b.*?>titi</p>\n\n<p\b.*?>toto</p>,",
$b = propre( $a = "titi\n\ntoto")))
$err[] = htmlentities ("$a -- $b -- $c");
if (!preg_match(",<p\b.*?>titi</p>\n\n<p\b.*?>toto<br /></p>,",
propre("titi\n\n<br />toto<br />")))
$err[] = 'erreur 2';
if (!strpos(propre("Ligne\n\n<br class=\"n\" />\n\nAutre"), '<br class="n" />'))
$err[] = "erreur le &lt;br class='truc'> n'est pas preserve";
// si le tableau $err est pas vide ca va pas
if ($err) {
foreach($err as $i=>$val) $err[$i] = str_replace("\n", '\n', $val);
echo ('<dl>' . join('', $err) . '</dl>');
} else {
echo "OK";
}
?>
<?php
$test = 'traiter_tableau';
require '../test.inc';
include_spip('inc/texte');
// trois tests un peu identiques sur <br />...
$essais['caption seul'] = array(
array('preg_match',',<caption>\s*titre de mon tableau\s*</caption>,i',true),
'|| titre de mon tableau||
|{{Colonne 0}} | {{Colonne 1}} | {{Colonne 2}} | {{Colonne 3}} | {{Colonne 4}} |
| {{Bourg-les-Valence}} | 10,39 | 20,14 | 46,02 | 15,99 |
| {{Valence}} | 16,25 | 23,31 | 49,21 | 13,43 |
| {{Romans}} | 14,09 | 20,54 | 67,85 | 17 |
| {{Montelimar}} | 20,15 | 26,43 | 70,21 | 16,82 |
| {{Bourg-de-Peage}} | 13,22 | 30 | 50 | 14,67 |'
);
$essais['caption'] = array(
array('preg_match',',<caption>\s*titre de mon tableau\s*</caption>,i',true),
'|| titre de mon tableau | resume de mon tableau ||
|{{Colonne 0}} | {{Colonne 1}} | {{Colonne 2}} | {{Colonne 3}} | {{Colonne 4}} |
| {{Bourg-les-Valence}} | 10,39 | 20,14 | 46,02 | 15,99 |
| {{Valence}} | 16,25 | 23,31 | 49,21 | 13,43 |
| {{Romans}} | 14,09 | 20,54 | 67,85 | 17 |
| {{Montelimar}} | 20,15 | 26,43 | 70,21 | 16,82 |
| {{Bourg-de-Peage}} | 13,22 | 30 | 50 | 14,67 |'
);
$essais['summary'] = array(
array('preg_match',',<table\s[^>]*summary=([\'"])\s*resume de mon tableau\s*(\\1)[^>]*>,i',true),
'|| titre de mon tableau | resume de mon tableau ||
|{{Colonne 0}} | {{Colonne 1}} | {{Colonne 2}} | {{Colonne 3}} | {{Colonne 4}} |
| {{Bourg-les-Valence}} | 10,39 | 20,14 | 46,02 | 15,99 |
| {{Valence}} | 16,25 | 23,31 | 49,21 | 13,43 |
| {{Romans}} | 14,09 | 20,54 | 67,85 | 17 |
| {{Montelimar}} | 20,15 | 26,43 | 70,21 | 16,82 |
| {{Bourg-de-Peage}} | 13,22 | 30 | 50 | 14,67 |'
);
$essais['thead simple'] = array(
array('preg_match',',<thead>\s*<tr[^>]*>(:?<th[^>]*>.*</th>){5}\s*</tr>\s*</thead>,Uims',true),
'|| titre de mon tableau | resume de mon tableau ||
|{{Colonne 0}} | {{Colonne 1}} | {{Colonne 2}} | {{Colonne 3}} | {{Colonne 4}} |
| {{Bourg-les-Valence}} | 10,39 | 20,14 | 46,02 | 15,99 |
| {{Valence}} | 16,25 | 23,31 | 49,21 | 13,43 |
| {{Romans}} | 14,09 | 20,54 | 67,85 | 17 |
| {{Montelimar}} | 20,15 | 26,43 | 70,21 | 16,82 |
| {{Bourg-de-Peage}} | 13,22 | 30 | 50 | 14,67 |'
);
$essais['thead avec une colonne vide'] = array(
array('preg_match',',<thead>\s*<tr[^>]*>(:?<th[^>]*>.*</th>){5}\s*</tr>\s*</thead>,Uims',true),
'|| titre de mon tableau | resume de mon tableau ||
| | {{Colonne 1}} | {{Colonne 2}} | {{Colonne 3}} | {{Colonne 4}} |
| {{Bourg-les-Valence}} | 10,39 | 20,14 | 46,02 | 15,99 |
| {{Valence}} | 16,25 | 23,31 | 49,21 | 13,43 |
| {{Romans}} | 14,09 | 20,54 | 67,85 | 17 |
| {{Montelimar}} | 20,15 | 26,43 | 70,21 | 16,82 |
| {{Bourg-de-Peage}} | 13,22 | 30 | 50 | 14,67 |'
);
$essais['thead avec une colonne vide et un retour ligne'] = array(
array('preg_match',',<thead>\s*<tr[^>]*>(:?<th[^>]*>.*</th>){5}\s*</tr>\s*</thead>,Uims',true),
'|| titre de mon tableau | resume de mon tableau ||
| | {{Colonne 1}} | {{Colonne 2}} | {{Colonne 3
_ avec retour ligne}} | {{Colonne 4}} |
| {{Bourg-les-Valence}} | 10,39 | 20,14 | 46,02 | 15,99 |
| {{Valence}} | 16,25 | 23,31 | 49,21 | 13,43 |
| {{Romans}} | 14,09 | 20,54 | 67,85 | 17 |
| {{Montelimar}} | 20,15 | 26,43 | 70,21 | 16,82 |
| {{Bourg-de-Peage}} | 13,22 | 30 | 50 | 14,67 |'
);
$essais['thead errone'] = array(
array('preg_match',',<thead>\s*<tr[^>]*>(:?<th[^>]*>.*</th>){5}\s*</tr>\s*</thead>,Uims',false),
'|| titre de mon tableau | resume de mon tableau ||
|{{Colonne 0}} | {Colonne 1}} | {{Colonne 2}} | {{Colonne 3}} | {{Colonne 4}} |
| {{Bourg-les-Valence}} | 10,39 | 20,14 | 46,02 | 15,99 |
| {{Valence}} | 16,25 | 23,31 | 49,21 | 13,43 |
| {{Romans}} | 14,09 | 20,54 | 67,85 | 17 |
| {{Montelimar}} | 20,15 | 26,43 | 70,21 | 16,82 |
| {{Bourg-de-Peage}} | 13,22 | 30 | 50 | 14,67 |'
);
// hop ! on y va
$err = tester_fun('traiter_raccourcis', $essais);
// si le tableau $err est pas vide ca va pas
if ($err) {
echo ('<dl>' . join('', $err) . '</dl>');
} else {
echo "OK";
}
?>
[(#REM)
La fonction creer_rubrique_nommee('a/b/c/d') creee une arborescence et renvoie l'id_rubrique
Ici on en prend 10 au pif et on essaie de voir si on retombe bien dessus (attention, le
test est potentiellement "destructeur" (ou plutot "constructeur", puisqu'il creera des
rubriques superflues) si la fonction echoue, ou si deux rubriques soeurs portent le meme titre).
]
<BOUCLE_r(RUBRIQUES){par hasard}{0,10}>
[(#SET{hier,''})]
<BOUCLE_h(HIERARCHIE){tout}>
[(#SET{hier,[(#GET{hier})][/(#TITRE**)]})]
</BOUCLE_h>
[(#GET{hier}|creer_rubrique_nommee|=={#ID_RUBRIQUE}|?{'',
[(#GET{hier}|htmlspecialchars)]
[(#SET{bug,1})]
})]
</B_h>
</BOUCLE_r>
[(#GET{bug}|?{'','OK'})]
<?php
require '../test.inc';
include 'inc-sql_datas.inc';
include_spip('base/abstract_sql');
/*
* Creation/suppression/analyse de tables dans la base de donnee
*
* Permet de verifier que
* - tous les champs sont correctement ajoutes
* - que les PRIMARY sont pris en compte
* - que les KEY sont prises en compte
*
*/
/*
* Lecture de la description des tables
*/
function test_show_table() {
$tables = test_sql_datas();
$essais = array();
// lire la structure de la table
// la structure doit avoir le meme nombre de champs et de cle
// attention : la primary key DOIT etre dans les cle aussi
foreach ($tables as $t=>$d){
$desc = sql_showtable($t);
$essais["Compter field $t"] = array(count($d['desc']['field']),$desc['field']);
$essais["Compter key $t"] = array($d['desc']['nb_key_attendues'],$desc['key']);
}
$err = tester_fun('count', $essais);
if ($err) {
return '<b>Lecture des structures de table en echec</b><dl>' . join('', $err) . '</dl>';
}
}
$err = "";
// supprimer les eventuelles tables
$err .= test_drop_table();
// creer les eventuelles tables
$err .= test_create_table();
// lire les structures des tables
$err .= test_show_table();
// supprimer les tables
$err .= test_drop_table();
if ($err)
die($err);
echo "OK";
?>
<?php
require '../test.inc';
include 'inc-sql_datas.inc';
include_spip('base/abstract_sql');
/*
* Selection/insertion de tables dans la base de donnee
*
*/
/*
* Teste que le champ "maj" s'actualise bien sur les update
* ainsi que les autres champs !
*
* utilise sql_quote, sql_getfetsel, sql_update et sql_updateq.
*/
function test_maj_timestamp() {
$table = 'spip_test_tintin';
$where = 'id_tintin='.sql_quote(1);
$err = $essais = array();
// lecture du timestamp actuel
$maj1 = sql_getfetsel('maj',$table,$where);
if (!$maj1) {
$err[] = "Le champ 'maj' ($maj1) n'a vraissemblablement pas recu de timestamp a l'insertion";
}
// update
sleep(1); // sinon le timestamp ne change pas !
$texte = 'nouveau texte';
sql_update($table,array('un_texte'=>sql_quote($texte)),$where);
// comparaison timastamp
$maj2 = sql_getfetsel('maj',$table,$where);
if (!$maj2 OR $maj1==$maj2) {
$err[] = "Le champ 'maj' ($maj2) n'a vraissemblablement pas ete mis a jour lors de l'update";
}
// comparaison texte
$texte2 = sql_getfetsel('un_texte',$table,$where);
if (!$texte2 OR $texte2!==$texte){
$err[] = "Le champ 'un_texte' ($texte2) n'est pas correctement rempli a l'update";
}
// idem avec updateq
sleep(1); // sinon le timestamp ne change pas !
$texte = 'encore un nouveau texte';
sql_updateq($table,array('un_texte'=>$texte),$where);
// comparaison timastamp
$maj3 = sql_getfetsel('maj',$table,$where);
if (!$maj3 OR $maj3==$maj2) {
$err[] = "Le champ 'maj' ($maj3) n'a vraissemblablement pas ete mis a jour lors de l'updateq";
}
// comparaison texte
$texte3 = sql_getfetsel('un_texte',$table,$where);
if (!$texte3 OR $texte3!==$texte){
$err[] = "Le champ 'un_texte' ($texte2) n'est pas correctement rempli a l'update";
}
// affichage
if ($err) {
return '<b>Champ maj sur update</b><dl><dd>' . join('</dd><dd>', $err) . '</dd></dl>';
}
}
/*
* Selections diverses selon criteres
* -
*/
function test_selections() {
$err = $essais = array();
$desc = test_sql_datas();
$nb_data = count($desc['spip_test_tintin']['data']);
// selection simple
$res = sql_select("*","spip_test_tintin");
if (($nb = sql_count($res)) != $nb_data){
$err[] = "sql_count ($nb) ne renvoie pas : $nb2 elements";
}
// selection float
$res = sql_select("*","spip_test_tintin",array("un_double>".sql_quote(3)));
$elems = $desc['spip_test_tintin']['data'];
$n=0;
foreach($elems as $a=>$b)
foreach($b as $c=>$d)
if (($c == 'un_double') AND ($d > 3))
$n++;
if (($nb = sql_count($res)) != $n){
$err[] = "sql_count ($nb) ne renvoie pas : $n elements";
}
// selection REGEXP
// ! chiffre en dur !
$res = sql_select("*","spip_test_tintin",array("un_varchar REGEXP ".sql_quote("^De")));
if (($nb = sql_count($res)) != 1) {
$err[] = "sql_select comprends mal REGEXP ($nb resultats au lieu de 1)";
}
// selection LIKE
// ! chiffre en dur !
$res = sql_select("*","spip_test_tintin",array("un_varchar LIKE ".sql_quote("De%")));
if (($nb = sql_count($res)) != 1) {
$err[] = "sql_select comprends mal LIKE ($nb resultats au lieu de 1)";
}
// selection array(champs)
$res = sql_fetsel(array("id_tintin","un_varchar"),"spip_test_tintin");
if (!isset($res['id_tintin']) OR !isset($res['un_varchar'])) {
$err[] = "sql_select comprends mal une selection : array(champ1, champ2)";
}
// selection array(champs=>alias)
$res = sql_fetsel(array("id_tintin AS id","un_varchar AS vchar"),"spip_test_tintin");
if (!isset($res['id']) OR !isset($res['vchar'])) {
$err[] = "sql_select comprends mal une selection : array(champ1 AS alias1, champ2 AS alias2)";
}
// selection avec sql_multi
$res = sql_select(array("id_tintin", sql_multi("grrrr",'fr')),"spip_test_milou","","","multi");
if (!(sql_count($res) == $nb_data)) {
$err[] = "sql_multi mal interprete";
}
$rs = sql_fetch($res); $id1 = $rs['id_tintin'];
$rs = sql_fetch($res); $id2 = $rs['id_tintin'];
$rs = sql_fetch($res); $id3 = $rs['id_tintin'];
if ($id1!=3 AND $id2!=2 AND $id3!=1){
$err[] = "sql_multi order by multi rate : ordre ($id1, $id2, $id3) - attendu : (3, 2, 1)";
}
// le bon texte avec multi
foreach (array('fr'=>'Crac','en'=>'Krack') as $lg=>$res) {
$multi = sql_getfetsel(sql_multi("grrrr",$lg),"spip_test_milou","id_milou=".sql_quote(2));
if (!($multi == ($res))) {
$err[] = "sql_multi $lg mal rendu : retour : ".htmlentities($multi).", attendu : ".htmlentities($res);
}
}
// le bon texte avec multi et accents
foreach (array('fr'=>'Aérien','en'=>'Aérieny') as $lg=>$res) {
$multi = sql_getfetsel(sql_multi("alcool",$lg),"spip_test_haddock","id_haddock=".sql_quote(2));
if (!($multi == ($res))) {
$err[] = "sql_multi $lg mal rendu : retour : ".htmlentities(utf8_decode($multi)).", attendu : ".htmlentities(utf8_decode($res));
}
}
// affichage
if ($err) {
return '<b>Selections</b><dl><dd>' . join('</dd><dd>', $err) . '</dd></dl>';
}
}
/*
* Selections diverses entre plusieurs tables
* -
*/
function test_selections_entre_table() {
$err = $essais = array();
// selection 2 tables
// ! nombre en dur !
$res = sql_select(
array("spip_test_tintin.id_tintin","spip_test_milou.id_milou"),
array("spip_test_tintin", "spip_test_milou"),
array("spip_test_milou.id_tintin=spip_test_tintin.id_tintin"));
if (!($nb=sql_count($res) == 3)) {
$err[] = "selection sur 2 tables avec where en echec : attendu 3 reponses, presntes : $nb";
}
// selection 2 tables avec alias =>
// ! nombre en dur !
$res = sql_select(
array("a.id_tintin AS x","b.id_milou AS y"),
array("a"=>"spip_test_tintin", "b"=>"spip_test_milou"),
array("a.id_tintin=b.id_tintin"));
if (!($nb=sql_count($res) == 3)) {
$err[] = "From avec alias en echec (3 reponses attendues) - presentes : $nb";
}
// selection 2 tables avec alias AS
// ! nombre en dur !
$res = sql_select(
array("a.id_tintin AS x","b.id_milou AS y"),
array("spip_test_tintin AS a", "spip_test_milou AS b"),
array("a.id_tintin=b.id_tintin"));
if (!(($nb=sql_count($res)) == 3)) {
$err[] = "From avec alias AS en echec (3 reponses attendues) - presentes : $nb";
}
// selection 2 tables avec INNER JOIN + ON
// ! nombre en dur !
$res = sql_select(
array("a.id_tintin AS x","b.id_milou AS y"),
array("spip_test_tintin AS a INNER JOIN spip_test_milou AS b ON (a.id_tintin=b.id_tintin)"));
if (!(($nb=sql_count($res)) == 3)) {
$err[] = "Echec INNER JOIN + ON (3 reponses attendues, presentes : $nb)";
}
// selection 2 tables avec LEFT JOIN + ON
// ! nombre en dur !
$res = sql_select(
array("a.id_tintin AS x","b.id_milou AS y"),
array("spip_test_tintin AS a LEFT JOIN spip_test_milou AS b ON (a.id_tintin=b.id_tintin)"));
if (!(($nb=sql_count($res)) == 4)) {
$err[] = "Echec LEFT JOIN + ON (4 reponses attendues, presentes : $nb)";
}
// selection 2 tables avec jointure INNER JOIN + USING
// ! nombre en dur !
// SQLite 2 se plante : il ne connait pas USING (enleve de la requete,
// et du coup ne fait pas correctement la jointure)
$res = sql_select(
array("a.id_tintin AS x","b.id_milou AS y"),
array("spip_test_tintin AS a INNER JOIN spip_test_milou AS b USING (id_tintin)"));
if (!(($nb=sql_count($res)) == 3)) {
$err[] = "Echec INNER JOIN + USING (3 reponses attendues, presentes : $nb)";
}
// affichage
if ($err) {
return '<b>Selections multi tables</b><dl><dd>' . join('</dd><dd>', $err) . '</dd></dl>';
}
}
$err="";
// supprimer les eventuelles tables
$err .= test_drop_table();
// creer les eventuelles tables
$err .= test_create_table();
// inserer les donnees dans la table
$err .= test_insert_data();
// test maj timestamp automatique (select, update, comparaison)
// ! il prend 3 secondes volontairement !
$err .= test_maj_timestamp();
// tests de selections
$err .= test_selections();
// tests de selections entre 2 tables et jointures
$err .= test_selections_entre_table();
// supprimer les tables
$err .= test_drop_table();
if ($err)
die($err);
echo "OK";
?>
<?php
require '../test.inc';
include 'inc-sql_datas.inc';
include_spip('base/abstract_sql');
/*
* Update/delete, de tables dans la base de donnee
*
*/
/*
* Updates
*/
function test_update_data() {
$err = $essais = array();
// ajouter un champ
$nb = sql_getfetsel("un_bigint","spip_test_tintin","id_tintin=".sql_quote(1));
sql_update("spip_test_tintin",array("un_bigint"=>"un_bigint+2"));
$nb2 = sql_getfetsel("un_bigint","spip_test_tintin","id_tintin=".sql_quote(1));
if ($nb+2 != $nb2)
$err[] = "sql_update n'a pas fait l'adition ! ($nb + 2 != $nb2)";
// affichage
if ($err) {
return '<b>Updates</b><dl><dd>' . join('</dd><dd>', $err) . '</dd></dl>';
}
}
/*
* Delete
*/
function test_delete_data() {
$err = $essais = array();
// supprimer une colonne
sql_delete("spip_test_tintin","id_tintin=".sql_quote(1));
$nb = sql_countsel("spip_test_tintin");
if ($nb!=2)
$err[] = "sql_delete n'a rate sa suppression de id_tintin=1";
// supprimer une colonne
sql_delete("spip_test_tintin");
$nb = sql_countsel("spip_test_tintin");
if ($nb!=0)
$err[] = "sql_delete n'a rate le vidage de la table spip_test_tintin";
// affichage
if ($err) {
return '<b>Updates</b><dl><dd>' . join('</dd><dd>', $err) . '</dd></dl>';
}
}
$err = "";
// supprimer les eventuelles tables
$err .= test_drop_table();
// creer les eventuelles tables
$err .= test_create_table();
// inserer les donnees dans la table
$err .= test_insert_data();
// mettre a jour les donnees dans la table
$err .= test_update_data();
// supprimer les donnees dans la table
$err .= test_delete_data();
// supprimer les tables
$err .= test_drop_table();
if ($err)
die($err);
echo "OK";
?>
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter